spring MVC处理请求过程及配置详解
本文主要梳理下Spring MVC处理http请求的过程,以及配置servlet及业务application需要的常用标签,及其包含的意义。
spring MVC处理请求过程
首先看一个整体图

简单说下各步骤:
handlerMapping
handlerMapping将请求映射到处理器,即图中的HandlerExecutionChain。依据是请求中的信息:请求URL(value),请求参数(params),请求方法(method),请求头(headers)。处理器方法从中获取参数,相关的标注有PathVariable、RequestParam、RequestHeader、CookieValue等。
- 请求方法包括GET、POST、DELETE、HEAD、OPTIONS、PUT、TRACE等。大多数浏览器只支持GET和POST,解决方法:客户端post提交数据,添加“_method”参数来指定特定的方法;服务端配置HiddenHttpMethodFilter。spring会根据_method的值模拟特定的HTTP方法,从而被controller正确获取。
DataBinder
DataBinder处理servletRequest中的消息,对其进行数据类型转换(conversionService接口)和数据格式化(Formatter接口)操作,然后填充到入参对象中。再调用validator组件,做数据校验。把conversion和validator的结果放在BindingResult中。即BindingResult存储入参对象和校验错误对象,可直接作为controller处理方法的参数。
看一下ConfigurableWebBindingInitializer(封装了WebDataBinder,继承自DataBinder)的代码:
//处理BindingResult
private BindingErrorProcessor bindingErrorProcessor;
//数据校验
private Validator validator;
//数据类型转换
private ConversionService conversionService;
- 这里的convert做什么工作呢?比如controller处理方法的参数为User,包含用户名、密码、昵称等,而用户传入的参数是userName:password:nick这样的特定格式,这时就需要一个converter处理String2User。
HandlerExecutionChain
HandlerExecutionChain,执行链。包含一个处理器Handler(controller中的处理方法)及若干拦截器HandlerInterceptor。处理过程如下:

- handlerInterceptor如果处理出错,就会直接返回结果,而不会到达handler。
- 在进入handler之前,执行handlerInterceptor的preHandler方法;handler处理之后,执行handlerInterceptor的postHandler方法;相应被渲染后,执行handlerInterceptor的afterCompletion方法。
viewResolve
视图对象是一个Bean,视图对象由视图解析器负责实例化(感觉有点像handler和handlerAdapter)。可装配多个视图解析器,配置优先级。
常用标签理解
<mvc:annotation-driven/>
- 默认创建并注册DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter。如果配置自定义的,则替换默认的。
- 默认注册FormattingConversionServiceFactoryBean(一个默认的ConversionService)。自定义conversionService使用属性conversion-service来组装。
- 默认装配LocalValidatorFactoryBean,支持controller方法的入参标注@Valid。
<mvc:default-servlet-handler />
- 默认配置DefaultServletHttpRequestHandler,检查URL,若是静态资源,则将请求转由web应用服务器默认的servlet处理。否则,由DispatcherServlet处理。
- 如果web应用服务器默认servlet的名字不是“default”,则需要配置
<mvc:default-servlet-handler default-servlet-name="yourServerDefaultServletName"/>
<mvc:resources/>
- 由Spring MVC框架自己处理静态资源,并添加一些有用的附加功能。可将多个路径映射为一个逻辑路径;按照配置路径顺序查找,只要查找到,即返回。
其他
ExceptionHandler
标注在方法上,指定处理特定异常的方法。作用域:类。创建一个BaseController,里面指定各种异常的处理方法;其他controller继承BaseController。
定义全局处理方法:配置SimpleMappingExceptionResolver 。
示例:
//处理一种异常@ExceptionHandler(RuntimeException.class)
//处理多种异常
@ExceptionHandler({BindException.class,RuntimeException.class})
@ResponseBody
public Map<String, Object> bindExceptionHandler(BindException e, HttpServletResponse response, HttpServletRequest request) {
HashMap body = new HashMap();
body.put("status", Integer.valueOf(1));
response.setStatus(200);
return body;
}
RequestBody
标注RequestBody,将参数按照属性名匹配的方式,填充入POJO。支持级联的属性名。如下,为类结构图,则传递user参数时,应该写
为userName=tom&dept.deptId=1&dept.address.tel=102

@RequestBody/ResponseBody
@RequestBody/ResponseBody是开发中常用的注解。
- 数据类型转换主要通过converter来实现,接口:
HttpMessageConverter<T>,作用:将请求信息转换为一个对象,将对象输出为响应信息。相应接口:canRead,read,canWrite,write。相关标注:RequestBody,ResponseBody。 - 当controller处理方法使用到@RequestBody/ResponseBody或者HttpEntity/ResponseEntity时,才使用HttpMessageConverter对请求/响应消息进行处理。
- 处理表单数据的FormHttpMessageConverter,处理的数据类型为MultiValueMap,所以如果要模拟post请求,需要将参数封装成MultiValueMap,看这个示例。
关于HttpMessageConverter的装配和使用,看下源代码:
RequestMappingHandlerAdapter 的属性包含如下几个:
private HandlerMethodArgumentResolverComposite argumentResolvers;
//参数解析器
private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;
//请求报文和对象之间的转换
private List<HttpMessageConverter<?>> messageConverters;
//封装DataBinder,用于数据类型转换、数据格式化、数据校验
private WebBindingInitializer webBindingInitializer;
其中HandlerMethodArgumentResolverComposite 是包含了一个HandlerMethodArgumentResolver的List,用于解析参数。 WebBindingInitializer接口 封装了WebDataBinder(继承自DataBinder),前面ConfigurableWebBindingInitializer是它的一个具体实现。 HttpMessageConverter就是我们配置的数据转换器。
RequestMappingHandlerAdapter构造方法中会添加默认的几个HttpMessageConverter:
public RequestMappingHandlerAdapter() {
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false); // See SPR-7316
this.messageConverters = new ArrayList<HttpMessageConverter<?>>();
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(stringHttpMessageConverter);
this.messageConverters.add(new SourceHttpMessageConverter<Source>());
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
}
设置之后,将messageConverters添加到参数解析其中:
@Override
public void afterPropertiesSet() {
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
......
}
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
// Annotation-based argument resolution
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
......
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
......
return resolvers;
}
可以看到,将messageConverters放入RequestResponseBodyMethodProcessor中。然后再在RequestResponseBodyMethodProcessor中使用具体的messageConverters转换报文和对象,同时对数据进行校验。
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
//使用MessageConverters读取报文,并转为对象
Object argument = readWithMessageConverters(webRequest, parameter, parameter.getGenericParameterType());
//创建WebDataBinder,获取对象参数
String name = Conventions.getVariableNameForParameter(parameter);
WebDataBinder binder = binderFactory.createBinder(webRequest, argument, name);
//参数校验,结果存入 binder.getBindingResult()
if (argument != null) {
validate(binder, parameter);
}
//将参数处理结果 binder.getBindingResult()放入mavContainer
mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
return argument;
}
这里,把HttpMessageConverter和WebDataBinder的顺序搞清楚了。其实,既然HttpMessageConverter是用来解析报文为对象的,肯定是放在参数处理第一步的。
spring MVC处理请求过程及配置详解的更多相关文章
- 转载 Spring、Spring MVC、MyBatis整合文件配置详解
Spring.Spring MVC.MyBatis整合文件配置详解 使用SSM框架做了几个小项目了,感觉还不错是时候总结一下了.先总结一下SSM整合的文件配置.其实具体的用法最好还是看官方文档. ...
- Spring MVC、MyBatis整合文件配置详解
Spring:http://spring.io/docs MyBatis:http://mybatis.github.io/mybatis-3/ Building a RESTful Web Serv ...
- Spring、Spring MVC、MyBatis整合文件配置详解
原文 http://www.cnblogs.com/wxisme/p/4924561.html 主题 MVC模式MyBatisSpring MVC 使用SSM框架做了几个小项目了,感觉还不错是时候总 ...
- 【转】Spring、Spring MVC、MyBatis整合文件配置详解
见:http://www.tuicool.com/articles/eyINveF web.xml的配置 web.xml应该是整个项目最重要的配置文件了,不过servlet3.0中已经支持注解配置方式 ...
- Spring、Spring MVC、MyBatis整合文件配置详解2
使用SSM框架做了几个小项目了,感觉还不错是时候总结一下了.先总结一下SSM整合的文件配置.其实具体的用法最好还是看官方文档. Spring:http://spring.io/docs MyBatis ...
- Spring、Spring MVC、MyBatis 整合文件配置详解
使用SSM框架做了几个小项目了,感觉还不错是时候总结一下了.先总结一下SSM整合的文件配置.其实具体的用法最好还是看官方文档. Spring:http://spring.io/docs MyBatis ...
- spring MVC处理请求过程
spring MVC处理请求过程 首先看一个整体图 简单说下各步骤: handlerMapping handlerMapping将请求映射到处理器,即图中的HandlerExecutionChain. ...
- Spring Boot 启动(二) 配置详解
Spring Boot 启动(二) 配置详解 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring Boot 配置 ...
- SSM ( Spring 、 SpringMVC 和 Mybatis )配置详解
使用 SSM ( Spring . SpringMVC 和 Mybatis )已经有三个多月了,项目在技术上已经没有什么难点了,基于现有的技术就可以实现想要的功能,当然肯定有很多可以改进的地方.之前没 ...
随机推荐
- Windows 10 IoT Serials 9 – 如何利用IoTCoreAudioControlTool改变设备的音频设备
大家知道,在Windows 10 IoT Core上,如果用户外接了USB声卡.带有麦克风的摄像头之类的硬件,就会有多个音频设备可以用.但是,系统目前并没有提供直接的UI来设置音频的输入或者输出设备. ...
- eclipse 打包 jar 到 Linux上运行
1.选择需要打包的项目,右键 Export 2.选择Runnable JAR file,然后点击 Next 3.选择jar包运行的main类,以及定义jar包的名字,保存的地方 4.将 导出来的 ja ...
- 【js】操作checkbox radio 的操作总结
摘要 总是忘记checkbox radio 的具体操作,总是坑自己,总结下记下来 html <input type="checkbox" value="1" ...
- android-iconify 使用详解
android-iconify 使用详解 有图有真相 1.android-iconify简介 iconify的github地址:https://github.com/JoanZapata/androi ...
- MySql 求一段时间范围内的每一天,每一小时,每一分钟
平常经常会求一段时间内的每一天统计数据,或者每一时点的统计数据.但是mysql本身是没有直接获取时点列表的函数或表.下面是自己用到的一些方法,利用临时变量和一个已存在的比较多数据(这个需要根据实际情况 ...
- Java GC - 垃圾回收机制
1.简介 对于Java developer来说,了解JVM GC工作原理能够帮助我们开发出更优秀的应用,同时在处理JVM瓶颈时能够更加自由.在最近一年的应用开发中能体会到这些知识带来的好处,并且让我们 ...
- oracle ORA-00604/ORA-01653
问题描述: ORA-00604: error occurred at recursive SQL level 1ORA-01653: unable to extend table SYS.AUD$ b ...
- 从.net到java,记录下这三个月的工作
从事.NET开发已经4个年头,经过十余个项目的学习与沉淀,终于有了一套自己熟悉并且相对完善的技术体系,面对未知,不再惧怕.期间完成并广泛用于公司项目的作品包括: abp的二次开发框架BodeAbp 基 ...
- 自制刻度尺-前端简易实现"腾讯信用"界面
依据我现有的知识,在前端上"简易"的实现了腾讯信用的界面,同时自己自制了一个竖直的刻度尺插件,曲线的位置可以根据传入的数值动态的改变,这次主要也想总结一下关于jQuery中exte ...
- ChromeDriver,IEDriver,Firefox配置
ChromeDriver: 下载ChromeDriver.exe,放入某个文件夹,如C:\Program Files (x86)\Google\Chrome\Application,把此路径加入pat ...