学习内容
本单元实验环境
- 创建web项目:与10单元创建过程类似,项目名为chap11Annotation。
- 创建com.annotation包,存放第11单元的java资源。
- 创建web\WEB-INF\jsp,存放第11单元的jsp页面文件。
一、DispatcherServlet
1.DispatcherServlet的作用
- 是Spring MVC的核心类、流程控制中心,又称为Spring MVC的前端控制器
- 可以拦截客户端的请求,之后根据具体规则将请求转发给其他组件处理
- 所有请求都要经过DispatcherServlet进行转发处理,以降低了Spring MVC组件之间的耦合性
2.web.xml配置项说明
- DispatcherServlet本质是一个servlet,在org.springframework.web.servlet包中
- 可以在配置文件web.xml完成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_4_0.xsd"
version="4.0">
<!--配置Spring MVC的前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--初始化参数,读取Spring MVC配置文件-->
<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>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern> <!--拦截所有请求(不包括.jsp)-->
</servlet-mapping>
</web-app>
- 元素用来设置DispatcherServlet的参数
- 如果contextConfigLocation参数值没有设置,应用程序到WEB-INF文件夹下找**名为“servlet名称-servlet.xml”的默认配置文件**。例:上例的默认文件名为“dispatcherServlet-servlet.xml”
- **<load-on-startup>元素**设置servlet的加载级别,**值≥0时**表示启动时加载并初始化这个servlet,值越小越先被加载;**值为负数或者没有设置**,则Servlet会在被请求时加载和初始化
二、@Controller注解
- 使用传统的处理器类需要在Spring MVC配置文件中定义请求和Controller 的映射关系,比较繁琐,灵活性低
- Spring MVC框架提供了@Controller注解。只需要将**@Controller注解标注在普通Java类上**,通过Spring的扫描机制找到标注了该注解的Java类,该Java类就会成为了Spring MVC的处理器类
【示例】阅读代码,理解Spring MVC配置访问页面实现过程
(1)创建处理器类PageController**(放com.annotation.controller包)**
package com.annotation.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class PageController {
@RequestMapping("/user/page01")
public String toPage01(){
return "jsp/page01";
}
}
(2)创建视图页面page01.jsp**(放web/WEB-INF/jsp文件夹)**
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
这是page01...
</body>
</html>
(3)修改配置文件spring-mvc.xml,注册处理器bean。此做作法:开启对com.annotation包内组件扫描
<!-- 开启com.annotation包内组件扫描 -->
<context:component-scan base-package="com.annotation"/>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"/>
<property name="suffix" value=".jsp"/>
</bean>
(4)启动项目,访问网址http://localhost:8080/chap11Annotation/user/page01
三、@RequestMapping注解
1.@RequestMapping注解的使用
基本语法:@RequestMapping("映射路径") 或 @RequestMapping(value="映射路径")
作用: 建立请求URL和Handler(处理器)之间的映射关系
使用: 可以标注在方法或类上
-
@RequestMapping注解标注在方法上
- 该方法就是可以处理客户端请求的Handler(处理器),在Spring MVC接收到对应的URL请求时被执行
- Handler在浏览器中对应访问地址:项目访问路径+处理器的映射路径
【示例】阅读代码,简述浏览器访问地址为什么值时会执行处理器方法sayHello()、toUser()。
package com.annotation.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class PageController {
@RequestMapping("/say")
public void sayHello(){
System.out.println("say hello...");
}
@RequestMapping("/user/login")
public String toUser(){
System.out.println("显示用户登录界面...");
return "jsp/user/login";
}
}
如果所在项目访问路径为:[http://localhost:8080/chap11Annotation/](http://localhost:8080/chap11Annotation/)
执行sayHello()方法时,在浏览器输入网址[http://localhost:8080/chap11Annotation/say](http://localhost:8080/chap11Annotation/say)
执行toUser()方法时,在浏览器输入网址[http://localhost:8080/chap11Annotation/user/login](http://localhost:8080/chap11Annotation/user/login)
- @RequestMapping注解标注在类上
- value属性值相当于本处理器类的命名空间,即:访问该处理器类下任意处理器都需要带上这个命名空间
- value属性值作为请求URL的第一级访问目录
- @RequestMapping注解同时标注在类和类中的方法上时,处理器在浏览器中的访问地址:项目访问路径+处理器类的映射路径+处理器的映射路径
【示例】阅读代码,简述浏览器访问地址为什么值时会执行处理器方法sayHello()、toUser()。
package com.annotation.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/cookie")
public class PageController {
@RequestMapping("/say")
public void sayHello(){
System.out.println("say hello...");
}
@RequestMapping("/user/login")
public String toUser(){
System.out.println("显示用户登录界面...");
return "chap11annotation/login";
}
}
答: 如果所在项目访问路径为:http://localhost:8080/chap11Annotation/
执行sayHello()方法时,在浏览器输入网址http://localhost:8080/chap11Annotation/cookie/say
执行toUser()方法时,在浏览器输入网址http://localhost:8080/chap11Annotation/cookie/user/login
2.@RequestMapping注解的属性
具体如下表所示。
****属性名 | ****类型 | ****描述 |
---|---|---|
name | String | 可选属性,用于为映射地址指定别名。 |
value | String[] | 可选属性,也是默认属性,用于****指定请求的URL。 |
method | RequestMethod[] | 可选属性,用于****指定该方法可以处理哪种类型的请求方式。 |
params | String[] | 可选属性,用于****指定客户端请求中参数的值,必须包含哪些参数的值,才可以通过其标注的方法处理。 |
headers | String[] | 可选属性,用于****指定客户端请求中必须包含哪些header的值,才可以通过其标注的方法处理。 |
consumes | String[] | 可选属性,用于****指定处理请求的提交内容类型(Content-type)。 |
produces | String[] | 可选属性,用于指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回。 |
(1)value属性
- value是默认属性,即下述两种写法含义相同。
@RequestMapping("/say")
@RequestMapping(value="/say")
- value属性值可以是一个数组,即:可以为一个处理器配置多个映射路径。此时表示多个映射路径执行同一个方法
@RequestMapping({"/cookie","/","/chap11"})
@RequestMapping(value={"/cookie","/","/chap11"})
【示例】阅读代码,理解@RequestMapping注解的value属性的使用。
第一步:创建处理器类ValueController**(放com.annotation.controller包)**
package com.annotation.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/annotation")
public class ValueController {
@RequestMapping(value = {"/addUser","/deleteUser","updateUser"})
public String checkAuth(){
return "jsp/editUser";
}
}
第二步:创建视图页面editUser.jsp**(放web/WEB-INF/jsp文件夹)**
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>编辑用户</title>
</head>
<style>
h1{
text-align: center;
}
button{
width: 100px;
height: 30px;
}
</style>
<body>
<h1 style="text-align: center">编辑用户信息</h1>
<hr/>
<button>添加用户</button>
<button>删除用户</button>
<button>修改用户</button>
</body>
</html>
第三步:确定Spring MVC配置文件中注册了处理器类ValueController
(2)method属性
- 用于限定处理器映射的URL请求方式
- http的URL请求方式有15种,常用的有GET和POST
序号 | 方法 | 描述 |
---|---|---|
1 | ****GET | 请求指定的页面信息,并返回实体主体。 |
2 | HEAD | 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头 |
3 | ****POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 |
4 | PUT | 从客户端向服务器传送的数据取代指定的文档的内容。 |
5 | DELETE | 请求服务器删除指定的页面。 |
6 | CONNECT | HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。 |
7 | OPTIONS | 允许客户端查看服务器的性能。 |
8 | TRACE | 回显服务器收到的请求,主要用于测试或诊断。 |
- method属性值为一个值或一个数组,值为数组时可以为一个处理器配置多种请求方式
@RequestMapping(method = RequestMethod.GET) //处理get请求方式
@RequestMapping(method = {RequestMethod.GET,RequestMethod.PUT}) //处理get和post请求方式
- 如果不指定该属性值,处理器自动适应客户端的请求方式
- 如果请求方式和method属性指定的属性值不匹配时,处理器不会正常处理请求
【示例】阅读代码,理解@RequestMapping注解的method属性的使用。
第一步:创建控制器类MethodController**(放com.annotation.controller包)**
package com.annotation.controller;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.support.HttpRequestHandlerServlet;
import javax.servlet.http.HttpServletRequest;
@Controller
@RequestMapping("/method")
public class MethodController {
@RequestMapping(method = RequestMethod.GET)
public void get(){
System.out.println("执行get请求...");
}
@RequestMapping(method = RequestMethod.POST)
public void post(){
System.out.println("执行post请求...");
}
@RequestMapping(method = RequestMethod.DELETE)
public void delete(){
System.out.println("执行delete请求...");
}
@RequestMapping(method = RequestMethod.PUT)
public void put(){
System.out.println("执行put请求...");
}
}
注意: 上述控制器方法为void没有返回值,默认转发到与该映射路径最后一部分名称相同的jsp页面。如果没有编写相关视图页面,方法还是会执行,只是访问页面时由页面不存在会失败。
第二步:确定Spring MVC配置文件中注册了处理器类MethodController
第三步:启动项目后,在postman工具中分别以GET、POST、PUT、DELETE调试网址http://localhost:8080/chap11Annotation/method,会执行相应方法,且在控制台能看到方法输出的信息;如果换成其它方式,不能处理。
执行效果如下图:
(3)params属性
- params属性值可以缩小请求映射的定位范围。即:当客户端发出请求时,不仅路径映射正确,且要求请求参数值与params设置一样,处理器方法才可以正常执行
- params属性值为一个字符串或一个字符串数组。值为数组则多个请求参数均要与parms设置一致,处理器才能正常执行
@RequestMapping(params = {"id=1"})
@RequestMapping(params = {"id=1","name=rose"})
【示例】阅读代码,理解@RequestMapping注解的params属性的使用。
第一步:创建控制器类ParamsController**(放com.annotation.controller包)**
package com.annotation.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ParamsController {
@RequestMapping(value = "/params01",params = {"id=1"})
public void findById(String id){
System.out.println("id = "+id);
}
@RequestMapping(value = "/params02",params = {"id=1","name=rose"})
public void findByIdAndName(String id,String name){
System.out.println("id = "+id);
System.out.println("name = "+name);
}
}
第二步:确定Spring MVC配置文件中注册了处理器类ParamsController
第三步:启动项目
输入网址:http://localhost:8080/chap11Annotation/params01,不能正常执行方法findById()
输入网址:http://localhost:8080/chap11Annotation/params01?id=1,可以正常执行方法findById()
输入网址:http://localhost:8080/chap11Annotation/params01?id=2,不能可正常执行方法findById()
输入网址:http://localhost:8080/chap11Annotation/params02?id=1&name=rose,可以正常执行方法findByIdAndName()
执行效果如下图:

3.请求映射方式
请求映射方式有三种:基于请求方式的URL路径映射、基于Ant风格的URL路径映射和基于REST风格的URL路径映射。
(1)基于请求方式的URL路径映射
- 使用@RequestMapping注解,并设置method属性值限定客户端请求方式
- 使用组合注解完成客户端请求方式的限定
- 提供了如下组合注解方式
- @GetMapping:匹配GET方式的请求
- @PostMapping:匹配POST方式的请求
- @PutMapping:匹配PUT方式的请求
- @DeleteMapping:匹配DELETE方式的请求
- @PatchMapping:匹配PATCH方式的请求
【示例】以下两种注解方式含义是一样的。
@PostMapping(value = "/login")
@RequestMapping(value = "/login",method = RequestMethod.POST)
(2)基于Ant风格的URL路径映射
- Ant风格其实就是一种通配符风格,在处理器映射路径中使用通配符对访问的URL路径进行关联
- Ant风格的通配符有以下3种
- ?匹配任何单字符
- *匹配0或者任意数量的字符
- **匹配0或者多级目录
****通配符 | ****URL路径 | ****通配符匹配说明 |
---|---|---|
? | /ant1? | 匹配项目根路径下/ant1[anyone]路径,其中[anyone]可以是任意单字符,即/ant1后有且只有1个字符。如/ant12、/ant1a。 |
* | /ant2/*.do | 匹配项目根路径下/ant2/[any].do路径,其中[any]可以是任意数量的字符。如/ant2/findAll.do、/ant2/.do。 |
* | /*/ant3 | 匹配项目根路径下/[onemore]/ant3路径,其中[onemore]可以是数量多于0个的任意字符。如/a/ant3、/findAll/ant3,但是字符数量不能为0个,并且目录层数必须一致,如//ant3、/findAll/a/ant3。 |
** | /**/ant4 | 匹配项目根路径下/[anypath]/ant4路径,其中[anypath]可以是0或者多层的目录。如/ant4、/a/ant4、/a/b/ant4。 |
** | /ant5/** | 匹配项目根路径下/ant5/[anypath]路径,其中[anypath]可以是0或者多层的目录。如/ant5、/ant5/a、/ant5/a/b。 |
- 匹配路径遵守最长匹配原则。当请求路径同时满足两个或多个Ant风格的映射路径匹配规则,那么请求路径最终会匹配满足规则字符最多的路径。例如,/ant/a/path同时满足 /**/path和/ant//path匹配规则,后者较长最终会匹配/ant//path路径。
(3)基于RESTful风格的URL路径映射
- 是按照REST风格访问网络资源,即:把请求参数变成请求路径的一种风格
传统的URL请求格式为:http://.../queryItems?id=1
用RESTful风格后,其URL请求为:http://.../items/1
- 使用RESTful风格后,有两个方面的明显变化:
- 参数id=1变成了请求路径的一部分。?id=1变成了/1
- 动词形式的路径变成了名词。queryItems变成了items
- 使用方法要经过三步
- 第一步,配置映射路径时,要在路径中将参数名以{}定界。示例如下:
@GetMapping("/restful/{id}")
@RequestMapping("/restful/{id}/{name}")
- 第二步:在处理器方法中使用@PathVariable注解获取路径参数值,如果路径参数名与方法参数名不一致时该注解括号里要写明路径参数名。示例如下:
@Controller
public class RestfulController {
@GetMapping("/rest01/{id}")
public void rest01(@PathVariable Integer id){
System.out.println(number);
}
}
@Controller
public class RestfulController {
@RequestMapping("/rest02/{id}/{name}")
public void rest02(@PathVariable("id") Integer number,@PathVariable String name){
System.out.println(number +" " + name);
}
}
- 第三步:使用RESTful风格发出请求。
以上面示例访问: 输入网址http://localhost:8080/chap11Annotation/rest01/1可以访问rest01方法 输入网址http://localhost:8080/chap11Annotation/rest02/1/cherry可以访问rest02方法
【示例】阅读代码,理解RESTful风格的路径映射方法。
第一步:创建控制器类RestfulController**(放com.annotation.controller包)**
package com.annotation.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@Controller
public class RestfulController {
@GetMapping("/restful/{type}")
public void restful(@PathVariable String type){
System.out.println(type);
}
}
第二步:确定Spring MVC配置文件中注册了处理器类RestfulController
第三步:启动项目
测试网址:http://localhost:8080/chap11Annotation/restful/玫瑰花
后台运行结果如下图:

六、课后练习
在IDEA中创建一个MavenWeb项目,要求如下:
(1)在项目web.xml文件中配置DispatcherServlet;
(2)创建一个处理类并使用@Controller注解,并配置文件的类包扫描配置信息;
(3)分别在类上和方法上使用@RequestMapping注解并设置属性;
(4)尝试使用Ant风格映射路径;
(5)尝试使用Restful风格映射路径。