|
| 1 | +## 在SpringMVC中优雅的拼接URL |
| 2 | + |
| 3 | +### 背景 |
| 4 | + |
| 5 | +> 在日常开发中常常会遇到拼接URL的情况,大多数时候可以手动拼接字符串来达到目的,但是这样的方式不够优雅,同时容易出错。其实SpringMVC中已经给我们提供好了工具,这个工具就是UriComponentsBuilder类。 |
| 6 | +
|
| 7 | +### 开始 |
| 8 | + |
| 9 | +UriComponentsBuilder给我们提供了多种方式来构建不可变的UriComponents实例,要使用这个工具,需要在maven中引入web的依赖: |
| 10 | + |
| 11 | +``` |
| 12 | +<dependency> |
| 13 | + <groupId>org.springframework</groupId> |
| 14 | + <artifactId>spring-web</artifactId> |
| 15 | + <version>5.1.0.RELEASE</version> |
| 16 | +</dependency> |
| 17 | +``` |
| 18 | +这里仅仅引入了web,如果是SpringBoot中,可以直接引入starter。 |
| 19 | + |
| 20 | +> 直接通过字符串拼接 |
| 21 | +
|
| 22 | +```java |
| 23 | +String url = "https://api.github.com" + "?" + "token=xxx" + "&name=" + "tomcat"; |
| 24 | +``` |
| 25 | + |
| 26 | +这种方式简单,写起来也不费劲,但问题就是容易出错。 |
| 27 | + |
| 28 | +> 通过Guava |
| 29 | +
|
| 30 | +Google的Guava中也提供了工具,方便我们拼接URL |
| 31 | + |
| 32 | +```java |
| 33 | +// 优雅的拼接出id=1&name=java这样的URL参数 |
| 34 | +Joiner.on("&").withKeyValueSeparator("=").join(ImmutableMap.of("id", 1, "name", "java")); |
| 35 | +// 轻松把URL参数的值转为Map |
| 36 | +Splitter.on("&").withKeyValueSeparator("=").split("id=1&name=java"); |
| 37 | +``` |
| 38 | + |
| 39 | +> UriComponentsBuilder |
| 40 | +
|
| 41 | +- 构造一个简单的URI |
| 42 | + |
| 43 | +``` |
| 44 | +@Test |
| 45 | +public void constructUri() { |
| 46 | + UriComponents uriComponents = UriComponentsBuilder.newInstance() |
| 47 | + .scheme("http").host("www.github.com").path("/constructing-uri") |
| 48 | + .queryParam("name", "tom") |
| 49 | + .build(); |
| 50 | +
|
| 51 | + assertEquals("/constructing-uri", uriComponents.getPath()); |
| 52 | + assertEquals("name=tom", uriComponents.getQuery()); |
| 53 | + assertEquals("/constructing-uri", uriComponents.toUriString()); |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +`uriComponents`可以使用`toUriString()`方法去输出拼接好的URI地址,这里的结果是: |
| 58 | + |
| 59 | +``` |
| 60 | +http://www.github.com/constructing-uri?name=tom |
| 61 | +``` |
| 62 | + |
| 63 | +可以看到`UriComponentsBuilder`是流式API的形式,代码也非常容易理解: |
| 64 | + |
| 65 | + 1. scheme:协议,http或者https |
| 66 | + 2. host:主机地址 |
| 67 | + 3. path:要访问的路径 |
| 68 | + 4. queryParam:url的参数,可以传入多个value |
| 69 | + |
| 70 | +**这个例子在我们后台想重定向到某个地址时非常有用。** |
| 71 | + |
| 72 | +- 构造一个编码的URI |
| 73 | + |
| 74 | +有些参数中携带了特殊符号,这时候需要进行编码,`UriComponentsBuilder`编码也很简单: |
| 75 | + |
| 76 | +```java |
| 77 | +@Test |
| 78 | +public void constructUriEncoded() { |
| 79 | + UriComponents uriComponents = UriComponentsBuilder.newInstance() |
| 80 | + .scheme("http").host("www.github.com").path("/constructing uri").build().encode(); |
| 81 | + |
| 82 | + assertEquals("/constructing%20uri", uriComponents.getPath()); |
| 83 | +} |
| 84 | +``` |
| 85 | + |
| 86 | +- 通过模板构造URI |
| 87 | + |
| 88 | +我们可以通过占位符的方式来构造URI,这种方式是Spring中常常使用的方式,如果用过RestTemplate,那么一定不会陌生。 |
| 89 | + |
| 90 | +```java |
| 91 | +@Test |
| 92 | +public void constructUriFromTemplate() { |
| 93 | + UriComponents uriComponents = UriComponentsBuilder.newInstance() |
| 94 | + .scheme("http").host("www.github.com").path("/{path-name}") |
| 95 | + .query("name={keyword}") |
| 96 | + .buildAndExpand("constructing-uri", "tomcat"); |
| 97 | + |
| 98 | + assertEquals("/constructing-uri", uriComponents.getPath()); |
| 99 | +} |
| 100 | +``` |
| 101 | + |
| 102 | +- 从已有的URI中获取信息 |
| 103 | + |
| 104 | +既然存在自己构造URI,那么也有从已知的URI中获取信息的需求,`UriComponentsBuilder`也可以做到 |
| 105 | + |
| 106 | +```java |
| 107 | +@Test |
| 108 | +public void fromUriString() { |
| 109 | + UriComponents result = UriComponentsBuilder |
| 110 | + .fromUriString("https://www.github.com/constructing-uri?name=tomcat").build(); |
| 111 | + MultiValueMap<String, String> expectedQueryParams = new LinkedMultiValueMap<>(1); |
| 112 | + expectedQueryParams.add("name", "tomcat"); |
| 113 | + assertEquals(result.getQueryParams(), expectedQueryParams); |
| 114 | +} |
| 115 | +``` |
| 116 | + |
| 117 | +使用`fromUriString()`方法,便可以把一个字符串URI转换为`UriComponents`对象,并且可以通过`getQueryParams()`方法取出参数。 |
| 118 | + |
| 119 | + |
| 120 | +### 总结 |
| 121 | + |
| 122 | +`UriComponentsBuilder`的用法远远不止这些,这些例子只是我日常开发中常常用到的,更多的可以参考[docs](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/UriComponentsBuilder.html),代码已经同步到[男性交友网站](https://note.youdao.com/)。 |
0 commit comments