目录:
Spring MVC - 请求处理
1. 请求参数处理
1.1. @RequestParam
@RequestParam
是Spring框架中的一个注解,用于将HTTP请求中的参数绑定到函数的参数上。当在控制器(Controller)的方法参数前使用此注解时,Spring会自动从HTTP请求的查询字符串中查找与注解中指定名称相匹配的参数,并将其值转换为方法参数的类型。- 其中一些常用的属性参数包括
name
、defaultValue
和required
。
下面是对这三个属性参数的详细解释:
name
属性:用于指定要提取的查询参数或表单参数的名称defaultValue
属性:用于设置参数的默认值。(请求中没有提供相应的参数,将使用默认值)required
属性:用于指定参数是否是必需的- 设置为
true
,则请求中必须包含相应的参数 - 设置为
false
,则参数是可选的
- 设置为
/**
* 控制器类,用于处理不同参数类型的请求。
*/
@Controller
public class ParamsController {
/**
* 处理路径为/testParams02的请求,通过请求参数获取名称。
*
* @param name 请求参数中的用户名。
* @return 指向/index.jsp的字符串,用于展示请求结果。
*/
@RequestMapping("/testParams02")
public String testParams02(@RequestParam(value = "username") String name) {
System.out.println("name:" + name);
return "/index.jsp";
}
/**
* 处理路径为/testParams03的请求,通过可选的请求参数获取名称。
*
* @param name 请求参数中的用户名,允许为空。
* @return 指向/index.jsp的字符串,用于展示请求结果。
*/
@RequestMapping("/testParams03")
public String testParams03(@RequestParam(value = "username", required = false) String name) {
System.out.println("name:" + name);
return "/index.jsp";
}
/**
* 处理路径为/testParams04的请求,通过请求参数获取名称,如果参数未提供,则使用默认值。
*
* @param name 请求参数中的用户名,如果未提供,则默认为"张三"。
* @return 指向/index.jsp的字符串,用于展示请求结果。
*/
@RequestMapping("/testParams04")
public String testParams04(@RequestParam(value = "username", defaultValue = "张三") String name) {
System.out.println("name:" + name);
return "/index.jsp";
}
/**
* 处理路径为/testParams05的请求,通过模型属性获取用户实体。
*
* @param userEntity 包含用户信息的实体对象。
* @return 指向/index.jsp的字符串,用于展示请求结果。
*/
@RequestMapping("/testParams05")
public String testParams05(UserEntity userEntity) {
System.out.println("userEntity:" + userEntity);
return "/index.jsp";
}
}
1.2. @RequestHeader
@RequestHeader
是Spring
框架中的一个注解,用于将HTTP
请求头中的信息绑定到控制器方法的参数上。当在控制器方法的参数前使用此注解时,Spring
会自动从HTTP
请求头中查找与注解中指定名称相匹配的头信息,并将其值转换为方法参数的类型。
/**
* 控制器类,用于处理与请求头相关的请求。
*/
@Controller
public class HeadersController {
/**
* 处理/testHeader01路径的请求,演示如何获取特定请求头的值。
*
* @param accept 通过请求头Accept获取的值,用于客户端表明它能接受的媒体类型。
* @return 返回/index.jsp,指示视图解析器将请求重定向到index.jsp页面。
*/
@RequestMapping("/testHeader01")
public String testHeaders01(@RequestHeader("Accept") String accept) {
System.out.println("accept: " + accept);
return "/index.jsp";
}
/**
* 处理/testHeader02路径的请求,演示如何获取所有请求头的值。
*
* @param headers 通过@RequestHeader注解以Map形式接收所有请求头,键为请求头名称,值为请求头的值。
* @return 返回/index.jsp,指示视图解析器将请求重定向到index.jsp页面。
*/
@RequestMapping("/testHeader02")
public String testHeaders02(@RequestHeader Map<String, String> headers) {
System.out.println(headers);
return "/index.jsp";
}
}
1.3. @CookieValue
@CookieValue
是Spring
框架中的一个注解,用于将HTTP
请求中的Cookie
信息绑定到控制器方法的参数上。当在控制器方法的参数前使用此注解时,Spring
会自动从HTTP
请求的Cookie
中查找与注解中指定名称相匹配的Cookie
,并将其值转换为方法参数的类型。
/**
* 控制器类,用于处理与Cookie相关的请求。
*/
@Controller
public class CookieController {
/**
* 处理测试Cookie的请求。
* 该方法旨在演示如何从Cookie中获取值,并且如何返回一个视图名称。
*
* @param cookie 从Cookie中获取的JSESSIONID值,用于识别会话。
* @return 返回视图名称"/index.jsp",用于指示浏览器加载对应的JSP页面。
*/
@RequestMapping("/testCookie")
public String testCookie(@CookieValue("JSESSIONID") String cookie) {
System.out.println(cookie);
return "/index.jsp";
}
}
1.4. 乱码问题的解决
- 对于
GET
请求乱码问题,可以通过配置SpringMVC
的CharacterEncodingFilter
过滤器来解决。
1.4.1. web.xml 版
src/main/webapp/WEB-INF/web.xml
<!-- 配置字符编码过滤器,确保请求和响应的字符编码为UTF-8 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 设置字符编码为UTF-8 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!-- 强制对请求和响应进行UTF-8编码 -->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- 将字符编码过滤器应用于名为springmvc的Servlet -->
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<servlet-name>springmvc</servlet-name>
</filter-mapping>
1.4.2. Config 版
src/main/java/com/springmvc/config/MyWebAppInitializer.java
/**
* 配置应用于所有Servlet的过滤器。
* 返回一个过滤器数组,这里定义了一个字符编码过滤器,用于确保所有请求和响应都使用UTF-8编码。
* 通过强制设置编码,可以避免由于编码不一致导致的问题。
*
* @return 过滤器数组
*/
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
// 设置字符编码为UTF-8
characterEncodingFilter.setEncoding("UTF-8");
// 强制设置编码,确保所有请求和响应都使用UTF-8编码。
characterEncodingFilter.setForceEncoding(true);
return new Filter[]{characterEncodingFilter};
}
2. 请求映射处理
2.1. @RequestMapping
@RequestMapping
注解是一个用来处理请求地址映射的注解,可用于映射一个请求或一个方法,可以用在类或方法上(以该地址作为父路径)。
params
: 设置请求必须的请求参数- 必须存在某参数
params = {"username"}
- 必须不存在某参数
params = {"!username"}
- 参数必须等于什么值
params = {"username=张三"}
- 参数必须不等于什么值
params = {"!username=张三"}
- 必须存在某参数
headers
: 设置请求必须的请求头headers = {"Accept"}
consums
: 设置请求必须的请求内容类型consumes = {"application/json"}
produces
: 设置响应内容的类型produces = {"application/json"}
- 映射路径的通配符
?
匹配一个字符*
匹配0个或多个字符**
匹配0个或多个路径部分
/**
* 控制器类,负责处理与特定URL路径匹配的HTTP请求。
*/
@Controller
@RequestMapping("/mapping")
public class MappingController {
/**
* 处理/testMapping01路径的GET请求。
*
* @return 指向/index.jsp的字符串,用于显示一个简单的欢迎页面。
*/
@RequestMapping("/testMapping01")
public String testMapping01() {
System.out.println("映射成功!");
return "/index.jsp";
}
/**
* 处理/testMapping02路径的GET和POST请求。
*
* @return 指向/index.jsp的字符串,用于显示一个简单的欢迎页面。
*/
@RequestMapping(value = "/testMapping02", method = {RequestMethod.GET, RequestMethod.POST})
public String testMapping02() {
System.out.println("映射成功!");
return "/index.jsp";
}
/**
* 当请求参数中包含username时处理/testMapping03路径的请求。
*
* @return 指向/index.jsp的字符串,用于显示一个简单的欢迎页面。
*/
@RequestMapping(value = "/testMapping03", params = {"username"})
public String testMapping03() {
System.out.println("映射成功!");
return "/index.jsp";
}
/**
* 当请求参数中不包含username时处理/testMapping04路径的请求。
*
* @return 指向/index.jsp的字符串,用于显示一个简单的欢迎页面。
*/
@RequestMapping(value = "/testMapping04", params = {"!username"})
public String testMapping04() {
System.out.println("映射成功!");
return "/index.jsp";
}
/**
* 当请求参数username的值为张三时处理/testMapping05路径的请求。
*
* @return 指向/index.jsp的字符串,用于显示一个简单的欢迎页面。
*/
@RequestMapping(value = "/testMapping05", params = {"username=张三"})
public String testMapping05() {
System.out.println("映射成功!");
return "/index.jsp";
}
/**
* 当请求参数username的值不为张三时处理/testMapping06路径的请求。
*
* @return 指向/index.jsp的字符串,用于显示一个简单的欢迎页面。
*/
@RequestMapping(value = "/testMapping06", params = {"username!=张三"})
public String testMapping06() {
System.out.println("映射成功!");
return "/index.jsp";
}
/**
* 当请求头中包含Accept字段时处理/testMapping07路径的请求。
*
* @return 指向/index.jsp的字符串,用于显示一个简单的欢迎页面。
*/
@RequestMapping(value = "/testMapping07", headers = {"Accept"})
public String testMapping07() {
System.out.println("映射成功:headers");
return "/index.jsp";
}
/**
* 当请求内容类型为application/json时处理/testMapping08路径的请求。
*
* @return 指向/index.jsp的字符串,用于显示一个简单的欢迎页面。
*/
@RequestMapping(value = "/testMapping08", consumes = {"application/json"})
public String testMapping08() {
System.out.println("映射成功:consumes");
return "/index.jsp";
}
/**
* 当响应内容类型为application/json时处理/testMapping09路径的请求。
*
* @return 指向/index.jsp的字符串,用于显示一个简单的欢迎页面。
*/
@RequestMapping(value = "/testMapping09", produces = {"application/json"})
public String testMapping09() {
System.out.println("映射成功:produces");
return "/index.jsp";
}
/**
* 处理/testMapping10路径的GET请求,展示通配符?的使用。
*
* @return 指向/index.jsp的字符串,用于显示一个简单的欢迎页面。
*/
@RequestMapping(value = "/ant?")
public String testMapping10() {
System.out.println("通配符 ==> ?");
return "/index.jsp";
}
/**
* 处理/testMapping11路径的GET请求,展示通配符*的使用。
*
* @return 指向/index.jsp的字符串,用于显示一个简单的欢迎页面。
*/
@RequestMapping(value = "/ant*")
public String testMapping11() {
System.out.println("通配符 ==> *");
return "/index.jsp";
}
/**
* 处理任意路径下/ant/**结构的请求,展示通配符**的使用。
*
* @return 指向/index.jsp的字符串,用于显示一个简单的欢迎页面。
*/
@RequestMapping(value = "**/ant/**")
public String testMapping12() {
System.out.println("通配符 ==> **");
return "/index.jsp";
}
}
2.2. @PathVariable
@PathVariable
是Spring
框架中的一个注解,用于在控制器方法的参数中注入从URL
路径中提取的变量值。当URL
中的某个部分被定义为变量时(通常使用大括号{}
包裹),该注解可以用来将这部分变量映射到控制器方法的参数上。
/**
* 控制器类,处理与路径相关的请求。
*/
@Controller
public class PathController {
/**
* 处理用户ID路径变量的请求。
*
* @param id 用户的ID,由路径变量提供。
* @return 指向index.jsp的字符串路径。
* URL:http://localhost:8080/user/1
*/
@RequestMapping("/user/{id}")
public String testPathVariable01(@PathVariable("id") Integer id) {
System.out.println("id = " + id);
return "/index.jsp";
}
/**
* 处理用户名和用户ID路径变量的请求。
*
* @param username 用户的用户名,由路径变量提供。
* @param id 用户的ID,由路径变量提供。
* @return 指向index.jsp的字符串路径。
* URL:http://localhost:8080/user/张三/1
*/
@RequestMapping("/user/{username}/{id}")
public String testPathVariable02(@PathVariable("username") String username, @PathVariable("id") Integer id) {
System.out.println("username = " + username);
System.out.println("id = " + id);
return "/index.jsp";
}
}
2.3. REST
REST(Representational State Transfer,表述性状态转移)是一种软件架构风格,主要用于设计网络应用程序的结构。REST架构风格是由Roy Fielding博士在其2000年的博士论文中提出的,他是HTTP协议的主要设计者之一。REST风格强调了几个核心概念,包括:
-
无状态(Stateless):服务器端的响应不应依赖于客户端保存的状态信息,每次请求都应包含处理该请求所需的所有信息。
-
客户端-服务器(Client-Server):架构将功能分为客户端和服务端两部分,客户端负责用户交互和展示,服务器负责存储和处理数据。
-
缓存(Cacheable):响应可以标记为可缓存或不可缓存,这可以提高效率和性能。
-
统一接口(Uniform Interface):这是REST架构中最显著的特点,它简化了客户端与服务端的交互,主要通过以下几点体现:
-
资源的识别通过URI(统一资源标识符);
-
对资源的操作通过标准的方法,如GET、POST、PUT、DELETE等HTTP方法;
-
资源表示的可变性,即资源可以通过不同的格式(如HTML、JSON、XML)来表示;
-
超媒体作为应用状态引擎(HATEOAS),即响应中包含链接到其他相关资源的信息,使得客户端能够发现和访问更多资源。
-
-
分层系统(Layered System):允许中间组件加入而不影响客户端或服务器,比如代理服务器和网关。
-
按需代码(Code on Demand):虽然这不是强制性的,但它允许服务器临时扩展客户端的功能,例如通过JavaScript脚本。
RESTful服务通常使用HTTP协议,因为它天然支持REST的核心原则。例如,GET方法用于检索资源,POST用于创建新资源,PUT用于更新现有资源,DELETE用于删除资源。RESTful API设计应该遵循这些原则,以便于理解和使用,同时保持良好的可扩展性和互操作性。
/**
* 控制器类,用于处理RESTful API请求。
*/
@Controller
public class RestController {
/**
* 处理GET请求,通过路径参数获取特定ID的信息。
*
* @param id 用户ID,作为路径参数传递。
* @return 返回指向index.jsp的路径,用于展示查询结果。
*/
@GetMapping("/testRest/{id}")
public String query(@PathVariable("id") Integer id) {
System.out.println("已查询:" + id);
System.out.println("@GetMapping");
return "/index.jsp";
}
/**
* 处理PUT请求,用于更新用户信息。
*
* @param userEntity 包含更新后用户信息的实体对象。
* @return 返回指向index.jsp的路径,用于展示更新结果。
*/
@PutMapping("/testRest")
public String update(UserEntity userEntity) {
System.out.println("已修改:" + userEntity);
System.out.println("@PutMapping");
return "/index.jsp";
}
/**
* 处理POST请求,用于添加新用户信息。
*
* @param userEntity 包含新用户信息的实体对象。
* @return 返回指向index.jsp的路径,用于展示添加结果。
*/
@PostMapping("/testRest")
public String create(UserEntity userEntity) {
System.out.println("已添加:" + userEntity);
System.out.println("@PostMapping");
return "/index.jsp";
}
/**
* 处理DELETE请求,通过路径参数删除特定ID的用户信息。
*
* @param id 用户ID,作为路径参数传递,用于指定要删除的用户。
* @return 返回指向index.jsp的路径,用于展示删除结果。
*/
@DeleteMapping("/testRest/{id}")
public String delete(@PathVariable("id") Integer id) {
System.out.println("已删除:" + id);
System.out.println("@DeleteMapping");
return "/index.jsp";
}
}
2.4. 静态资源访问
2.4.1. xml 版
src/main/resources/spring-web-config.xml
<!-- 启用基于注解的控制器,使得Spring MVC可以自动识别和处理使用了注解的控制器类 -->
<mvc:annotation-driven/>
<!-- 配置1 -->
<!-- 配置静态资源的处理,指定任何以/images/开头的URL请求都映射到/images/目录下对应的静态资源 -->
<mvc:resources mapping="/images/**" location="/images/" />
<!-- 配置2 -->
<!-- 添加默认的Servlet处理程序,用于处理Spring MVC未显式映射的其他所有请求 -->
<mvc:default-servlet-handler/>
- 配置二选一即可,建议配置 1
2.4.2. Config 版
src/main/java/com/springmvc/config/SpringWebConfig.java
/**
* Spring MVC的配置类,用于配置Spring Web的相关特性。
*/
@Configuration
@ComponentScan(basePackages = {"com.springmvc.controller"})
public class SpringWebConfig implements WebMvcConfigurer {
/**
* 配置静态资源的处理方式。
* 该方法用于告诉Spring MVC如何处理应用中的静态资源,如图片。
* @param registry ResourceHandlerRegistry实例,用于注册和配置资源处理器。
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 配置对/images/路径下资源的处理,资源位于classpath:/images/目录下
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/");
}
}