在进行一些集成测试时,我遇到了一个有趣的问题。
我有一个rest端点,它有一些查询参数,这些参数是ISO8601中指定的时间戳(例如: 2020-07-08T23:54:36.931159+03:00)。日期是用java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME格式化的
我使用以下方法创建请求地址:
//Query params are supplied in a Map<String,String>
String baseURL="http://localhost:" + this.port + uri
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseURL);
if (params != null) {
for (final Entry<String, String> entry : params.entrySet()) {
builder.queryParam(entry.getKey(), entry.getValue());
}
}
这将产生以下地址:
http://localhost:8090/remainingAddress?fromDate=2020-07-08T23:54:36.834869+03:00&toDate=2020-07-08T23:54:36.931159+03:00
问题是,"+“符号并没有被编码,并保留了原来在Map中的位置。在接收端,参数被解码,从而导致以下日期“020-0708T23:54:36.834869 03:00”(注意空格而不是+),因此,当我试图使用相同的格式化程序解析日期时,它会失败。
在将值添加到构建器之前,我尝试用java.net.URLEncoder.encode(String,字符集)编码参数:
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseURL);
if (params != null) {
for (final Entry<String, String> entry : params.entrySet()) {
var encoded=URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8);
builder.queryParam(entry.getKey(), encoded);
}
}
然而,这引入了"%“作为一个特殊字符,它实际上触发了构建器中的编码,因此日期参数被编码了2次。
input string: 2020-07-09T00:14:15.230699+03:00
result after first encoding: 2020-07-09T00%3A14%3A15.230699%2B03%3A00
final result: http://localhost:8090/remainingAddress?fromDate=2020-07-09T00%253A14%253A15.230699%252B03%253A00&toDate=2020-07-09T00%253A14%253A15.31158%252B03%253A00
在执行请求时,我在尝试解析日期时收到以下输入:2020-07-09T00%253A14%253A15.230699%252B03%253A00 (非常混乱)。
注意,这个项目使用SpringBootV2.5.5。
我的问题是,我应该如何提供查询参数,以便正确编码它们?或者这个构建器不适合与特殊字符一起使用?
发布于 2022-02-15 06:56:36
注:这是Kotlin实现
我最近遇到了这个问题,
其中一个端点的范围限制为queryparam,类型为OffsetDateTime。
有时类似于UTC时间戳,例如2021-01-13T02:00Z
,或者带有一个区域偏移(如2021-01-13T13:00+11:00
),其中两者都等于2021-01-13T13:00
LocalDateTime of ZoneId Australia/Melbourne
。
最初,我试图构建uri,比如:
val uri = UriComponentsBuilder.fromUriString(baseApi.url)
.path("/v1/products/${productId}/orders")
.queryParam("from", from)
.queryParam("to", to)
.queryParam("type", type)
.build().encode().toUri()
它适用于UTC时间戳,但不使用偏移编码时间戳。就像在你的案子里。
这就是为我准备的:
val uri = UriComponentsBuilder.fromUriString(baseApi.url)
.path("/v1/products/${productId}/orders")
.queryParam("from", "{from}")
.queryParam("to", "{to}")
.queryParam("type", type)
.encode().buildAndExpand(from, to).toUri()
这有助于将OffsetDateTime作为变量注入到字符串中,而buildAndExpand则是这样。这里的字符串插值通过添加这些特殊转义字符来修正任何uriString问题。
https://stackoverflow.com/questions/62803953
复制相似问题