为所欲为,自定义参数解析器绑定数据。前端
题图:from Zoommygit
HandlerMethodArgumentResolver
接口,重写supportsParameter
和resolveArgument
方法,配置文件中加入resolver配置。为何要自定义一个解析器呢?github
源于须要对前端请求参数进行手动URLDecode,也即除了Web容器自动decode一次,代码内还须要再decode一次。web
针对这种需求,首先想到的是filter或者interceptor实现,可是因为HttpServletRequest
对象自己是不提供setParameter()
方法的,所以想要修改request中的参数值为decode后的值是不易达到的。spring
SpringMVC的HandlerMethodArgumentResolver
,解析器;其功能就是解析request请求参数并绑定数据到Controller的入参上。所以自定义解析器加入URLDecode逻辑便可彻底知足需求。mvc
下面,就一步一步的完成一个解析器由简到繁的实现过程。ide
具体如何自定义一个参数解析器呢?学习
其实很简单,一句话——实现HandlerMethodArgumentResolver
接口,重写supportsParameter
和resolveArgument
方法,配置文件中加入resolver配置。ui
示例代码以下:this
自定义解析器实现
1 |
public class MyArgumentsResolver implements HandlerMethodArgumentResolver { |
自定义注解
1 |
|
在springmvc配置文件中注册解析器
1 |
<mvc:annotation-driven> |
好了,如今解析器会把全部应用了@MyParam
注解的参数都赋值为null
。
对于如何解析原始类型参数,SpringMVC已经有了一个内置的实现——RequestParamMethodArgumentResolver
,所以彻底能够参考这个实现来自定义咱们本身的解析器。
如上所述,解析器逻辑的主要部分都在resolveArgument
方法内,这里就说说自定义该方法的实现。
1 |
|
对于如何解析对象类型参数,SpringMVC内也有了一个内置的实现——ModelAttributeMethodProcessor
,咱们也是参考这个实现来自定义咱们本身的解析器。
一样,resolveArgument
方法示例以下
1 |
|
到目前为止,不论对于原始类型或者对象类型的参数,咱们均可以自定义一个参数解析器了,可是还有一个很严重的问题存在——没法让自定义解析器和现有解析器同时生效。
举个例子,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 |
|
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/