UriComponentsBuilder 是 Spring 提供的一个 UriComponents 类的构建类,通过他可以方便的构建我们请求的 url
org.springframework
spring-web
4.3.14.RELEASE
public static UriComponentsBuilder newInstance();
public static UriComponentsBuilder fromPath(String path);
public static UriComponentsBuilder fromUri(URI uri);
public static UriComponentsBuilder fromUriString(String uri);
public static UriComponentsBuilder fromHttpUrl(String httpUrl);
public static UriComponentsBuilder fromHttpRequest(HttpRequest request);
public static UriComponentsBuilder fromOriginHeader(String origin);
UriComponentsBuilder 提供了7中实例化的方法,看方法名就知道大概的用法了,里面几个方法做了一些其他的处理
这个方法按照字面一些,里面传入的应该是:http://www.baidu.com/ 这样的字符串,打开源码我们发现,里面其实传入的是一个完整的GET请求链接:[协议]://[域名]:[端口]/[路径]?[参数]
public static UriComponentsBuilder fromUriString(String uri) {
Assert.notNull(uri, "URI must not be null");
Matcher matcher = URI_PATTERN.matcher(uri);
if (matcher.matches()) {
UriComponentsBuilder builder = new UriComponentsBuilder();
String scheme = matcher.group(2);
String userInfo = matcher.group(5);
String host = matcher.group(6);
String port = matcher.group(8);
String path = matcher.group(9);
String query = matcher.group(11);
String fragment = matcher.group(13);
boolean opaque = false;
if (StringUtils.hasLength(scheme)) {
String rest = uri.substring(scheme.length());
if (!rest.startsWith(":/")) {
opaque = true;
}
}
builder.scheme(scheme);
if (opaque) {
String ssp = uri.substring(scheme.length()).substring(1);
if (StringUtils.hasLength(fragment)) {
ssp = ssp.substring(0, ssp.length() - (fragment.length() + 1));
}
builder.schemeSpecificPart(ssp);
}
else {
builder.userInfo(userInfo);
builder.host(host);
if (StringUtils.hasLength(port)) {
builder.port(port);
}
builder.path(path);
builder.query(query);
}
if (StringUtils.hasText(fragment)) {
builder.fragment(fragment);
}
return builder;
}
else {
throw new IllegalArgumentException("[" + uri + "] is not a valid URI");
}
}
并且他里面是通过正则去匹配的,这样你可以直接通过这个方法就完成一个url的拼装,后面的参数是可以省略的,这个方法的应用场景:当你拿到一个url,想修改其中某个部分的时候使用:
public static void main(String[] args) {
// 添加参数: http://www.test.com/test?query1=1&query2=2
System.out.println(UriComponentsBuilder.fromUriString("http://www.test.com/test?query1=1")
.queryParam("query2", 2)
.build().toString());
// 更换域名: http://www.test2.com/test?query1=1
System.out.println(UriComponentsBuilder.fromUriString("http://www.test.com/test?query1=1")
.host("www.test2.com")
.build().toString());
}
这个方法和上面方法的用法基本是一样的
origin 里面放的是跨域访问的域名地址,比如 www.a.com 访问 www.b.com会形成跨域,这个时候访问 www.b.com 的时候,
请求头里会携带 origin:www.a.com, b服务需要通过这个来判断是否允许a服务跨域访问.
fromOriginHeader()方法可以获取到协议,域名和端口,个人觉得这个方法没什么卵用
// 协议: http/https
private String scheme;
// 协议特定部分,用来处理一些特殊协议,http协议用不到
private String ssp;
// 还没搞懂
private String userInfo;
// 域名
private String host;
// 端口
private String port;
// path 路径
private CompositePathComponentBuilder pathBuilder;
// 参数
private final MultiValueMap queryParams = new LinkedMultiValueMap();
private String fragment;
UriComponents uriComponents = UriComponentsBuilder.newInstance()
.scheme("http")
.host("www.test2.com")
.path("/test")
.queryParam("query", "a")
.build();
UriComponents uriComponents = UriComponentsBuilder.newInstance()
.scheme("http")
.host("www.test2.com")
.path("/test")
.queryParam("query", "a")
.build().encode("UTF-8");
UriComponents uriComponents = UriComponentsBuilder.newInstance()
.scheme("http")
.host("www.test2.com")
.path("/{template}")
.queryParam("query", "a")
.build().expand("test");
System.out.println(uriComponents.toString()); // http://www.test2.com/test?query=a
expand 有多个实现,支持传入可变参数和Map