一步一步自定义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 ...
随机推荐
- SQL排序 空值的后面
按sort排序,sort为空的在后面 end),sort
- HDU-1037(水水水题)
Keep on Truckin' Problem Description Boudreaux and Thibodeaux are on the road again . . . "Boud ...
- CSS background-position随笔
1.定义和用法 background-position 属性设置背景图像的起始位置. 这个属性设置背景原图像(由 background-image 定义)的位置,背景图像如果要重复,将从这一点开始. ...
- OpenXML: Asp.net利用OpenXML 导出Excel.
http://www.cnblogs.com/skyfei/archive/0001/01/01/Openxml.html
- .net 关于数据库的链接
web.config的配置 <appSettings> <add key="Configpath" value="~/XmlConfig/webset. ...
- sql Server 触发器 调用java.
在这里,通过 xp_cmdshell 调用java程序. 步骤: 1)开启 xp_cmdshell(sql Server 2008): 通过如下命令开启: -- To allow advanced o ...
- 关于通过bindService启动的service,在unbindService后service是否继续运行的讨论
有三种情况:如果直接使用服务,则没有必要进行绑定,但是如果要使用服务里面的方法,则要进行绑定.具体的启动情况有下: 1.当启动时,单独调用bindService方法,在unbindService后,会 ...
- 学会怎样使用Jsp 内置标签、jstl标签库及自定义标签
学习jsp不得不学习jsp标签,一般来说,对于一个jsp开发者,可以理解为jsp页面中出现的java代码越少,对jsp的掌握就越好,而替换掉java代码的重要方式就是使用jsp标签. jsp标签的分 ...
- Artificial Intelligence
//**************************************BEST-FS ALRORITHM IN ARTIFICAL INTELLIGENCE***************** ...
- ACM HDU 2674 N! Again(数论)
继续数论.. Problem Description WhereIsHeroFrom: Zty,what are you doing ? Zty: ...