首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >UriComponentsBuilder不能编码ISO-8601日期参数。

UriComponentsBuilder不能编码ISO-8601日期参数。
EN

Stack Overflow用户
提问于 2020-07-08 21:31:13
回答 1查看 662关注 0票数 2

在进行一些集成测试时,我遇到了一个有趣的问题。

我有一个rest端点,它有一些查询参数,这些参数是ISO8601中指定的时间戳(例如: 2020-07-08T23:54:36.931159+03:00)。日期是用java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME格式化的

我使用以下方法创建请求地址:

代码语言:javascript
运行
复制
//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());
      }
    }

这将产生以下地址:

代码语言:javascript
运行
复制
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,字符集)编码参数:

代码语言:javascript
运行
复制
  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次。

代码语言:javascript
运行
复制
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。

我的问题是,我应该如何提供查询参数,以便正确编码它们?或者这个构建器不适合与特殊字符一起使用?

EN

回答 1

Stack Overflow用户

发布于 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,比如:

代码语言:javascript
运行
复制
val uri = UriComponentsBuilder.fromUriString(baseApi.url)
        .path("/v1/products/${productId}/orders")
        .queryParam("from", from)
        .queryParam("to", to)
        .queryParam("type", type)
        .build().encode().toUri()

它适用于UTC时间戳,但不使用偏移编码时间戳。就像在你的案子里。

这就是为我准备的:

代码语言:javascript
运行
复制
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问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62803953

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档