Spring MVC
研究一下spring mvc
springMVC是什么?
Spring MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,Spring MVC简单的说,最主要的作用就是帮我们简化开发。
springMVC的好处?
√让我们能非常简单的设计出干净的Web层
√进行更简洁的Web层的开发;
√天生与Spring框架集成(如IoC容器、AOP等);
√支持灵活的URL到页面控制器的映射;
√非常容易与其他视图技术集成,如Velocity、FreeMarker等等,因为模型数据不放在特定的API里,而是放在一个Model里
√非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的API;
√支持Restful风格。
一个请求是如何被SpringMVC接受,处理,并返回的:
HandlerAdapter
处理器的适配器,用来绑定数据,解析数据,处理返回值等等。
如果我们没有指定默认的HandlerAdapter的时候,spring MVC 会采用默认的类RequestMappingHandlerAdapter来充当Adapter角色。 看一下RequestMappingHandlerAdapter类。
一、 springMVC 之 参数解析器 —— ArgumentResolver
SpringMVC,对大家印象最深刻的肯定它强大的参数绑定机制,简单的说就是通过SpringMVC,我们可以把前台各种复杂的数据结构组装好,后台直接可以以对象的方式接收并绑定好数据。
我们来研究一下spring MVC是如何解析参数并且绑定数据,另外,解析器分别支持哪些参数类型。
有两个参数,customArgumentResolvers和argumentResolvers,分别是自定义的参数解析器和默认的参数解析器。
接口的定义,HandlerMethodArgumentResolver。
常见的实现(HandlerMethodArgumentResolver的实现)。
非常多,
1>.RequestParamMethodArgumentResolver-->这个解析器能够为参数上加了RequestParam注解的参数提供支持
2>.RequestParamMapMethodArgumentResolver,支持参数上加了RequestParam注解并且是Map类型的参数.
3>.PathVariableMethodArgumentResolver,支持参数上加了PathVariable注解并且不是Map类型的参数,
4>.PathVariableMapMethodArgumentResolver,支持参数上加了PathVariable注解并且参数类型为Map的参数,
5>.RequestResponseBodyMethodProcessor支持参数上加了RequestBody注解的参数,
6>.RequestPartMethodArgumentResolver支持参数上了RequestPart注解的参数,
7>.ServletCookieValueMethodArgumentResolver支持参数上加了CookieValue注解的参数.
8>.ExpressionValueMethodArgumentResolver支持参数上加了Value注解的参数
简单看两个具体的实现
1>.RequestParamMethodArgumentResolver-->这个解析器能够为参数上加了RequestParam注解的参数提供支持
1)@RequestParam注解的参数
2)另一种就是简单类型,如Integer、String、Date、URI, URL,Locale
3) MultipartFile类型的文件上传
2>.RequestResponseBodyMethodProcessor—>支持参数上加了@Request注解的参数
它的代言人(封装和实现)HandlerMethodArgumentResolverComposite。
通过方法getArgumentResolver迭代去寻找可用的resolver直到TRUE;
初始化。
如何增加ArgumentResolver?
WebMvcConfigurationSupport
WebMvcConfigurerAdapter
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(resolver);
}
推荐使用
1、PageableHandlerMethodArgumentResolver
如何自定义添加ArgumentResolver?
如何实现
public Object test(Teacher teacher, Student student){
}
(1) @RequestBody的办法 (2) 自已定义一个 HandlerMethodArgumentResolver(怎么定义呢)
二、 springMVC 之 返回值处理器 —— HandlerMethodReturnValueHandler
一个请求中有入参的绑定处理,那么当然也会有响应参数的处理
HandlerMethodReturnValueHandler就是用来处理当含有@RequestMapping的方法调度完成后,后面要进行的事情。
有两个参数,customReturnValueHandlers和returnValueHandlers,分别是自定义的返回值处理器和默认的返回值处理器。
常见的实现。
也非常多
1>. ViewNameMethodReturnValueHandler返回值类型是String 或者void类型的
2>. ModelAndViewMethodReturnValueHandler 返回值类型是ModelAndView或其子类
3>. ModelMethodProcessor 返回值类型是Model或其子类
4>. ViewMethodReturnValueHandler 返回值类型是View或其子类
5>. ModelAttributeMethodProcessor 返回值有@ModelAttribute注解
6>. MapMethodProcessor 返回值是Map的
简单看两个具体的实现
1>.ViewNameMethodReturnValueHandler 支持处理返回值是void或String的
2>.RequestResponseBodyMethodProcessor 支持处理返回值被@ResponseBody注解的
接口的定义 HandlerMethodReturnValueHandler, 封装实现是HandlerMethodReturnValueHandlerComposite。
原理和参数解析器一样, 调用方法 selectHandler ,有所不同,多实现了AsyncHandlerMethodReturnValueHandler,支持处理一些异步的返回值,比如promise。
初始化。
如何添加
如何实现自定义的 HandlerMethodReturnValueHandler,
比如要实现返回类型是的某个Tid从long改成String
@RequestMapping(value = "/test3")
public Object test3(){
Trade trade = new Trade();
trade.setUserId(11878123L);
trade.setTid(91234444L);
trade.setSellerNick("q奇园");
return trade;
}
其中mavContainer.setRequestHandled(true);
标志着此次请求是否是由handler自己控制的,true表示本方法会响应请求。
使用自己的实现后,需要去除controller方法上的@ResponseBody注解,因为我们不再需要使用默认的处理器。
三、springMVC 之 消息转换器 —— HttpMessageConverter
Http请求和响应报文本质上都是一串字符串,当请求报文被Java读取之后,它会被封装成为一个ServletInputStream的输入流,供我们读取报文。响应报文则是通过一个ServletOutputStream的输出流,来输出响应报文。我们从流中,只能读取到原始的字符串报文,同样,我们往输出流中,也只能写原始的字符。但是我们在Java中, 所有东西都是以对象来做处理的。
我们不可能手动的把字符串转成对象,简单的说,从字符串到java所认识的对象这一处理过程,就是由HttpMessageConverter来完成的。
HttpInputMessage类就是http请求报文的抽象。
HttpOutputMessage类就是SpringMVC内部对一次Http响应报文的抽象
再来看看消息转换器的抽象 HttpMessageConverter。
常见的实现
StringHttpMessageConverter: 可以从请求中读和写 String data。
FormHttpMessageConverter:可以从、中读和写 form data。
ByteArrayMessageConverter:可以从请求中读和写 byte arrays。
MarshallingHttpMessageConverter:XML的转换需要使用Spring的 Marshaller 和 Unmarshaller.
MappingJacksonHttpMessageConverter:JSON的转换.
举个例子,具体实现
StringHttpMessageConverter
@RequestMapping(value="/string", method=RequestMethod.POST)
@ResponseBody
public String readString(@RequestBody String string) {
return "Read string '" + string + "'";
}
在SpringMVC进入readString方法前,会根据@RequestBody注解选择适当的HttpMessageConverter实现类来将请求参数解析到string变量中,具体来说是使用了StringHttpMessageConverter类,它的canRead()方法返回true,然后它的read()方法会从请求中读出请求参数,绑定到readString()方法的string变量中。
当SpringMVC执行readString方法后,由于返回值标识了@ResponseBody,SpringMVC将使用StringHttpMessageConverter的write()方法,将结果作为String值写入响应报文,当然,此时canWrite()方法返回true。
推荐使用
MappingJackson2HttpMessageConverter
一般加上对Java8时间的解析支持。
如何添加messageConvert?
四、请求值和返回值增强 ——RequestBodyAdvice,ResponseBodyAdvice
ResponseBodyAdvice是spring4.1的新特性,其作用是在响应体写出之前做一些处理;比如,修改返回值、对返回值统一加密等。
接口的定义
看下AbstractMessageConverterMethodProcessor类
我们一般在方法writeWithMessageConverters之前调用
从这个可以看出,我们可以在使用这些HandlerMethodReturnValueHandler的时候,我们能对返回值返回之前做统一处理。
初始化
initControllerAdviceCache();
添加ResponseBodyAdvice
首先一个实现类,实现RequestBodyAdvice,然后在类上加上注解@ControllerAdvice,比如有些请求的参数需要做加密处理,可以在此将json串解密处理,再处理。