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
allowedFields
property on the DataBinder.The binding results can be examined via the
BindingResult
interface, extending theErrors
interface: 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
BindingErrorProcessor
strategy, 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
/FieldError
through itsMessageSource.getMessage(org.springframework.context.MessageSourceResolvable, java.util.Locale)
method. The list of message codes can be customized through theMessageCodesResolver
strategy: 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
ServletRequestDataBinder
andPortletRequestDataBinder
.- 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 ...
随机推荐
- web 电子商务网站开发笔记整理
js只保留整数,向上取整,四舍五入,向下取整等函数 来源:ab蓝学网整理 时间:2014-07-09 点击:30131 简介:WEB前端|1.丢弃小数部分,保留整数部分parseInt(5/2)2.向 ...
- bootstrap.css.map这个文件有何用处?该怎能使用它?
. ├── bootstrap.css ├── bootstrap.css.map ├── bootstrap.min.css ├── bootstrap-theme.css ├── bootstra ...
- portal单点登录的原理与实现还有ESB
portal单点登录的原理与实现还有ESB 在毕业论文中有描述到这一点.我给我出的截图
- linq to ef(相当于sql中in的用法)查询语句
select * from DoctorInfo doctor where doctor.HosDepartId in (select Id from HospitalDepartment hd wh ...
- MySQL分区表例子——List分区
列表分区(List分区) 这里假设表中有一个sale_item_type 字段,数据类型为INT 型 当sale_item_type 为1,3,5的时候,作为一个分区 当sale_item_type ...
- java对图片的裁剪(包括来自网络的图片)
import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.File; import java.io. ...
- 如何恢复oracle中已删除的表
在9i中Oracle引入了flashback的概念,可以将数据返回到某个时间点,但对于诸如drop/truncate等DDL语句却尚不支持.进入Oracle10g,这一缺陷得到了弥补.可以将丢失掉的表 ...
- html-----015---HTML ASCII 参考手册
HTML 和 XHTML 用标准的 7 比特 ASCII 代码在网络上传输数据. 7 比特 ASCII 代码可提供 128 个不同的字符值. 7 比特 可显示的 ASCII 代码 <html&g ...
- Cesium的api之关于viewer(二)
1.构建一个viewer,如下创建:options的参数根据实际情况,进行设定 var viewer = new Cesium.Viewer('cesiumContainer', { //Start ...
- fastjson的坑 com.alibaba.fastjson.JSONObject cannot be cast to xxx
解析json对象时,使用了new TypeReference()对象 fastjson会对解析的对象类型进行缓存 new TypeReference<ResultData>(){} ...