一、参数解析绑定

1. 自定义绑定:不绑定某些项

   @InitBinder
private void initBinder(WebDataBinder dataBinder) {
dataBinder.setDisallowedFields("company", "dateCreated", "lastUpdated");
}

2. 什么时候使用DataBinder

RequestMappingHandlerAdapter 的 invokeHandlerMethod 方法
    protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response);
     //获取WebDataBinderFactory 
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
if (logger.isDebugEnabled()) {
logger.debug("Found concurrent result value [" + result + "]");
}
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}

     //注入方法参数
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
} return getModelAndView(mavContainer, modelFactory, webRequest);
}

3.  RequestMappingHandlerAdapter

1. RequestMappingHandlerAdapter中两个和参数解析器相关的成员变量
    private List<HandlerMethodArgumentResolver> customArgumentResolvers;

    private HandlerMethodArgumentResolverComposite argumentResolvers;
2. RequestMappingHandlerAdapter实例化后,会调用afterPropertiesSet(),在这里把系统默认的解析器和我们写的自定义解析器汇总
    @Override
public void afterPropertiesSet() {
// Do this first, it may add ResponseBody advice beans
initControllerAdviceCache(); if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.initBinderArgumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}

3. 调用匹配的methodArgumentResolver解析数据

参数解析绑定总结

  1. SpringMVC初始化时,RequestMappingHandlerAdapter类会把一些默认的参数解析器添加到argumentResolvers中。当SpringMVC接收到请求后首先根据url查找对应的HandlerMethod。
  2. 遍历HandlerMethod的MethodParameter数组
  3. 根据MethodParameter的类型来查找确认使用哪个HandlerMethodArgumentResolver,遍历所有的argumentResolvers的supportsParameter(MethodParameter parameter)方法。如果返回true,则表示查找成功,当前MethodParameter,使用该HandlerMethodArgumentResolver。这里确认大多都是根据参数的注解已经参数的Type来确认。
  4. 解析参数,从request中解析出MethodParameter对应的参数,这里解析出来的结果都是String类型。
  5. 转换参数,把对应String转换成具体方法所需要的类型,这里就包括了基本类型、对象、List、Set、Map。

二、输入输出转换

1.

public interface ConverterFactory<S, R> {

    /**
* Get the converter to convert from S to target type T, where T is also an instance of R.
* @param <T> the target type
* @param targetType the target type to convert to
* @return A converter from S to T
*/
<T extends R> Converter<S, T> getConverter(Class<T> targetType); }

Spring实现ConvertFactory示例

final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {

    @Override
public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
Class<?> enumType = targetType;
while (enumType != null && !enumType.isEnum()) {
enumType = enumType.getSuperclass();
}
if (enumType == null) {
throw new IllegalArgumentException "The target type " + targetType.getName() + " does not refer to an enum");
}
return new StringToEnum(enumType);
} private class StringToEnum<T extends Enum> implements Converter<String, T> { private final Class<T> enumType; public StringToEnum(Class<T> enumType) {
this.enumType = enumType;
} @Override
public T convert(String source) {
if (source.length() == 0) {
// It's an empty enum identifier: reset the enum value to null.
return null;
}
return (T) Enum.valueOf(this.enumType, source.trim());
}
} }

上面的示例不支持基数转换为枚举,改进如下:

public class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {

    public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToEnumConverter(targetType);
} private final class StringToEnumConverter<T extends Enum> implements Converter<String, T> { private Class<T> enumType; public StringToEnumConverter(Class<T> enumType) {
this.enumType = enumType;
} public T convert(String source) { try {
Integer ordinal = Integer.parseInt(source);
          //Enum的values是编译器加的
T[] values = (T[]) enumType.getDeclaredMethod("values", new Class[0]).invoke(null, new Object[0]);
return values[ordinal];
} catch (Exception e) { } try {
Method valueOf = enumType.getDeclaredMethod("valueOf", String.class);
return (T) valueOf.invoke(null, source);
} catch (Exception e) { } throw new IllegalStateException("非法参数值:" + source); }
}
}

二、json输出转换:  ObjectMapper

spring提供三种不同级别的自定义方式

参考:

spring reference: how to customer ObjectMapper

spring 参数解析绑定

SpringMVC(三):参数绑定、输入输出转换的更多相关文章

  1. springmvc(三) 参数绑定、

    前面两章就介绍了什么是springmvc,springmvc的框架原理,并且会简单的使用springmvc以及ssm的整合,从这一章节来看,就开始讲解springmvc的各种功能实现,慢慢消化 --W ...

  2. SpringMVC(三) —— 参数绑定和数据回显

    参数绑定的过程:就是页面向后台传递参数,后台接受的一个过程. 默认支持的参数类型:(就是你在方法上以形参的形式去定义一下的类型,就可以直接使用它) HttpServletRequest HttpSer ...

  3. springmvc(2)--参数绑定

    一.以实例来看springmvc各种参数绑定方式   先定义个dto类: public class RestInDto implements Serializable { private static ...

  4. (转)SpringMVC学习(六)——SpringMVC高级参数绑定与@RequestMapping注解

    http://blog.csdn.net/yerenyuan_pku/article/details/72511749 高级参数绑定 现在进入SpringMVC高级参数绑定的学习,本文所有案例代码的编 ...

  5. <SpringMvc>入门三 参数绑定

    1.get请求 <%--请求参数的绑定--%> <%--get请求参数--%> <a href="/param/testParam1?username=tom& ...

  6. SpringMVC【参数绑定、数据回显、文件上传】

    前言 本文主要讲解的知识点如下: 参数绑定 数据回显 文件上传 参数绑定 我们在Controller使用方法参数接收值,就是把web端的值给接收到Controller中处理,这个过程就叫做参数绑定.. ...

  7. 【SpringMVC】参数绑定

    一.概述 1.3 参数绑定过程 1.2 @RequestParam 二.自定义绑定使用属性编辑器 2.1 使用WebDataBinder(了解) 2.2 使用WebBindingInitializer ...

  8. SpringMVC学习--参数绑定

    spring参数绑定过程 从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上.springmvc中,接收页面提交的数据是通过方法形参来接收 ...

  9. SpringMVC中参数绑定

    SpringMVC中请求参数的接收主要有两种方式, 一种是基于HttpServletRequest对象获取, 另外一种是通过Controller中的形参获取 一  通过HttpServletReque ...

  10. SpringMVC学习笔记之二(SpringMVC高级参数绑定)

    一.高级参数绑定 1.1 绑定数组 需求:在商品列表页面选中多个商品,然后删除. 需求分析:功能要求商品列表页面中的每个商品前有一个checkbok,选中多个商品后点击删除按钮把商品id传递给Cont ...

随机推荐

  1. 在linux环境下编译android so库

    (1) 配置Android NDK环境 (2) mk文件编写 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # OpenCV OPENCV_CA ...

  2. Java关键字-----------------java中synchronized关键字的用法

    在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...

  3. MySQL5.7.19 服务挂掉 自动关闭 mysqld got exception 0xc000001d win 2008R2

    在mysql 官网看到mysqld got exception 0xc000001dThis error message occurs because you are also using a CPU ...

  4. 安卓开发笔记——关于开源项目SlidingMenu的使用介绍(仿QQ5.0侧滑菜单)

    记得去年年末的时候写过这个侧滑效果,当时是利用自定义HorizontalScrollView来实现的,效果如下: 有兴趣的朋友可以看看这篇文件<安卓开发笔记——自定义HorizontalScro ...

  5. swoole webSocket服务

    socket.php <?php //创建websocket服务器对象,监听0.0.0.0:9502端口 $ws = ); //监听WebSocket连接打开事件 (刚打开的时候会给客户端发送 ...

  6. java面试(2)--大数据相关

    第一部分.十道海量数据处理面试题 1.海量日志数据,提取出某日访问百度次数最多的那个IP. 首先是这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文件中.注意到IP是32位的,最多有个2^ ...

  7. puppt服务资源管理

    1.服务资源的特性     controllable 提供变量控制     enableable   可以启动 停止服务   refreshable  可以重启服务   2.可用参数: ensure ...

  8. 【zheng环境准备】安装redis

    1.下载源码,解压缩后编译源码 wget http://download.redis.io/release/redis-2.8.3.tar.gz tar -xzf redis-.tar.gz cd r ...

  9. Code first 数据迁移

    前段时间用到了EF,整理一下 EF ,全称Entity FramWork.就是微软以ADO.NET为基础发展的所谓ORM(对象关系映射框架,或者说是数据持久化框架). 简单说就是根据实体对象操作数据库 ...

  10. python-Beautiful rose

    热爱python,热爱生活,python需要浪漫,让我带大家走进浪漫的国度...写的不好的地方请大佬指教 import turtle import time class Rose: def __ini ...