一步一步自定义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 ...
随机推荐
- XC文件管理器(Android应用)
XC文件管理器,是基于Android4.4开发的一个方便易用的文件管理器,具有文件的目录管理和文件的管理,主要包括文件的新建.删除.重命名.复制,移动剪切以及文件详情查看等文件和目录的功能,同时支持文 ...
- XC软件管理器应用
这是一个基于android 4.4开发的android应用-XC软件管理器.包含应用的信息查看,打开应用以及应用的卸载等功能.非常实用的一个应用,欢迎大家下载使用. 下载地址:http://downl ...
- Java-Junit 的Hello world
这里介绍junit 4的基本配置: <1>建立一个java project项目. <2>在src目录下面建一个包,com.sun.junit4,在包下面写一点文件T.java ...
- [DEncrypt] HashEncode--哈希加密帮助类 (转载)
点击下载 HashEncode.zip 这个类是关于加密,解密的操作,文件的一些高级操作1.HashEncode 得到随机哈希加密字符串2.HashEncode 得到一个随机数值3.HashEncod ...
- 一个误解: 单个服务器程序可承受最大连接数“理论”上是“65535”
转载:http://www.cnblogs.com/tianzhiliang/archive/2011/06/13/2079564.html 请注意,这里有两个词分别被我标记上了引号,一个是" ...
- 黑马入学基础测试(三)求斐波那契数列第n项,n<30,斐波那契数列前10项为 1,1,2,3,5,8,13,21,34,55
.获得用户的输入 计算 3打印就行了. 这里用到了java.util.Scanner 具体API 我就觉得不常用.解决问题就ok了.注意的是:他们按照流体的方式读取.而不是刻意反复 ...
- UIAlertController使用的一个坑
/ // 创建一个确定按钮”一定要注意不能在提醒控制器的按钮的点击方法内部用到提醒控制器自己”,不能把下面这句话放在block内部”不然会死循环,导致警告控制器不能销毁" UITextFie ...
- OC - 13.数据解析(JSON与XML)
##数据交互格式 服务器返回给用户的数据,通常是以下两种方式: JSON XML JSON 一种轻量级的数据数据格式,体积比XML小,是服务器返回给移动端通常采用的格式 用使用JSON文件中的数据,需 ...
- C# 控制台窗口的显示与隐藏
1. 定义一个Consolse帮助类,如下: /// <summary> /// 控制台帮助类 /// </summary> public static class Conso ...
- 3D Game Programming with directx 11 习题答案 8.2
第八章 第二题 1.首先找到Directx Texture Tool,它位于 2.填入配置 3.用画图工具画好每个level的图片,例如level0 4.用Directx Texture Tool添加 ...