使用@RequestParam获取带加号的日期参数时加号丢失,如何解决?
解决@RequestParam中ISO日期参数加号被转为空格的问题
你遇到的核心问题是:在application/x-www-form-urlencoded编码规则里,+会被自动解码为空格,而你的请求URL里的时区部分+0000被Spring解码后变成了空格,导致@DateTimeFormat无法匹配格式,返回400错误。由于不能修改URL格式,我们可以通过以下两种方案解决:
方案一:手动替换时区部分的空格为加号(简单直接)
先以String类型接收参数,然后通过正则表达式精准替换时区前的空格为+,再手动解析为Date:
import org.springframework.format.datetime.DateFormatter; import java.text.ParseException; import java.util.Locale; @GetMapping(value = "/api/{version}/test", produces = "application/json") public ResponseEntity<MyList> getFreeList( @PathVariable String version, @RequestParam("date") String dateStr) throws ParseException { // 仅替换时区部分的空格为+(匹配毫秒数后的空格与时区数字) String correctedDateStr = dateStr.replaceAll("(\\.\\d{3})\\s(\\d{4})$", "$1+$2"); // 手动解析为Date DateFormatter formatter = new DateFormatter("yyyy-MM-dd HH:mm:ss.SSSZ"); Date date = formatter.parse(correctedDateStr, Locale.getDefault()); return new ResponseEntity<>(myService.getList(date), HttpStatus.OK); }
这个方案的好处是只针对你的日期格式做修改,不会影响其他参数的正常解码。
方案二:获取原始查询字符串并自定义解码(更通用)
如果你的日期格式可能有变化,或者需要保留原始参数的所有编码信息,可以直接从HttpServletRequest获取未解码的查询字符串,自己解析并解码(跳过+转空格的规则):
import org.springframework.web.util.UriUtils; import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.text.SimpleDateFormat; @GetMapping(value = "/api/{version}/test", produces = "application/json") public ResponseEntity<MyList> getFreeList( @PathVariable String version, HttpServletRequest request) throws ParseException { String queryString = request.getQueryString(); String dateStr = null; // 解析查询字符串,提取date参数的原始值 if (queryString != null) { String[] params = queryString.split("&"); for (String param : params) { if (param.startsWith("date=")) { dateStr = param.substring(5); break; } } } // 自定义解码:不将+转为空格 String decodedDateStr = UriUtils.decode(dateStr, StandardCharsets.UTF_8.name(), false); // 解析为Date SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ"); Date date = sdf.parse(decodedDateStr); return new ResponseEntity<>(myService.getList(date), HttpStatus.OK); }
这里用到了Spring的UriUtils.decode方法,第三个参数设为false,就会保留原始的+符号,避免被转为空格。
为什么原来的代码会失败?
当Spring处理@RequestParam时,默认会按照application/x-www-form-urlencoded规则解码参数,其中+被视为空格的编码形式,所以你的+0000变成了 0000,导致@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSSZ")无法匹配格式,触发400错误。
内容的提问来源于stack exchange,提问作者PythonQQ
相关产品推荐
相关产品推荐

