前言
开发中,小编在项目中,使用RestTemplate做GET请求,为了优雅的封装参数,使用了UriComponentsBuilder来进行参数封装。直接123将代码写完,远程调用有数据,远程底层solr库,所以拿到数据了,没有过多的验证,在测试时,发现接口是返回了数据,但是,数据不正确。最后,两边联调查找原因,发现是传递到远程的参数,被编码了,从而导致的数据结果不正确。
参数被编码的示例:
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url)
.queryParam("title", title)
.queryParam("page", page)
.queryParam("pageSize", pageSize);
String fullUrl = builder.toUriString();
参数不被编码的示例:
UriComponents uriComponents = UriComponentsBuilder.fromUriString(url)
.queryParam("title", title)
.queryParam("page", page)
.queryParam("pageSize", pageSize)
.build();
String fullUrl = uriComponents.toUriString();
可以看到两个示例不同之处,就是第一个示例,使用构造器来封装参数,然后通过 String fullUrl = builder.toUriString()
获取构建的url字符串。第二个示例是通过build()方法构建出UriComponents 实例,然后通过 String fullUrl = uriComponents.toUriString();
获取构建的url字符串,问题就出在这里了。
UriComponentsBuilder
和 UriComponents
的toUriString()
方法底层实现不一样,UriComponentsBuilder 的toUriString()方法在实现的时候对中文参数进行了编码,而UriComponents的toUriString()方法并没有进行参数编码,原因就在这里。下面我们比较一下,两个方法的源码。
UriComponentsBuilder
UriComponents
UriComponents的toUriString()的有两个实现,默认是走HierarchicalUriComponents类的toUriString()方法
从上边两个类的toUriString()方法,我们可以看到UriComponentsBuilder里调用了encode()方法,所以对最终的url中的中文参数进行了编码。
UriComponentsBuilder的一些其他的用法
包含下面几个方法:
UriComponentsBuilder.fromUriString()
UriComponentsBuilder.fromHttpUrl()
UriComponentsBuilder.fromHttpRequest()
UriComponentsBuilder.fromUri()
UriComponentsBuilder.fromOriginHeader()
UriComponentsBuilder.fromPath()
这几个方法都是用于创建 UriComponentsBuilder 实例的静态工厂方法,但它们有一些不同的使用场景和用途。
fromUriString(String uriString):
- 使用给定的字符串创建一个 UriComponentsBuilder 实例。
- 适用于从一个字符串 URI 中创建UriComponentsBuilder。
fromHttpUrl(String httpUrl):
- 使用给定的 HTTP 或 HTTPS URL 字符串创建一个 UriComponentsBuilder 实例。
- 适用于从一个完整的HTTP 或 HTTPS URL 中创建 UriComponentsBuilder。
fromHttpRequest(HttpServletRequest request):
- 使用给定的 HttpServletRequest 对象创建一个 UriComponentsBuilder 实例。
- 适用于从一个 HTTP请求中获取 URI 并创建 UriComponentsBuilder。
fromUri(URI uri):
- 使用给定的 URI 对象创建一个 UriComponentsBuilder 实例。
- 适用于从一个 URI 对象中创建UriComponentsBuilder。
fromOriginHeader(String originHeader):
- 使用给定的 Origin 头字符串创建一个 UriComponentsBuilder 实例。 适用于从一个 Origin 头字符串中创建 UriComponentsBuilder。
fromPath(String path):
- 使用给定的路径字符串创建一个 UriComponentsBuilder 实例。
- 适用于从一个路径字符串中创建UriComponentsBuilder,不包含主机和方案等信息。
这些方法提供了不同的入口点来创建 UriComponentsBuilder 实例,并根据不同的输入来构建 URI。您可以根据具体的场景和需求选择适当的方法来创建 UriComponentsBuilder,然后使用其它方法来构建和操作 URI。
小结
出现这个问题,究其本质还是对api熟悉的不够,所以我们平时学习技术要更加的细致,不仅要会用,还要了解它的实现方式,从而是我们的技术功底更加的扎实。加油~