点击上方蓝色字体,选择“标星公众号”
优质文章,第一时间送达
上一篇:这300G的Java资料是我师傅当年给我的,免费分享给大家(已修复)
下一篇:昨天分享资料不小心把百度网盘深处的秘密泄露了(已修复)
作者:Throwable
来源:http://suo.im/6lV5ng
在日常使用 SpringMVC 进行开发的时候,有可能遇到前端各种类型的请求参数,这里做一次相对全面的总结。SpringMVC 中处理控制器参数的接口是 HandlerMethodArgumentResolver ,此接口有众多子类,分别处理不同(注解类型)的参数,下面只列举几个子类:
RequestParamMethodArgumentResolver :解析处理使用了 @RequestParam 注解的参数、 MultipartFile 类型参数和 Simple 类型(如 long 、 int 等类型)参数。
RequestResponseBodyMethodProcessor :解析处理 @RequestBody 注解的参数。
PathVariableMapMethodArgumentResolver :解析处理 @PathVariable 注解的参数。
实际上,一般在解析一个控制器的请求参数的时候,用到的是 HandlerMethodArgumentResolverComposite ,里面装载了所有启用的 HandlerMethodArgumentResolver 子类。而 HandlerMethodArgumentResolver 子类在解析参数的时候使用到 HttpMessageConverter (实际上也是一个列表,进行遍历匹配解析)子类进行匹配解析,常见的如 MappingJackson2HttpMessageConverter (使用 Jackson 进行序列化和反序列化)。而 HandlerMethodArgumentResolver 子类到底依赖什么 HttpMessageConverter 实例实际上是由请求头中的 Content-Type (在 SpringMVC 中统一命名为 MediaType ,见 org.springframework.http.MediaType )决定的,因此我们在处理控制器的请求参数之前必须要明确外部请求的 Content-Type 到底是什么。上面的逻辑可以直接看源码 AbstractMessageConverterMethodArgumentResolver#readWithMessageConverters ,思路是比较清晰的。在 @RequestMapping 注解中, produces 和 consumes 属性就是和请求或者响应的 Content-Type 相关的:
consumes 属性:指定处理请求的提交内容类型( Content-Type ),例如 application/json、 text/html 等等,只有命中了对应的 Content-Type 的值才会接受该请求。
produces 属性:指定返回的内容类型,仅当某个请求的请求头中的( Accept )类型中包含该指定类型才返回,如果返回的是JSON数据一般考虑使用 application/json;charset=UTF-8。
另外提一点, SpringMVC 中默认使用 Jackson 作为JSON的工具包,如果不是完全理解透整套源码的运作,一般不是十分建议修改默认使用的 MappingJackson2HttpMessageConverter (例如有些人喜欢使用 FastJson ,实现 HttpMessageConverter 引入 FastJson 做HTTP消息转换器,这种做法并不推荐)。
SpringMVC请求参数接收
其实一般的表单或者JSON数据的请求都是相对简单的,一些复杂的处理主要包括URL路径参数、文件上传、数组或者列表类型数据等。另外,关于参数类型中存在日期类型属性(例如 java.util.Date 、 java.sql.Date 、 java.time.LocalDate 、 java.time.LocalDateTime 、 java.time.ZonedDateTime 等等),解析的时候一般需要自定义实现的逻辑实现 String-->日期类型 的转换。其实道理很简单,日期相关的类型对于每个国家、每个时区甚至每个使用者来说认知都不一定相同,所以 SpringMVC 并没有对于日期时间类型的解析提供一个通用的解决方案。在演示一些例子可能用到下面的模特类:
@Data
public class User {
private String name;
private Integer age;
private List contacts;
}
@Data
public class Contact {
private String name;
private String phone;
}
下面主要以 HTTP 的 GET 方法和 POST 方法提交在 SpringMVC 体系中正确处理参数的例子进行分析,还会花精力整理 SpringMVC 体系中 独有的 URL 路径参数 处理的一些技巧以及最常见的 日期参数 处理的合理实践(对于 GET 方法和 POST 方法提交的参数处理,基本囊括了其他如 DELETE 、 PUT 等方法的参数处理,随机应变即可)。
GET方法请求参数处理
HTTP(s) 协议使用 GET 方法进行请求的时候,提交的参数位于 URL 模式的 Query 部分,也就是 URL 的 ? 之后的参数,格式是 key1=value1&key2=value2 。GET 方法请求参数可以有多种方法获取:
@RequestParam
Query
HttpServletRequest
假设请求的 URL 为 http://localhost:8080/get?name=doge&age=26 ,那么控制器如下:
@Slf4j
@RestController
public class SampleController {
@GetMapping(path = "/get1")
public void get1(@RequestParam(name = "name") String name,
@RequestParam(name = "age") Integer age) {
log.info("name:{},age:{}", name, age);
}
@GetMapping(path = "/get2")
public void get2(UserVo vo) {
log.info("name:{},age:{}", vo.getName(), vo.getAge());
}
@GetMapping(path = "/get3")
public void get3(HttpServletRequest request) {
String name = request.getParameter("name");
String age = request.getParameter("age");
log.info("name:{},age:{}", name, age);
}
@Data
public static class UserVo {
private String name;
private Integer age;
}
}
表单参数
表单参数,一般对应于页面上