Spring MVC
MVC 体系结构
MVC 指 MVC 模式的某种框架,它强制性地使应用程序的输入、处理和输出分开。使用 MVC 应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。最典型的 MVC 就是 JSP + Servlet + JavaBean
的模式。
视图
视图是用户看到并与之交互的界面。对老式的 Web 应用程序来说,视图就是由 HTML
元素组成的界面,在新式的 Web 应用程序中,HTML
依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括 Adobe Flash
和像 XHTML
,XML/XSL
,WML
等一些标识语言和 Web services
。
MVC 好处是它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式。
模型
模型表示企业数据和业务规则。在 MVC 的三个部件中,模型拥有最多的处理任务。例如它可能用像 EJBs
和 ColdFusion Components
这样的构件对象来处理数据库,被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
控制器
控制器接受用户的输入并调用模型和视图去完成用户的需求,所以当单击 Web 页面中的超链接和发送 HTML
表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。
Spring MVC 简介
Spring Web MVC 是最初建立在 Servlet API 之上的 Web 框架,从一开始就包含在 Spring Framework 中。正式名称“ Spring Web MVC ”来自其源模块的名称 (spring-webmvc
),但通常称为“Spring MVC”。
Spring MVC 围绕 DispatcherServlet
设计。DispatcherServlet
的作用是将请求分发到不同的处理器。从 Spring 2.5 开始,使用 Java 5 或者以上版本的用户可以采用基于注解 @Controller
的声明方式。
Spring MVC 框架同许多其他的 MVC 框架一样, 以请求为驱动 , 围绕一个中心 Servlet 分派请求以及提供其他功能,DispatcherServlet 实际上是一个Servlet (它继承自 HttpServlet 基类)。
Spring MVC 的原理:
当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。
图为 Spring MVC 的一个较完整的流程图,实线表示 Spring MVC 框架提供的技术,不需要开发者实现,虚线表示需要开发者实现。
Spring MVC 九大组件
-
HandlerMapping
(处理器映射器)HandlerMapping
是⽤来查找Handler
的,也就是处理器,具体的表现形式可以是类,也可以是⽅法。⽐如,标注了@RequestMapping
的每个⽅法都可以看成是⼀个Handler
。Handler
负责具体实际的请求处理,在请求到达后,HandlerMapping
的作⽤便是找到请求相应的处理器Handler
和Interceptor
。 -
HandlerAdapter
(处理器适配器)HandlerAdapter
是⼀个适配器。因为 Spring MVC 中Handler
可以是任意形式的,只要能处理请求即可。但是把请求交给 Servlet 的时候,由于 Servlet 的⽅法结构都是doService(HttpServletRequest req,HttpServletResponse resp)
形式的,要让固定的 Servlet 处理⽅法调⽤ Handler 来进⾏处理,便是HandlerAdapter
的职责。 -
HandlerExceptionResolver
HandlerExceptionResolver
⽤于处理Handler
产⽣的异常情况。它的作⽤是根据异常设置ModelAndView
,之后交给渲染⽅法进⾏渲染,渲染⽅法会将ModelAndView
渲染成⻚⾯。 -
ViewResolver
ViewResolver
即视图解析器,⽤于将 String 类型的视图名和 Locale 解析为 View 类型的视图,只有⼀个resolveViewName()
⽅法。从⽅法的定义可以看出,Controller 层返回的 String 类型视图名viewName
最终会在这⾥被解析成为 View。View 是⽤来渲染⻚⾯的,也就是说,它会将程序返回的参数和数据填⼊模板中,⽣成HTML
⽂件。ViewResolver
在这个过程主要完成两件事情:ViewResolver
找到渲染所⽤的模板(第⼀件⼤事)和所⽤的技术(第⼆件⼤事,其实也就是找到视图的类型,如JSP
)并填⼊参数。默认情况下,Spring MVC 会⾃动为我们配置⼀个InternalResourceViewResolver
,是针对JSP
类型视图的。 -
RequestToViewNameTranslator
RequestToViewNameTranslator
组件的作⽤是从请求中获取viewName
。因为ViewResolver
根据viewName
查找 View,但有的Handler
处理完成之后,没有设置 View,也没有设置viewName
,便要通过这个组件从请求中查找viewName
。 -
LocaleResolver
ViewResolver
组件的resolveViewName
⽅法需要两个参数,⼀个是视图名,⼀个是 Locale。LocaleResolver
⽤于从请求中解析出 Locale,⽐如中国 Locale 是Zh-CN
,⽤来表示⼀个区域。这个组件也是i18n
的基础。 -
ThemeResolver
ThemeResolver
组件是⽤来解析主题的。主题是样式、图⽚及它们所形成的显示效果的集合。Spring MVC 中⼀套主题对应⼀个properties
⽂件,⾥⾯存放着与当前主题相关的所有资源,如图⽚、CSS
样式等。创建主题⾮常简单,只需准备好资源,然后新建⼀个“主题名.properties
”,并将资源设置进去,放在classpath
下,之后便可以在⻚⾯中使⽤了。Spring MVC 中与主题相关的类有ThemeResolver
、ThemeSource
和Theme
。ThemeResolver
负责从请求中解析出主题名,ThemeSource
根据主题名找到具体的主题,其抽象也就是Theme
,可以通过Theme
来获取主题和具体的资源。 -
MultipartResolver
MultipartResolver
⽤于上传请求,通过将普通的请求包装成MultipartHttpServletRequest
来实现。MultipartHttpServletRequest
可以通过getFile()
⽅法直接获得⽂件。如果上传多个⽂件,还可以调⽤getFileMap()
⽅法得到Map
这样的结构,MultipartResolver
的作⽤就是封装普通的请求,使其拥有⽂件上传的功能。 -
FlashMapManager
FlashMap
⽤于重定向时的参数传递,⽐如在处理⽤户订单时候,为了避免重复提交,可以处理完post
请求之后重定向到⼀个get
请求,这个get
请求可以⽤来显示订单详情之类的信息。这样做虽然可以规避⽤户重新提交订单的问题,但是在这个⻚⾯上要显示订单的信息,这些数据从哪⾥来获得呢?因为重定向时没有传递参数这⼀功能的,如果不想把参数写进URL
(不推荐),那么就可以通过FlashMap
来传递。只需要在重定向之前将要传递的数据写⼊请求(可以通过ServletRequestAttributes.getRequest()
⽅法获得)的属性OUTPUT_FLASH_MAP_ATTRIBUTE
中,这样在重定向之后的Handler
中 Spring MVC 就会⾃动将其设置到Model
中,在显示订单信息的⻚⾯上就可以直接从Model
中获取数据。FlashMapManager
就是⽤来管理FalshMap
的。
参数绑定
简单参数绑定
绑定简单数据类型参数,只需要直接声明形参即可(形参参数名和传递的参数名要保持⼀致,建议使⽤包装类型,当形参参数名和传递参数名不⼀致时可以使⽤ @RequestParam
注解进⾏⼿动映射)。
实体类参数绑定
接收 Bean 类型参数,直接形参声明即可,类型就是 Bean 的类型,形参名⽆所谓,但是要求传递的参数名必须和 Bean 的属性名保持⼀致。
包装实体类参数绑定
不管包装 Bean 与否,它⾸先是⼀个 Bean,那么就可以按照上述 Bean 的要求来:绑定时候直接形参声明即可。传参参数名和 Bean 属性保持⼀致,如果不能够定位数据项,那么通过属性名 + “.” 的⽅式进⼀步锁定数据。
日期类型处理
public class DateConverter implements Converter<String, Date> {
@Override
public Date convert(String dateStr) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
try {
Date date = simpleDateFormat.parse(dateStr);
return date;
} catch (ParseException e) {
e.printStackTrace();
}
}
}
<!-- ⾃动注册最合适的处理器映射器, 处理器适配器调⽤ handler ⽅法 -->
<mvc:annotation-driven conversion-service="conversionServiceBean"/>
<!-- 注册⾃定义类型转换器 -->
<bean id="conversionServiceBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.lagou.edu.converter.DateConverter"/>
</set>
</property>
</bean>
RESTFul 风格
REST 简介
REST(英⽂:Representational State Transfer
,简称 REST)描述了⼀个架构样式的⽹络系统, ⽐如 Web 应⽤程序。它⾸次出现在 2000 年 Roy Fielding 的博⼠论⽂中,他是 HTTP
规范的主要编写者之⼀。在⽬前主流的三种 Web 服务交互⽅案中,REST 相⽐于 SOAP(Simple Object Access Protocol
, 简单对象访问协议)以及 XML-RPC 更加简单明了,⽆论是对 URL
的处理还是对 Payload
的编码, REST 都倾向于⽤更加简单轻量的⽅法设计和实现。值得注意的是 REST 并没有⼀个明确的标准,⽽更像是⼀种设计的⻛格。它本身并没有什么实⽤性,其核⼼价值在于如何设计出符合 REST ⻛格的⽹络接⼝。
RESTFul 优点
结构清晰、符合标准、易于理解、扩展⽅便,正得到越来越多⽹站的采⽤。
RESTFul 特点
-
每一个
URI
代表 **1 **种资源; -
客户端使用
GET
、POST
、PUT
、DELETE
4 个表示操作方式的动词对服务端资源进行操作:GET
用来获取资源,POST
用来新建资源(也可以用于更新资源),PUT
用来更新资源,DELETE
用来删除资源; -
通过操作资源的表现形式来操作资源;
-
资源的表现形式是
XML
或者HTML
; -
客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息。
RESTFul 概括
看 URL
就知道要什么
看 HTTP Method
就知道干什么
看 HTTP Status Code
就知道结果如何
Spring MVC ⽀持 RESTFul ⻛格请求,具体的就是使⽤ @PathVariable
注解获取 RESTFul ⻛格的请求 URL
中的路径变量,@RequestMapping
注解配置具体的请求类型。有几种专门针对 RESTFul 请求的注解 @GetMapping
、 @PutMapping
、 @UpdateMapping
、@DeleteMapping
。
@ResponseBody 注解
@responseBody
注解的作⽤是将 Controller 的⽅法返回的对象通过适当的转换器转换为指定的格式之后,写⼊到**Response **对象的 body
区,通常⽤来返回 JSON
数据或者是 XML
数据。 注意:在使⽤此注解之后不会再⾛视图处理器,⽽是直接将数据写⼊到输⼊流中,他的效果等同于通过 Response 对象输出指定格式的数据。