Spring MVC 概述
Spring MVC
也叫 Spring Web MVC
,属于展示层框架,是 Spring
框架的一部分。
MVC
模式作用在于分离应用程序的不同方面(业务逻辑、 UI 逻辑、输入逻辑),而 Spring MVC
框架分别对应为其提供了 模型(Model)、视图(View)、控制器(Controller) 三层架构和用于开发灵活和松散耦合的 Web 应用程序的组件,同时提供这些元素之间的松散耦合的实现。
- 模型(Model):封装了应用程序数据,通常它们将由
POJO
类组成。 - 视图(View):负责渲染模型数据,一般来说它生成客户端浏览器可以解释
HTML
输出。 - 控制器(Controller):负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染。
Spring MVC 组件功能
DispatcherServlet(前端控制器)
用户请求到达前端控制器,它就相当于 MVC 模式中的 C,DispatcherServlet 是整个流程控制的中心,相当于是 SpringMVC 的大脑,由它调用其它组件处理用户的请求,DispatcherServlet 的存在降低了组件之间的耦合性。
HandlerMapping(处理器映射器)
HandlerMapping 负责根据用户请求找到 Handler 即处理器(也就是我们所说的 Controller),SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等,在实际开发中,我们常用的方式是注解方式。
Handler(处理器)
Handler 是继 DispatcherServlet 前端控制器的后端控制器,在DispatcherServlet 的控制下 Handler 对具体的用户请求进行处理。由于 Handler 涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发 Handler。(这里所说的 Handler 就是指我们的 Controller)
HandlAdapter(处理器适配器)
通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
ViewResolver(视图解析器)
ViewResolver 负责将处理结果生成 View 视图,ViewResolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。 SpringMVC 框架提供了很多的 View 视图类型,包括:jstlView、freemarkerView、pdfView 等。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
Spring MVC 工作流程
Spring MVC
框架是围绕 DispatcherServlet
设计的,它处理所有的 HTTP
请求和响应。
Spring MVC
的请求处理工作流如下图所示:
以下是对应于到 DispatcherServlet
的传入 HTTP
请求的事件顺序:
- 用户发送请求至前端控制器
DispatcherServlet
; -
DispatcherServlet
收到请求调用HandlerMapping
处理器映射器; - 处理器映射器找到具体的处理器(可以根据 xml 配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给
DispatcherServlet
; -
DispatcherServlet
调用HandlerAdapter
处理器适配器; -
HandlerAdapter
经过适配调用具体的处理器(Controller
,也叫后端控制器); -
Controller
执行完成返回ModelAndView
; -
HandlerAdapter
将Controller
执行结果ModelAndView
返回给DispatcherServlet
; -
DispatcherServlet
将ModelAndView
传给ViewReslover
视图解析器; -
ViewReslover
解析后返回具体View
; -
DispatcherServlet
根据View
进行渲染视图(即将模型数据填充至视图中); -
DispatcherServlet
响应用户。
Spring MVC 初体验
引入依赖
创建一个 Maven 项目,在 pom.xml
中添加 spring-webmvc
及相关依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.17.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
相关配置
在 resources
目录下创建 spring-mvc.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 使用 Annotation 自动注册 Bean,只扫描 @Controller -->
<context:component-scan base-package="com.antoniopeng.hello.spring.mvc" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 注解映射的支持 -->
<mvc:annotation-driven />
<!-- 定义视图文件解析 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 静态资源映射 -->
<mvc:resources mapping="/static/**" location="/static/" cache-period="31536000"/>
</beans>
上述配置说明:
-
context:component-scan
:当前配置文件为 MVC 相关,故只需要扫描包含@Controller
的注解即可,由于spring-context.xml
配置文件中也配置了包扫描,所以还需要排除@Controller
的注解扫描。 InternalResourceViewResolver
:视图文件解析器的一种,用于配置视图资源的路径和需要解释的视图资源文件类型,这里有两个需要配置的属性prefix
(前缀)以及suffix
(后缀)。
-
prefix
:配置视图资源路径,如:/WEB-INF/views/
。 -
suffix
:配置视图资源类型,如:.jsp
。
-
mvc:resources
:静态资源映射,主要用于配置静态资源文件存放路径,如:JS、CSS、IMG 等。
在 web.xml
中配置 DispatchServlet
处理所有的 HTTP
请求和响应:
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring-mvc*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
最后还需在 web.xml
中配置字符集过滤器,用于解决中文编码问题:
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
创建视图
这里我们就采用 JSP 作为视图,在 webapp/WEB-INF/views/
目录(需要新建)下创建 index.jsp
文件,内容如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Hello Spring MVC</h1>
</body>
</html>
创建 Controller 控制器
创建 IndexController
类,即一个处理浏览器请求的接口。
@Controller
public class IndexController {
@RequestMapping(value = {"", "/index"}, method = RequestMethod.GET)
public String index() {
return "index";
}
}
项目启动成功后,访问 http://localhost:8080/index
相关注解使用说明
@Controller
在 Spring MVC
中,控制器 Controller
负责处理由 DispatcherServlet
分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个 Model
,然后再把该 Model
返回给对应的 View
进行展示。
在 Spring MVC
中提供了一个非常简便的定义 Controller
的方法,你无需继承特定的类或实现特定的接口,只需使用 @Controller
标记一个类是控制器,然后使用 @RequestMapping
和 @RequestParam
等一些注解用以定义 URL
请求和 Controller
方法之间的映射,这样的 Controller
就能被外界访问到。此外 Controller
不会直接依赖于 HttpServletRequest
和 HttpServletResponse
等 HttpServlet
对象,它们可以通过 Controller
的方法参数灵活的获取到。
但 @Controller
只是定义了一个控制器类,而使用 @RequestMapping
注解的方法才是真正处理请求的处理器。
@RequestMapping
@RequestMapping
是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
@RequestMapping
注解有六个属性:
-
value
:指定请求的实际地址。 -
method
:指定请求的类型,如 GET、POST、PUT、DELETE 等。 -
consumes
:指定处理请求的提交内容类型(Content-Type),如application/json
和text/html
。 -
produces
: 指定返回的内容类型。 -
params
:指定请求的参数值。 -
headers
:指定请求中的header
值。
@ResponseBody
该注解用于将 Controller
的方法返回的对象,通过适当的 HttpMessageConverter
转换为指定格式后,直接写入 HTTP
响应正文中。
如果需要返回自定义对象为 JSON
格式,需要添加以下依赖:
<!-- Json Begin -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- Json End -->