在基于Spring Boot 2.0.1的微服务中,我有一个GET
Rest控制器,它接受一个fromDate& toDate编码为ISO字符串(缩短):
@GetMapping(value = "/range")
public ResponseEntity<MyDTO> getDateRange(
@RequestParam
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
ZonedDateTime fromDate,
@RequestParam
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
ZonedDateTime toDate) {
if (fromDate.isAfter(toDate) || fromDate.isEqual(toDate)) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(HttpStatus.OK);
}
所以请求应该看起来像(完全URLEncoded):
http://localhost:8080/range/?fromDate=2015-05-31T03%3A00%3A00.000%2B04%3A00&toDate=2015-05-31T03%3A30%3A00.000%2B04%3A00
或仅使用+
转义:
http://localhost:8080/range/?fromDate=2015-05-31T03:00:00.000%2B04:00&toDate=2015-05-31T03:30:00.000%2B04:00
作为参考,un-URI编码的字符串是:
http://localhost:8080/range/?fromDate=2015-05-31T03:00:00.000+04:00&toDate=2015-05-31T03:30:00.000+04:00
- 这不起作用。
当我通过Postman执行GETs
或在Spring Boot中使用MockMvc
进行测试时,此休息控制器工作正常。但为了完整性和我自己的理解,我还希望通过TestRestTemplate
进行测试。但是,在参数中使用+
的问题是有问题的。但我无法理解为什么。
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class IntegrationTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void test_get_in_range() throws Exception {
// String uri = "/range?fromDate={fromDate}&toDate={toDate}";
//
// Map<String, String> uriParams = new HashMap<>();
// uriParams.put("fromDate", "2015-05-31T03:00:00.000+04:00");
// uriParams.put("toDate", "2015-05-31T19:00:00.000+04:00");
UriComponents uriComponents = UriComponentsBuilder
.fromPath("/range")
.queryParam("fromDate", "2015-05-31T03:00:00.000+04:00")
.queryParam("toDate", "2015-05-31T19:00:00.000+04:00").build();
// Also tried with manually replacing + with %2B
// Also tried manually encoding the string
ResponseEntity<String> getResponseEntity = restTemplate.withBasicAuth("cameraUser", "change_me")
.getForEntity(uriComponents.toUriString(), String.class);
}
}
服务器的结果是Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam @org.springframework.format.annotation.DateTimeFormat java.time.ZonedDateTime] for value '2015-05-31T03:00:00.000 04:00'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2015-05-31T03:00:00.000 04:00]
似乎字符串中的+
被空格替换,当我从Postman执行未编码的GET
请求时也会发生这种情况。
在测试中用+
替换%2B
会产生:
Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam @org.springframework.format.annotation.DateTimeFormat java.time.ZonedDateTime] for value '2015-05-31T03:00:00.000%2B04:00'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2015-05-31T03:00:00.000%2B04:00]
有谁知道为什么?我怀疑它在某种程度上与自动配置相关,并且在测试模式下不使用与默认执行中相同的过滤器/转换器(不清楚术语)。我没有注册额外的转换器,并且完全依赖Spring Boot自动配置。
编辑:我创建了一个示例应用程序,显示问题here。