SpringMVC快速入门及解析
SpringMVC快速入门及解析
本篇整理 SpringMVC 的概述与快速入门、执行流程与组件解析、核心注解(@RequestMapping、@Controller)、XML 配置解析,以及转发和重定向。
1. SpringMVC 概述及快速入门
1.1 概述
SpringMVC 是一种基于 Java 的、实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架,属于 Spring Framework 的后续产品,已经融合在 Spring 中。
SpringMVC 已经成为目前最主流的 MVC 框架之一,并且随着 Spring 3.0 的发布,全面超越 Struts2,成为最优秀的 MVC 框架。它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口。同时它还支持 RESTful 编程风格的请求。
1.2 快速入门
需求:客户端发起请求,服务器端接收请求,执行逻辑并进行视图跳转。
开发步骤:
- 使用 Maven 骨架创建 Maven web 项目并导入坐标;
- 创建 Controller 类(类似于 Servlet)和视图页面;
- 使用注解配置 Controller 类中业务方法的映射地址;
- 配置 SpringMVC 核心文件 spring-mvc.xml;
- 配置 SpringMVC 核心控制器 DispatcherServlet;
- 浏览器发起请求测试。
1.2.1 使用 Maven 骨架创建 Maven web 项目并导入坐标
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qfedu</groupId>
<artifactId>01_springmvc_start</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<name>01_springmvc_start Maven Webapp</name>
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<scope>provided</scope>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>1.2.2 创建 Controller 类和视图页面
HelloController.java:
// 指定这是一个控制器类
@Controller
// 指定这个控制器的地址
@RequestMapping("/hello")
public class HelloController {
/**
* 在访问时要使用类上 @RequestMapping 中的路径和方法上 @RequestMapping 中的路径才能访问到该方法
* 如果在视图解析器中没有配置前缀和后缀,文件的路径和后缀不能省略
* 默认以转发的方式访问视图
* @return 视图的位置
*/
@RequestMapping("/hello")
public String hello() {
return "/jsp/success.jsp";
}
}在 web 目录下新建 jsp 目录,在该目录中创建 success.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>success</title>
</head>
<body>
<p>success</p>
</body>
</html>1.2.3 配置 SpringMVC 核心文件 spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<!-- 配置包扫描 -->
<context:component-scan base-package="com.qfedu.controller" />
</beans>1.2.4 配置 SpringMVC 核心控制器 DispatcherServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- 配置SpringMVC核心控制器,其本质上就是一个Servlet -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- 配置SpringMVC配置文件,使SpringMVC核心控制器能够加载 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!-- tomcat启动就加载 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>1.2.5 浏览器发起请求测试
http://localhost:8080/hello/hello2. SpringMVC 组件解析
2.1 SpringMVC 执行流程(要能自己描述)

完整执行流程如下:
- 用户发送请求至前端控制器 DispatcherServlet;
- DispatcherServlet 收到请求后调用 HandlerMapping 处理器映射器;
- 处理器映射器找到具体的处理器(可以根据 XML 配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给 DispatcherServlet;
- DispatcherServlet 调用 HandlerAdapter 处理器适配器;
- HandlerAdapter 经过适配调用具体的处理器(Controller,也叫后端控制器);
- Controller 执行完成返回 ModelAndView;
- HandlerAdapter 将 Controller 执行结果 ModelAndView 返回给 DispatcherServlet;
- DispatcherServlet 将 ModelAndView 传给 ViewResolver 视图解析器;
- ViewResolver 解析后返回具体 View;
- DispatcherServlet 根据 View 进行渲染视图(即将模型数据填充至视图中);
- DispatcherServlet 响应用户。
2.2 SpringMVC 各组件简介
| 组件 | 职责 |
|---|---|
| DispatcherServlet(前端控制器) | 整个流程控制的中心,调用其他组件处理用户请求 |
| HandlerMapping(处理器映射器) | 根据用户请求找到 Handler 即处理器 |
| HandlerAdapter(处理器适配器) | 对处理器进行执行,适配器模式的应用 |
| Handler(处理器) | 即我们编写的 Controller,处理具体的用户请求 |
| ViewResolver(视图解析器) | 将逻辑视图名解析为物理视图名,生成 View 视图对象 |
| View(视图) | 将模型数据通过页面展示给用户 |
下面分别展开说明。
2.2.1 前端控制器 DispatcherServlet
用户请求到达前端控制器,它就相当于 MVC 模式中的 C。DispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求。DispatcherServlet 的存在降低了组件之间的耦合性。
2.2.2 处理器映射器 HandlerMapping
HandlerMapping 负责根据用户请求找到 Handler 即处理器。SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式、实现接口方式、注解方式等。
2.2.3 处理器适配器 HandlerAdapter
通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用。通过扩展适配器可以对更多类型的处理器进行执行。
2.2.4 处理器 Handler
就是我们上面写的 Controller。由 DispatcherServlet 把用户请求转发到 Handler,由 Handler 对具体的用户请求进行处理。
2.2.5 视图解析器 ViewResolver
ViewResolver 负责将处理结果生成 View 视图。ViewResolver 首先根据逻辑视图名解析成物理视图名(即具体的页面地址),再生成 View 视图对象,最后对 View 进行渲染,将处理结果通过页面展示给用户。
2.2.6 视图 View
SpringMVC 框架提供了很多 View 视图类型的支持,包括:jspView、freemarkerView、pdfView 等。最常用的视图就是 JSP。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,具体页面由程序员根据业务需求开发。
3. SpringMVC 注解解析
3.1 @RequestMapping
作用:用于建立请求 URL 和处理请求类及方法之间的对应关系。
位置:
- 类上:请求 URL 的第一级访问目录。此处不写的话,就相当于应用的根目录;
- 方法上:请求 URL 的第二级访问目录,与类上
@RequestMapping标注的一级目录一起组成完整访问路径。
属性:
| 属性 | 说明 |
|---|---|
value | 用于指定请求的 URL,它和 path 属性的作用是一样的 |
method | 用于指定请求的方式 |
params | 用于指定限制请求参数的条件 |
限制请求方式的示例:
@RequestMapping(value = "/hello", method = RequestMethod.POST)
public String hello() {
return "/jsp/success.jsp";
}params 用于指定限制请求参数的条件,它支持简单的表达式,要求请求参数的 key 和 value 必须和配置的一模一样。例如:
params = {"accountName"},表示请求参数中必须有 accountName;params = {"money!=100"},表示请求参数中 money 不能是 100。
@RequestMapping(value = "/hello", method = RequestMethod.GET, params = {"username"})
public String hello() {
return "/jsp/success.jsp";
}如果只是想限制请求的方式,可以使用如下注解进行地址映射:
@GetMapping(地址):限制只接收 get 请求;@PostMapping(地址):限制只接收 post 请求。
3.2 @Controller
指定这是一个控制器类。这个注解的作用和 @Component 作用是一样的,用来配置 bean 让 Spring 容器进行管理。配置了 @Controller 注解之后,需要在 SpringMVC 配置文件中配置包扫描:<context:component-scan />。
4. SpringMVC 的 XML 配置解析
配置视图解析器:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置视图名称前缀 -->
<property name="prefix" value="/jsp/" />
<!-- 配置视图名称后缀 -->
<property name="suffix" value=".jsp" />
</bean>配置前缀和后缀之后,修改 HelloController 中的方法,视图名只需写逻辑名称:
/**
* 配置视图解析器的前缀后缀之后,视图的写法
*/
@RequestMapping("/hello")
public String hello() {
return "success";
}5. 转发和重定向
我们在 Controller 中写的方法,默认以转发的方式跳转到相应名称的视图。如果希望明确配置转发和重定向,在视图名称前加上 forward: 或者 redirect::
/**
* 转发
*/
@RequestMapping("/hello1")
public String hello1() {
return "forward:/jsp/success.jsp";
}
/**
* 重定向
*/
@RequestMapping("/hello2")
public String hello2() {
return "redirect:/jsp/success.jsp";
}两者的关键区别:转发是服务器内部的跳转,浏览器地址栏不变,request 域中的数据可以带到目标页面;重定向是浏览器重新发起一次新的请求,地址栏会发生变化,request 域中的数据会丢失。
6. 本章小结
- SpringMVC 是基于 MVC 设计模式的请求驱动型 Web 框架,通过注解即可将普通 Java 类变为控制器;
- 快速入门的固定套路:导入坐标 —— 写 Controller —— 配 spring-mvc.xml 包扫描 —— 在 web.xml 注册 DispatcherServlet —— 测试;
- 执行流程围绕三大组件展开:HandlerMapping 找处理器、HandlerAdapter 执行处理器、ViewResolver 解析视图,DispatcherServlet 居中调度;
@RequestMapping通过 value/method/params 精确匹配请求,限定请求方式时更推荐@GetMapping/@PostMapping;- 视图跳转默认转发,可通过
forward:与redirect:显式指定。
