一步一步自定义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转义xml中的多余尖括号
xml中的敏感字符是尖括号,如果xml的值中含有尖括号,那么在解析的时候就会报错,如: <?xml version="1.0" encoding="UTF-8&qu ...
- Ⅳ.AngularJS的点点滴滴-- 服务
服务(Angularjs很多方法都是服务组成的) 1.使用service方法创建的单例服务 <html> <script src="http://ajax.googleap ...
- Java基础知识强化之集合框架笔记57:Map集合之HashMap集合(HashMap<Student,String>)的案例
1. HashMap集合(HashMap<Student,String>)的案例 HashMap<Student,String>键:Student 要求:如果两个对象 ...
- css中判断IE版本的语句
css中判断IE版本的语句<!--[if gte IE 6]> Only IE 6/+ <![endif]-->: 1. <!--[if !IE]> 除IE外都可识 ...
- jmeter压测app
使用代理的方式,录制app端脚本,之后用jmeter压测就没啥好说的了 1.电脑端谷歌设置本地代理(端口号为8888) 2.jmeter设置HTTP代理服务器(端口号为8888) 3.手机端wifi设 ...
- AndroidStudio1.4 manifest 中注册Activity时的错误提示解决办法
问题截图如下: 解决办法截图如下: 1: File->setting->Editor->Language Injections到如下界面 2:双击右侧选中的Item进入编辑界面 3: ...
- C# CRC校验的一点感悟
今天在鼓捣一个手持操作器的时候,遇到一点问题,记录一下今天的经验包 由于之前公司产品在校验时基本上都是和校验,今天在准备用C#模拟一个古董操作器的时候,却遇到一个问题,模拟器发出的数据,主板一律不回复 ...
- jQuery 标签淡入淡出 个人随笔
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- juquery验证插件validation addMethod方法使用笔记
该方法有三个api接口参数,name,method,messages addMethod(name,method,message)方法 参数 name 是添加的方法的名字. 参数 method 是一个 ...
- C#应用程序中读取Oracle数据库
前言 最近的任务就是开发了一个功能,要从供应商那边读取数据,然后拿过来,处理以后放到我们自己的数据库中.供应商那边是Oracle数据库,其实不管什么数据我想都差不多,于是我就开始了.由于在家里写的博客 ...