一步一步自定义SpringMVC参数解析器

随心所欲,自定义参数解析器绑定数据。
题图:from Zoommy
干货
- SpringMVC解析器用于解析request请求参数并绑定数据到Controller的入参上。
- 自定义一个参数解析器需要实现
HandlerMethodArgumentResolver接口,重写supportsParameter和resolveArgument方法,配置文件中加入resolver配置。 - 如果需要多个解析器同时生效需要在一个解析器中对其他解析器做兼容
缘起
为什么要自定义一个解析器呢?
源于需要对前端请求参数进行手动URLDecode,也即除了Web容器自动decode一次,代码内还需要再decode一次。
针对这种需求,首先想到的是filter或者interceptor实现,但是由于HttpServletRequest对象本身是不提供setParameter()方法的,因此想要修改request中的参数值为decode后的值是不易达到的。
SpringMVC的HandlerMethodArgumentResolver,解析器;其功能就是解析request请求参数并绑定数据到Controller的入参上。因此自定义解析器加入URLDecode逻辑即可完全满足需求。
下面,就一步一步的完成一个解析器由简到繁的实现过程。
实现一个极其简单的参数解析器
具体如何自定义一个参数解析器呢?
其实很简单,一句话——实现HandlerMethodArgumentResolver接口,重写supportsParameter和resolveArgument方法,配置文件中加入resolver配置。
示例代码如下:
自定义解析器实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26public class MyArgumentsResolver implements HandlerMethodArgumentResolver {
/**
* 解析器是否支持当前参数
*/
@Override
public boolean supportsParameter(MethodParameter parameter) {
// 指定参数如果被应用MyParam注解,则使用该解析器。
// 如果直接返回true,则代表将此解析器用于所有参数
return parameter.hasParameterAnnotation(MyParam.class);
} /**
* 将request中的请求参数解析到当前Controller参数上
* @param parameter 需要被解析的Controller参数,此参数必须首先传给{@link #supportsParameter}并返回true
* @param mavContainer 当前request的ModelAndViewContainer
* @param webRequest 当前request
* @param binderFactory 生成{@link WebDataBinder}实例的工厂
* @return 解析后的Controller参数
*/
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { return null;
}
}自定义注解
1
2
3
4
5@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyParam {
}在springmvc配置文件中注册解析器
1
2
3
4
5
6<mvc:annotation-driven>
<!--MyArgumentsResolver-->
<mvc:argument-resolvers>
<bean class="xxx.xxx.xxx.MyArgumentsResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
好了,现在解析器会把所有应用了@MyParam注解的参数都赋值为null。
实现一个解析原始类型的参数解析器
对于如何解析原始类型参数,SpringMVC已经有了一个内置的实现——RequestParamMethodArgumentResolver,因此完全可以参考这个实现来自定义我们自己的解析器。
如上所述,解析器逻辑的主要部分都在resolveArgument方法内,这里就说说自定义该方法的实现。
1 |
@Override |
添加解析对象类型参数的功能
对于如何解析对象类型参数,SpringMVC内也有了一个内置的实现——ModelAttributeMethodProcessor,我们也是参考这个实现来自定义我们自己的解析器。
同样,resolveArgument方法示例如下
1 |
@Override |
同时支持多个参数解析器生效
到目前为止,不论对于原始类型或者对象类型的参数,我们都可以自定义一个参数解析器了,但是还有一个很严重的问题存在——无法让自定义解析器和现有解析器同时生效。
举个例子,public String myController(@Valid @MyParam param, BindingResult result){},这个方法在执行时是会报错的。他会提示类似如下报错:
An Errors/BindingResult argument is expected to be declared immediately after the model attribute, the @RequestBody or the @RequestPart arguments
是SpringMVC不支持同时使用两个解析器吗?public String myController(@Valid @ModelAttribute param, BindingResult result){},也是两个内置解析器,没有任何问题。
再去看ModelAttributeMethodProcessor的实现,原来是对@Valid做了兼容处理。
因此, 如果需要多个解析器同时生效需要在一个解析器中对其他解析器做兼容。
这里仅以对@Valid进行兼容处理为例,在解析对象类型的解析器实现中进行修改
1 |
@Override |
OK,到这里,我们自定义的解析器已经可以算是一个完善的参数解析器了,如果有对其他解析器做兼容的需要,只要参照此类方法稍作修改即可。
后记
还记得这次自定义解析器的原因吗——需要对前端请求参数进行手动URLDecode,也即除了Web容器自动decode一次,代码内还需要再decode一次。
事实证明,根本不需要进行二次decode,写出的解析器也就无疾而终了,仅存这篇整理,算是对SpringMVC解析器的一次学习总结吧。
http://coderec.cn/2016/08/27/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E8%87%AA%E5%AE%9A%E4%B9%89SpringMVC%E5%8F%82%E6%95%B0%E8%A7%A3%E6%9E%90%E5%99%A8/
一步一步自定义SpringMVC参数解析器的更多相关文章
- 自定义springmvc参数解析器
实现spring HandlerMethodArgumentResolver接口 通过使用@JsonArg自定义注解来解析json数据(通过fastjson的jsonPath),支持多个参数(@Req ...
- 自定义HandlerMethodArgumentResolver参数解析器和源码分析
在初学springmvc框架时,我就一直有一个疑问,为什么controller方法上竟然可以放这么多的参数,而且都能得到想要的对象,比如HttpServletRequest或HttpServletRe ...
- 实现自定义的参数解析器——HandlerMethodArgumentResolver
1.为什么需要自己实现参数解析器 我们都知道在有注解的接口方法中加上@RequestBody等注解,springMVC会自动的将消息体等地方的里面参数解析映射到请求的方法参数中. 如果我们想要的信息不 ...
- Spring boot中自定义Json参数解析器
转载请注明出处... 一.介绍 用过springMVC/spring boot的都清楚,在controller层接受参数,常用的都是两种接受方式,如下 /** * 请求路径 http://127.0. ...
- SpringMVC自动封装List对象 —— 自定义参数解析器
前台传递的参数为集合对象时,后台Controller希望用一个List集合接收数据. 原生SpringMVC是不支持,Controller参数定义为List类型时,接收参数会报如下错误: org.sp ...
- springmvc 源码分析(三) -- 自定义处理器映射器和自定义处理器适配器,以及自定义参数解析器 和错误跳转自定页面
测试环境搭建: 本次搭建是基于springboot来实现的,代码在码云的链接:https://gitee.com/yangxioahui/thymeleaf.git DispatcherServlet ...
- SpringMVC 自定义参数解析器.
一.简述 有没有想过像 @RequestParam.@RequestBody 这些注解的工作原理呢?为什么 form 表单.application/json 的参数能够直接封装进 Bean 对象中呢? ...
- SpringBoot系列教程web篇之如何自定义参数解析器
title: 190831-SpringBoot系列教程web篇之如何自定义参数解析器 banner: /spring-blog/imgs/190831/logo.jpg tags: 请求参数 cat ...
- springMVC源码分析--RequestParamMethodArgumentResolver参数解析器(三)
之前两篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)和springMVC源码解析--HandlerMethodArgumentResol ...
随机推荐
- Java基础知识强化之网络编程笔记02:Socket通信原理图解
1. Socket (1)Socket套接字 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字 (2)Socket原理机制: • 通信两端都有Socket. • 网 ...
- majikan
- 数字证书简介及Java编码实现
1.数字证书简介 数字证书具备常规加密解密必要的信息,包含签名算法,可用于网络数据加密解密交互,标识网络用户(计算机)身份.数字证书为发布公钥提供了一种简便的途径,其数字证书则成为加密算法以及公钥的载 ...
- 获得Radio选中的后面文本框的值
例如: 选中的radio的值在button中显示 代码如下: <!DOCTYPE html> <html lang="en" xmlns="http:/ ...
- html不同文档类型支持的元素标签
- 初学HTML5系列二:HTML5新增的事件属性
Window事件属性: 属性 值 描述 onafterprint script 文档打印之后运行的脚本. 属性发生于用户设置页面打印并且打印对话框已出现之后. onbeforeprint scri ...
- JS关闭窗口或JS关闭页面的几种代码
//JS定时自动关闭窗口 <script language="javascript"> <!-- function closewin(){ self.opener ...
- sql server抓取表结构的语句
sql server 2008抓取方法: --------------------------------------- SELECT 表名 = Case When A.colorder ...
- 简单的完全背包HDU1114
今天广州下雨啦,不过没关系啦,反正我最近也都在刷题学习算法. 昨天做了五题01背包,今天还是背包,不过是完全背包,估计做动态规划要持续好一段时间,一开始选了一道简单题目啦. HDU1114,看了小一段 ...
- (转)log4j日志级别设置成DEBUG时输出Html代码等问题:
log4j日志级别设置成DEBUG时输出Html代码等问题: 问题: log4j日志级别设置成DEBUG时会输出很多信息,包括一些Html代码 解决方案: log4j的控制是树形,所以在log4j.p ...