Spring中URI操作工具类
# UriComponents
UriComponentsBuilder帮助从带有变量的URI模板中构建URI, 如下示例:
UriComponents uriComponents = UriComponentsBuilder
.fromUriString("https://www.baidu.com/users/{userName}")
.queryParam("q", "{q}")
.encode()
.build();
URI uri = uriComponents.expand("userName", "pack").toUri() ;
System.out.println(uri) ; // 输出 https://www.baidu.com/users/userName?q=pack
2
3
4
5
6
7
可以直接使用URI来进一步缩短它:
URI uri = UriComponentsBuilder
.fromUriString("https://www.baidu.com/users/{userName}")
.queryParam("q", "{q}")
.build("userName", "pack");
System.out.println(uri);// 输出 https://www.baidu.com/users/userName?q=pack
2
3
4
5
通过模版方式,更简短:
URI uri = UriComponentsBuilder
.fromUriString("https://www.baidu.com/users/{userName}?q={q}")
.build("userName", "pack");
System.out.println(uri);
2
3
4
# UriBuilder
UriComponentsBuilder实现了UriBuilder。反过来,可以使用UriBuilderFactory创建UriBuilder。UriBuilderFactory和UriBuilder共同提供了一种基于共享配置(如基本URL、编码首选项和其他细节)从URI模板构建URI的可插拔机制。
你可以使用UriBuilderFactory配置RestTemplate和WebClient来定制uri的准备。DefaultUriBuilderFactory是UriBuilderFactory的默认实现,它在内部使用UriComponentsBuilder并公开共享配置选项。下面以RestTemplate为例:
String baseUrl = "https://www.baidu.com";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
RestTemplate restTemplate = new RestTemplate() ;
restTemplate.setUriTemplateHandler(factory) ;
2
3
4
5
6
WebClient下使用
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
2
3
4
直接使用DefaultUriBuilderFactory创建URI
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(baseUrl);
URI uri = uriBuilderFactory.uriString("/users/{userName}")
.queryParam("q", "{q}")
.build("userName", "pack");
System.out.println(uri) ; //输出 https://www.baidu.com/users/userName?q=pack
2
3
4
5
6
# URI编码
UriComponentsBuilder提供了两种级别的编码选项:
- UriComponentsBuilder#encode():先对URI模板进行预编码,然后在展开时对URI变量进行严格编码。
- UriComponents#encode():在URI变量展开后对URI组件进行编码。
这两个选项都用转义的八位字节替换非ASCII和非法字符。但是,第一个选项也替换URI变量中出现的具有保留含义的字符。
在大多数情况下,第一种选择可能会得到预期的结果,因为它将URI变量视为完全编码的不透明数据,而在URI变量有意包含保留字符时,第二种选择很有用。当不展开URI变量时,第二个选项也很有用,因为它也会编码任何看起来像URI变量的东西。
URI uri = UriComponentsBuilder.fromPath("/users list/{name}")
.queryParam("q", "{q}")
.encode()
.buildAndExpand("name", "pack")
.toUri();
System.out.println(uri) ; //输出 /users%20list/name?q=pack
2
3
4
5
6
简化版本
URI uri = UriComponentsBuilder.fromPath("/users list/{name}")
.queryParam("q", "{q}")
.build("name", "pack") ;
2
3
完整的URI模版
URI uri = UriComponentsBuilder.fromUriString("/users list/{name}?q={q}")
.build("name", "pack") ;
2
# Servlet请求
你可以使用ServletUriComponentsBuilder来创建相对于当前请求的uri,如下示例:
MockHttpServletRequest request = new MockHttpServletRequest() ;
request.setRequestURI("/users") ;
URI uri = ServletUriComponentsBuilder
.fromRequest(request)
.replaceQueryParam("id", "{id}")
.build("666") ;
System.out.println(uri) ; //输出 http://localhost/users?id=666
2
3
4
5
6
7
创建相对于上下文路径的uri
URI uri = ServletUriComponentsBuilder.fromContextPath(request)
.path("/users")
.build()
.toUri() ;
2
3
4
# 链接Controller
Spring MVC提供了一种机制可以到Controller方法的链接。如下示例:
MockHttpServletRequest request = new MockHttpServletRequest() ;
ServletRequestAttributes requestAttribute = new ServletRequestAttributes(request) ;
// 我这是直接通过一个main函数运行的,而MvcUriComponentsBuilder内部需要Request相关对象
// 所以这里需要自己构建
RequestContextHolder.setRequestAttributes(requestAttribute) ;
UriComponents uriComponents = MvcUriComponentsBuilder
.fromMethodName(UserController.class, "queryById", 666L).buildAndExpand();
URI uri = uriComponents.encode().toUri();
System.out.println(uri) ; //输出 http://localhost/users/666
2
3
4
5
6
7
8
9
10