SpringMVC中WebDataBinder的应用及原理
- @InitBinder
- public void initBinder(WebDataBinder binder) throws Exception {
- binder.registerCustomEditor(Long.class, new CustomNumberEditor(Long.class, true));
- binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
- }
- public final Object resolveArgument(
- MethodParameter parameter, ModelAndViewContainer mavContainer,
- NativeWebRequest request, WebDataBinderFactory binderFactory)
- throws Exception {
- String name = ModelFactory.getNameForParameter(parameter);
- Object target = (mavContainer.containsAttribute(name)) ?
- mavContainer.getModel().get(name) : createAttribute(name, parameter, binderFactory, request);
- WebDataBinder binder = binderFactory.createBinder(request, target, name);
- if (binder.getTarget() != null) {
- bindRequestParameters(binder, request);
- validateIfApplicable(binder, parameter);
- if (binder.getBindingResult().hasErrors()) {
- if (isBindExceptionRequired(binder, parameter)) {
- throw new BindException(binder.getBindingResult());
- }
- }
- }
- mavContainer.addAllAttributes(binder.getBindingResult().getModel());
- return binder.getTarget();
- }
每次请求到来后的参数解析都会利用WebDataBinderFactory创建一个binder对象,然后从这个binder中取得最终解析好的参数对象。WebDataBinderFactory是在InvocableHandlerMethod中定义的,即不同的Controller方法有着不同的WebDataBinderFactory。其实创建binder的同时还对binder进行了初始化,这个初始化过程就会执行Controller中的InitBinder方法。InitBinderDataBinderFactory实现了初始化binder的方法:
- public void initBinder(WebDataBinder binder, NativeWebRequest request) throws Exception {
- for (InvocableHandlerMethod binderMebinderMethod thod : this.binderMethods) {
- if (isBinderMethodApplicable(binderMethod, binder)) {
- Object returnValue = binderMethod.invokeForRequest(request, null, binder);
- if (returnValue != null) {
- throw new IllegalStateException("@InitBinder methods should return void: " + binderMethod);
- }
- }
- }
- }
- protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) {
- ServletRequest servletRequest = request.getNativeRequest(ServletRequest.class);
- ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder;
- servletBinder.bind(servletRequest);
- }
- public void bind(ServletRequest request) {
- MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request);
- MultipartRequest multipartRequest = WebUtils.getNativeRequest(request, MultipartRequest.class);
- if (multipartRequest != null) {
- bindMultipart(multipartRequest.getMultiFileMap(), mpvs);
- }
- addBindValues(mpvs, request);
- doBind(mpvs);
- }
这个方法跟依赖注入的过程非常相似,依赖注入是根据属性在容器中找到满足条件的对象,然后设置到当前的bean中。而上面的方法不是在容器中查找,而是从Request中获取,即把Request中的请求参数注入到binder的target中去。此时进行类型转换的就是刚刚注册的PropertyEditor,因为InitBinder方法每次都会执行,所以使用者可以在每个Controller中对相同类型的参数定义不同的参数转换方式。
经过了bindRequestParameters方法的处理,现在binder中target(即HandlerMethod的参数)已经包含了Request中的请求参数。
- private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
- Class<?> handlerType = handlerMethod.getBeanType();
- Set<Method> methods = this.dataBinderFactoryCache.get(handlerType);
- if (methods == null) {
- methods = HandlerMethodSelector.selectMethods(handlerType, INIT_BINDER_METHODS);
- this.dataBinderFactoryCache.put(handlerType, methods);
- }
- List<InvocableHandlerMethod> binderMethods = new ArrayList<InvocableHandlerMethod>();
- for (Method method : methods) {
- InvocableHandlerMethod binderMethod = new InvocableHandlerMethod(handlerMethod.getBean(), method);
- binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers);
- binderMethod.setDataBinderFactory(new DefaultDataBinderFactory(this.webBindingInitializer));
- binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
- binderMethods.add(binderMethod);
- }
- return createDataBinderFactory(binderMethods);
- }
SpringMVC中WebDataBinder的应用及原理的更多相关文章
- 详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]
目录 前言 现象 源码分析 HandlerMethodArgumentResolver与HandlerMethodReturnValueHandler接口介绍 HandlerMethodArgumen ...
- 详解SpringMVC中Controller的方法中参数的工作原理
Spring MVC中Controller的处理方法的参数可以是Integer,String,自定义对象,ServletRequest,ServletResponse,ModelAndView等等,非 ...
- 详解SpringMVC中Controller的方法中参数的工作原理——基于maven
转自:http://www.tuicool.com/articles/F7byQn 前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:ht ...
- 【MVC - 参数原理】详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]
前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:http://www.cnblogs.com/fangjian0423/p/spring ...
- SpringMVC中Controller
详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析] 目录 前言 现象 源码分析 HandlerMethodArgumentResolver与HandlerMethodR ...
- SpringMVC中注解@RequestBody和@ResponseBody的使用区别
首先上源码 在面试时经常会问到我们如何使用SpringMVC将Http请求转换为java对象,或者又是问如何将结果转换为java的呢? SpringMVC在接收到请求之后HandlerMapping像 ...
- 8.springMVC中的RESTful架构风格
RESTful架构:是一种设计的风格,并不是标准,只是提供了一组设计原则和约束条件,也是目前比较流行的一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以正得到越来越多网站的采用. 关于 ...
- JavaEE开发之SpringMVC中的静态资源映射及服务器推送技术
在上篇博客中,我们聊了<JavaEE开发之SpringMVC中的自定义拦截器及异常处理>.本篇博客我们继续的来聊SpringMVC的东西,下方我们将会聊到js.css这些静态文件的加载配置 ...
- 将SpringMVC中的HttpMessageConverter替换为Gson
读者们看到这个标题也许会感到奇怪,SpringMVC中默认的HttpMessageConverter不是Jackson吗,但是我在使用的过程中发现Jackson并不好用,如果有一些复杂的嵌套类型,当然 ...
随机推荐
- 在windows上搭建redis集群
一 所需软件 Redis.Ruby语言运行环境.Redis的Ruby驱动redis-xxxx.gem.创建Redis集群的工具redis-trib.rb 二 安装配置redis redis下载地址 ...
- Rest_framework-1
目录 一.认证 二.权限 三.限制访问频率 四.总结 一.认证(补充) 认证请求头 #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_fra ...
- 解决hash冲突的办法
1.开发定址法 2.再哈希法 3.链地址法 4.建立一个公共溢出区
- 虚拟环境virtualenv和virtualenvwrapper(转)
virtualenv是用来创建一个独立的Python虚拟环境的工具,通过virtualenv可以创建一个拥有独立的python版本和安装库的虚拟开发环境.这样一来我们就可以在虚拟环境中安装各种各种所需 ...
- Java集合(7):HashMap
一.HashMap介绍 HashMap是基于哈希表的 Map 接口的实现,以key-value的形式存在.在HashMap中,key-value总是会当做一个整体来处理,系统会根据hash算法来来计算 ...
- SVN项目迁移到GIT
源项目为SVN项目, 复制一份出来后. 在VS里无法修改 源码管理器的插件为GIT. 解决方法: 删除SVN插件信息 在解决方案文件中. 删除以下SVN信息就可以了 删除后:
- $python数据分析基础——初识numpy库
numpy库是python的一个著名的科学计算库,本文是一个quickstart. 引入:计算BMI BMI = 体重(kg)/身高(m)^2 假如有如下几组体重和身高数据,让求每组数据的BMI值: ...
- Mysql5.7 用户与授权
mysql -uroot -proot MySQL5.7 mysql.user表没有password字段改 authentication_string: 一. 创建用户: 命令:CREATE USER ...
- linux命令(6/9):watch命令
watch是一个非常实用的命令,基本所有的Linux发行版都带有这个小工具,如同名字一样,watch可以帮你监测一个命令的运行结果,省得你一遍遍的手动运行.在Linux下,watch是周期性的执行下个 ...
- linux:查看磁盘硬件信息hdparm,smartctl
smartctl 命令 这个一个用于控制和监控支持smart技术的硬盘的命令.通常配合 -a 选项我们可以查看到比较详尽的硬盘信息(比如序列号.硬盘容量.已运行时间.硬盘健康状况等).用法如下: sm ...