org.springframework.web.bind.ServletRequestDataBinde
Class DataBinder
- java.lang.Object
- org.springframework.validation.DataBinder
- All Implemented Interfaces:
- PropertyEditorRegistry, TypeConverter
- Direct Known Subclasses:
- WebDataBinder
public class DataBinder
extends Object
implements PropertyEditorRegistry, TypeConverterBinder that allows for setting property values onto a target object, including support for validation and binding result analysis. The binding process can be customized through specifying allowed fields, required fields, custom editors, etc.Note that there are potential security implications in failing to set an array of allowed fields. In the case of HTTP form POST data for example, malicious clients can attempt to subvert an application by supplying values for fields or properties that do not exist on the form. In some cases this could lead to illegal data being set on command objects or their nested objects. For this reason, it is highly recommended to specify the
allowedFieldsproperty on the DataBinder.The binding results can be examined via the
BindingResultinterface, extending theErrorsinterface: see thegetBindingResult()method. Missing fields and property access exceptions will be converted toFieldErrors, collected in the Errors instance, using the following error codes:- Missing field error: "required"
- Type mismatch error: "typeMismatch"
- Method invocation error: "methodInvocation"
By default, binding errors get resolved through the
BindingErrorProcessorstrategy, processing for missing fields and property access exceptions: see thesetBindingErrorProcessor(org.springframework.validation.BindingErrorProcessor)method. You can override the default strategy if needed, for example to generate different error codes.Custom validation errors can be added afterwards. You will typically want to resolve such error codes into proper user-visible error messages; this can be achieved through resolving each error via a
MessageSource, which is able to resolve anObjectError/FieldErrorthrough itsMessageSource.getMessage(org.springframework.context.MessageSourceResolvable, java.util.Locale)method. The list of message codes can be customized through theMessageCodesResolverstrategy: see thesetMessageCodesResolver(org.springframework.validation.MessageCodesResolver)method.DefaultMessageCodesResolver's javadoc states details on the default resolution rules.This generic data binder can be used in any kind of environment. It is typically used by Spring web MVC controllers, via the web-specific subclasses
ServletRequestDataBinderandPortletRequestDataBinder.- Author:
- Rod Johnson, Juergen Hoeller, Rob Harrop, Stephane Nicoll
at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-1)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.beans.BeanWrapperImpl$BeanPropertyHandler.setValue(BeanWrapperImpl.java:344)
at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:452)
at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:278)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:95)
at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:810)
at org.springframework.validation.DataBinder.doBind(DataBinder.java:706)
at org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:189)
at org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:106)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.bindRequestParameters(ServletModelAttributeMethodProcessor.java:150)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:110)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:111)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:799)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:728)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:860)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.global.filter.AddExtraToParamsFilter.doFilter(AddExtraToParamsFilter.java:27)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478)
- locked <0x14a4> (a org.apache.tomcat.util.net.NioChannel)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
增加的就是第110行
1 binder.setFieldDefaultPrefix(parameter.getParameterName() + "!");
parameter.getParameterName()返回的是你@Controller里2RequestMapping方法参数的名字
"!"是我区分成员域与对象名的分解符...这个可以自己设置.你想设置成.也可以!也可以#也OK
只要自己能区分就行了.
测试
URL:
1 http://localhost:8080/quick-start/test18?context!stateCode=91&a!name=hehe&context!exception.message=error&a!stateCode=84
后台打印参数:
1 com.labofjet.web.ContextDTO@9344568[stateCode=91,data=<null>,exception=com.labofjet.exception.BaseException: error]
2 com.labofjet.dto.ADTO@814d736[id=<null>,name=hehe,age=<null>,value=<null>,b=0,stateCode=84]
Controller的方法签名:
1 @RequestMapping("/test18")
2 public Object index18(ContextDTO context, ADTO a) throws IOException {
3 System.out.println(context);
4 System.out.println(a);
5 return null;
6 }
原理
先简明说下原理..具体的理论我想后面等我整理下思路,介绍RequestMappingHandlerAdapter的时候再讲(反正没人看...)
SpringMVC里@Controller里的各种参数由各种argumentsResolver来解析.
解析自定义的这种DTO的argumentsResolver是ServletModelAttributeMethodProcessor这个类.
收到参数以后他怎么解析呢?
很简单呀.在我测试例子中,比如我要初始化一个context对象,SpringMVC就先把context包装成BeanWrapperImpl对象..然后把Request里的各种key-value包装成MutablePropertyValues..然后set进去就可以了.利用的是反射的知识,你有一个key,那我就看BeanWrapperImpl warp的那个对象有没有对应的属性.有就设置进去.
既然原理是这样,那怎么达到我们的目的呢?
这里又有至少2种方法:
第一种就是像我那样: binder.setFieldDefaultPrefix(parameter.getParameterName() + "!"); 这样在解析MutablePropertyValues的时候会去掉你set进去的Feild的Prefix.
第二种方法: ServletRequestDataBinder在绑定的参数的时候需要先把request转化成MutablePropertyValues,做法是:

1 public void bind(ServletRequest request) {
2 MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request);
3 MultipartRequest multipartRequest = WebUtils.getNativeRequest(request, MultipartRequest.class);
4 if (multipartRequest != null) {
5 bindMultipart(multipartRequest.getMultiFileMap(), mpvs);
6 }
7 addBindValues(mpvs, request);
8 doBind(mpvs);
9 }

也就是说:
1 MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request);
而MutablePropertyValues 其实还有一种构造方法:
1 public ServletRequestParameterPropertyValues(ServletRequest request, String prefix) {
2 this(request, prefix, DEFAULT_PREFIX_SEPARATOR);
3 }
这种方法允许你填入一个prefix...那原理和前面是一样的..
但是这种方法需要改很多类...所以没有方法一简单....
为什么不使用继承
可能会有朋友想问.改进的ArgumentResolver和原本Spring自带的基本一样,只是多了一步,为什么不继承自原本的ServletModelAttributeMethodProcessor? 毕竟修改源码方案不太好.
原因有很多,主要有2个原因:
原因1:
ServletModelAttributeMethodProcessor extends ModelAttributeMethodProcessor
resolveArgument在ModelAttributeMethodProcessor里的定义是:
public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
...........
}
是final啊!final!!!!!!!!!!!
所以我修改不了.
原因2:
一般父类定义了一个处理流程的话不能修改的话,会在子类给我们留一个扩展接口...
没错,那就是:
1 @Override
2 protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) {
3 ServletRequest servletRequest = request.getNativeRequest(ServletRequest.class);
4 ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder;
5 servletBinder.bind(servletRequest);
6 }
这个是在ServletModelAttributeMethodProcessor里覆盖了父类的方法,我们可以继承ServletModelAttributeMethodProcessor再覆盖这个bindRequestParameters方法..
但是......
这里只有2个参数啊!!!!我们需要的@Controller的参数名称的信息不在这里....我们需要这个变量:
1 public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
2 NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
3 .............
4 }
参数的信息都在这里里面..可是bindRequestParameters方法里没有传入这个参数...所以坑爹的是我们在bindRequestParameters里并不能知道@Controller里参数的名字到底是什么...
所以我们没有办法设置一个通用的绑定方法...
方法:利用其它的HandlerMethodArgumentResolver
具体方法
不改源码最简单的方法可能是不自己写ArgumentResolver,而是利用SpringMVC原有的Resolver了吧..
我们可以利用RequestResponseBodyMethodProcessor这个ArgumentResolver..
具体请参考我的另外一篇文章:
http://www.cnblogs.com/abcwt112/p/5169250.html
原理就是利用HttpMessageConverter和其它的json转化工具将request里的参数转化成java bean.这也是很简单的.
基本只要在参数前加一个@RequestBody...
方法:利用@InitBinder注解
具体:
请大家看这篇文章:
http://jinnianshilongnian.iteye.com/blog/1888474
缺点:
1.原理和方法:改源码是差不多的....都是通过修改binder设置额外属性来达到目的的,但是没传入MethodParameter parameter,所以还是不知道你的@Controller里的参数名字..只能手动指定前缀
2.貌似要绑定的时候每个Controller里都要写@InitBinder,稍微有点麻烦..当然好处是更灵活...
方法N:自己实现HandlerMethodArgumentResolver
这个方法就太多了......
请参考:
http://jinnianshilongnian.iteye.com/blog/1717180
简单总结
方法有太多太多了..不同方法可能适合不同场景,但是我觉得最简单的还是@InitBinder和@RequestBody这2种方案.
http://www.cnblogs.com/abcwt112/p/5302469.html
org.springframework.web.bind.ServletRequestDataBinde的更多相关文章
- 使用ControllerAdvice注意事项,Ambiguous @ExceptionHandler method mapped for [class org.springframework.web.bind.MethodArgumentNotValidException]
前言 ControllerAdvice非常好用,可以把系统内部的异常统一处理.用起来也很简单.比如,http://www.cnblogs.com/woshimrf/p/spring-web-400.h ...
- org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'xxxx' is not present
org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'xxx ...
- Java-API-Package:org.springframework.web.bind.annotation
ylbtech-Java-API-Package:org.springframework.web.bind.annotation 1.返回顶部 1. @NonNullApi @NonNullField ...
- Java-Class-@I:org.springframework.web.bind.annotation.PostMapping
ylbtech-Java-Class-@I:org.springframework.web.bind.annotation.PostMapping 1.返回顶部 2.返回顶部 1. package ...
- Java-Class-@I:org.springframework.web.bind.annotation.RestController
ylbtech-Java-Class-@I:org.springframework.web.bind.annotation.RestController 1.返回顶部 2.返回顶部 1. pack ...
- Java-Class-@I:org.springframework.web.bind.annotation.RequestMapping
ylbtech-Java-Class-@I:org.springframework.web.bind.annotation.RequestMapping 1.返回顶部 2.返回顶部 1. pack ...
- Java-Class-@I:org.springframework.web.bind.annotation.RequestBody
ylbtech-Java-Class-@I:org.springframework.web.bind.annotation.RequestBody 1.返回顶部 2.返回顶部 1. package ...
- org.springframework.web.bind.annotation重定向的问题
@RequestMapping(value="/redir/authcode") public ModelAndView getAuthCode(){ String authUrl ...
- spring org.springframework.web.bind.annotation 常用注解
开发中常用的注解记录,查缺补漏 Request注解 @RequestBody @RequestHeader @RequestMapping @RequestParam @RequestPart @Co ...
随机推荐
- Nginx 简单的负载均衡配置示例
http://www.cnblogs.com/xiaogangqq123/archive/2011/03/02/1969006.html 在此记录下Nginx服务器nginx.conf的配置文件说明, ...
- Ajax.Utility.RegisterTypeForAjax(typeof(_Default)) 的使用
语句的作用:页面注册方法的作用. Ajax.Utility.RegisterTypeForAjax(typeof(命名空间.类名)); 首先要在配置文件里配置 <httpHandlers> ...
- 如何使用SC命令添加删除服务
1.如何删除服务 cmd然后再输入 sc delete "服务名称" 后,回车,双引号必须为英文符号. 2.添加服务 sc create ServiceName binPath= ...
- Oracle的%type和%rowtype
1 %TYPE说明 为了使一个变量的数据类型与另一个已经定义了的变量(尤其是表的某一列)的数据类型相一致,Oracle提供 了%TYPE定义方式.当被参照的那个变量的数据类型改变了之后,这个新定义的变 ...
- iOS常见的设计模式
ios开发学习中,经常弄不清楚ios的开发模式,今天我们就来进行简单的总结和探讨~ (一)代理模式 应用场景:当一个类的某些功能需要由别的类来实现,但是又不确定具体会是哪个类实现.优势:解耦合敏捷原则 ...
- requirejs下载与配置
写在开始: requirejs有中文版api文档,可以访问http://www.requirejs.cn/home.html 下载requirejs 访问http://www.requirejs.cn ...
- UVA 11991 Easy Problem from Rujia Liu?(vector map)
Easy Problem from Rujia Liu? Though Rujia Liu usually sets hard problems for contests (for example, ...
- 【ADO.NET】3、从TXT中导入数据到数据库
数据库字段与类型id int,Name nvarchar(20),Age int TXT文本内容为 小高-20张三-18李四-19 private void btnInput_Click(object ...
- apache config directive – order, allow, deny
在对apache进行配置的时候,常看到oerder, allow, deny.现在就简单回顾一下其用法. 对于每个对于资源的请求,服务器可以配置是否允许这个请求通过.在配置当中,使用的是允许与不允许的 ...
- 开发错误日志之Unix/Linux命令未执行或无结果等且程序无错误
在Unix/Linux环境中开发时,特别要注意权限问题,否则经常找不到错误的原因,其实就是因为权限所致.