处理URL请求参数:精通`@PathVariable`、`@RequestParam`与`@MatrixVariable`
摘要: 欢迎进入Spring Boot Web核心开发篇!在上一章,我们为应用穿上了“视图”的外衣,学会了使用Thymeleaf渲染动态页面。现在,我们将回归Web开发的基石——API,并深入探索其与外界交互的第一道门槛:URL。本章将系统性地讲解Spring Boot中用于解析URL中各种参数的三个核心注解:
@PathVariable
、@RequestParam
和@MatrixVariable
。通过本章学习,你将能够设计出更加灵活、强大且符合RESTful风格的API接口,精准地捕获并处理来自客户端的各种请求信息。
引言:从基础到核心的跨越
在第一部分“基础入门篇”中,我们已经搭建起了坚实的脚手架。我们不仅创建了第一个返回JSON的API,还体验了服务端渲染的魅力。现在,我们正式踏入第二部分:Web核心开发篇。这意味着我们将从“能用”迈向“好用”,深入挖掘Spring Boot在Web开发领域的强大功能。
Web开发的核心在于交互,而交互的起点便是URL(统一资源定位符)。一个设计良好的URL不仅能清晰地表达意图,还能携带各种参数,驱动后端的业务逻辑。如何优雅、高效地从URL中提取这些参数?这正是本章要解决的核心问题。
我们将围绕一个“用户管理”的场景,逐一精通Spring Boot提供的三大URL参数处理利器。
一、@PathVariable
:捕获路径中的变量
@PathVariable
用于将URL中占位符部分的值,绑定到控制器方法的参数上。这在RESTful风格的API设计中极为常见,通常用于标识一个唯一的资源。
1. 场景
假设我们需要根据用户ID查询特定用户的信息。我们期望的URL是这样的:/users/1
、/users/42
。这里的1
和42
就是路径变量。
2. 代码实战
修改或创建一个UserController
,添加如下方法:
package com.example.myfirstapp.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Map;@RestController
@RequestMapping("/users") // 在类级别定义通用的请求路径前缀
public class UserController {/*** 使用 @PathVariable 获取路径中的用户ID* {userId} 是一个占位符,Spring MVC会捕获 /users/之后到下一个/之前的部分* @param userId 映射路径变量的值* @return 返回包含用户信息的Map*/@GetMapping("/{userId}")public Map<String, Object> getUserById(@PathVariable("userId") Long userId) {// 在实际应用中,这里会调用Service层根据userId查询数据库return Map.of("id", userId,"username", "user_" + userId,"from", "PathVariable");}
}
代码解读:
@RequestMapping("/users")
: 我们在类级别使用了此注解,意味着这个Controller下的所有方法的URL都将以/users
作为前缀。@GetMapping("/{userId}")
:GetMapping
的路径中包含了一个由花括号{}
包裹的占位符userId
。@PathVariable("userId") Long userId
:@PathVariable
注解告诉Spring MVC,需要将路径占位符的值注入到这个参数中。- 括号中的
"userId"
明确指定了要绑定的占位符名称。如果方法参数名与占位符名称完全一致(如此处的userId
),则可以省略括号,直接写成@PathVariable Long userId
。 - Spring Boot会自动进行类型转换,将URL中的字符串
"42"
转换为Long
类型的42
。
3. 效果演示
启动应用,使用curl
或浏览器访问 http://localhost:8080/users/101
,你将得到如下响应:
{"id": 101,"username": "user_101","from": "PathVariable"
}
二、@RequestParam
:解析查询参数
@RequestParam
用于获取URL中?
之后,以key=value
形式存在的查询参数(Query Parameters)。它常用于实现过滤、分页、排序等功能。
1. 场景
我们需要根据条件查询用户列表,例如:
- 查询第2页,每页10条数据:
/users?page=2&size=10
- 查询所有状态为“active”的用户:
/users?status=active
2. 代码实战
在UserController
中添加新方法:
import org.springframework.web.bind.annotation.RequestParam;
// ... 其他import@RestController
@RequestMapping("/users")
public class UserController {// ... getUserById 方法 .../*** 使用 @RequestParam 获取查询参数* @param page 当前页码,默认为1* @param size 每页大小,默认为10* @param status 用户状态,非必需参数* @return 返回查询参数信息*/@GetMappingpublic Map<String, Object> getUsersByQuery(@RequestParam(value = "page", defaultValue = "1") int page,@RequestParam(value = "size", defaultValue = "10") int size,@RequestParam(value = "status", required = false) String status) {return Map.of("page", page,"size", size,"status", status != null ? status : "not provided","from", "RequestParam");}
}
代码解读:
@GetMapping
: 这次没有指定路径,所以它会匹配类级别的/users
。@RequestParam(value = "page", defaultValue = "1") int page
:value = "page"
: 指定要绑定的查询参数的key。如果参数名与key一致,value
可省略。defaultValue = "1"
: 设置了默认值。如果请求URL中不包含page
参数,page
变量将被赋值为1
。设置了默认值后,required
属性会自动变为false
。
@RequestParam(value = "status", required = false) String status
:required = false
: 表明status
参数是可选的。如果URL中没有此参数,status
变量的值将是null
。如果不设置required = false
且不提供默认值,当缺少该参数时,请求会报错。
3. 效果演示
- 带所有参数: 访问
http://localhost:8080/users?page=3&size=20&status=inactive
{"page": 3,"size": 20,"status": "inactive","from": "RequestParam" }
- 使用默认值: 访问
http://localhost:8080/users?status=active
{"page": 1,"size": 10,"status": "active","from": "RequestParam" }
三、@MatrixVariable
:探索矩阵变量(进阶)
矩阵变量是一种不那么常见但特定场景下非常有用的URL参数形式。它允许你在URL的路径段中嵌入键值对,通常用分号;
隔开。
注意: Spring Boot默认不开启对矩阵变量的支持,需要手动配置。
1. 场景与优势
假设我们要查询一个用户,并且想同时指定该用户信息的几个特定字段。
- 传统查询参数:
/users/42?fields=name,age
- 使用矩阵变量:
/users/42;fields=name,age
或者更复杂的,查询汽车信息:/cars/suv;color=red/brand;name=tesla
,这清晰地表达了color=red
是suv
这个路径段的属性,name=tesla
是brand
的属性。
2. 开启矩阵变量支持
创建一个配置类来开启此功能:
package com.example.myfirstapp.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.util.UrlPathHelper;@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {UrlPathHelper urlPathHelper = new UrlPathHelper();// 设置为false,Spring才会解析分号后的内容作为矩阵变量urlPathHelper.setRemoveSemicolonContent(false);configurer.setUrlPathHelper(urlPathHelper);}
}
3. 代码实战
在UserController
中添加方法:
import org.springframework.web.bind.annotation.MatrixVariable;
// ... 其他import@RestController
@RequestMapping("/users")
public class UserController {// ... 其他方法 .../*** 使用 @MatrixVariable 获取矩阵变量* URL示例: /users/101;role=admin;dept=tech* @param userId 路径变量* @param role 矩阵变量* @param dept 矩阵变量* @return*/@GetMapping("/{userId}/profile")public Map<String, Object> getUserProfile(@PathVariable Long userId,@MatrixVariable String role,@MatrixVariable(value = "dept", pathVar = "userId") String department) {return Map.of("id", userId,"role", role,"department", department,"from", "MatrixVariable");}
}
代码解读:
@MatrixVariable String role
: 最简单的用法,直接绑定与参数名相同的矩阵变量。@MatrixVariable(value = "dept", pathVar = "userId")
:value = "dept"
: 矩阵变量的key。pathVar = "userId"
: 明确指定这个矩阵变量是附着在userId
这个路径变量段上的。当URL中存在多个路径段且都可能带有矩阵变量时,这个属性非常有用,可以避免歧义。
4. 效果演示
重启应用后,访问 http://localhost:8080/users/101;role=admin;dept=tech/profile
{"id": 101,"role": "admin","department": "tech","from": "MatrixVariable"
}
四、总结与对比
我们来用一个图表清晰地总结这三个注解的区别:
通过本章的学习,你已经掌握了Spring Boot处理URL参数最核心的工具。现在,你可以根据业务需求,设计出清晰、规范且功能强大的API接口了。
预告:URL只是客户端与服务端交互的“地址簿”。交互的“内容”——即HTTP请求体(Request Body),同样至关重要。下一章,我们将深入学习 处理HTTP请求体:精通
@RequestBody
、@RequestHeader
与@CookieValue
,探索如何接收和处理POST、PUT等请求中携带的复杂JSON数据。