@PathVariable
@RequestParam学习笔记
1. 介绍
@PathVariable
是一个在Spring MVC 框架中用于处理 URI 模板变量(URI Template Variables)的一个注解,它用于将Web请求中的URL路径参数映射到控制器(Controller)的方法参数上,从而使得方法的参数可以根据客户端请求的 URI 动态变化。这个注解通常与@RequestMapping
或@GetMapping
、@PostMapping
等注解一起使用,以处理基于REST的URL。
2. 场景
当你的URL包含动态部分时,可以使用@PathVariable
来获取这些动态部分的值。例如,如果你有一个URL /users/{userId}
,其中{userId}
是一个动态参数,你可以使用@PathVariable
来获取这个userId
的值。
3. 源码
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PathVariable {
// String类型的属性,用于指定URL中占位符的名称
@AliasFor("name")
String value() default "";
// Spring从4.3.3版本开始提供
// String类型的属性,作用与value属性相同
@AliasFor("value")
String name() default "";
// Spring从4.3.3版本开始提供的String类型的属性
// 用于指定URL中是否必须存在当前占位符的参数,默认值为true
boolean required() default true;
}
4. Demo
假设我们有一个在线书店的 Web 应用,用户可以通过访问不同的 URL 来获取书籍的详细信息、作者的详细信息以及根据书籍分类浏览书籍。我们可以使用 @PathVariable
来处理这些 URL 中的动态部分。
@RestController
@RequestMapping("/api")
public class BookstoreController {
// 假设我们有一个服务层来提供书籍、作者和分类的数据
private final BookService bookService;
private final AuthorService authorService;
private final CategoryService categoryService;
// 构造函数注入服务层
public BookstoreController(BookService bookService, AuthorService authorService, CategoryService categoryService) {
this.bookService = bookService;
this.authorService = authorService;
this.categoryService = categoryService;
}
// 获取书籍详细信息
@GetMapping("/books/{bookId}")
public ResponseEntity<Book> getBookById(@PathVariable Long bookId) {
Book book = bookService.findById(bookId);
if (book == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(book);
}
// 获取作者详细信息
@GetMapping("/authors/{authorId}")
public ResponseEntity<Author> getAuthorById(@PathVariable Long authorId) {
Author author = authorService.findById(authorId);
if (author == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(author);
}
// 浏览特定分类下的所有书籍
@GetMapping("/categories/{categoryId}/books")
public ResponseEntity<List<Book>> getBooksByCategoryId(@PathVariable Long categoryId) {
List<Book> books = bookService.findByCategoryId(categoryId);
if (books.isEmpty()) {
return ResponseEntity.notFound().build(); // 或者返回一个空列表,取决于业务逻辑
}
return ResponseEntity.ok(books);
}
}
服务层
public interface BookService {
Book findById(Long bookId);
List<Book> findByCategoryId(Long categoryId);
// 其他方法...
}
public interface AuthorService {
Author findById(Long authorId);
// 其他方法...
}
public interface CategoryService {
// 可能包含分类的查找、创建等方法,但在这个示例中未使用
}
实体类
public class Book {
private Long id;
private String title;
private Author author;
private Category category;
// 其他字段、getter和setter方法...
}
public class Author {
private Long id;
private String name;
// 其他字段、getter和setter方法...
}
public class Category {
private Long id;
private String name;
// 其他字段、getter和setter方法...
}
5. @PathVariable和@RequestParam注解对比
5.1 使用场景
-
@PathVariable
:- 使用框架:Spring MVC(Web框架)。
- 用途:从请求的URL中获取路径变量的值。
- 场景:在RESTful API中,用于提取URL路径中的参数。例如,
/users/{userId}
中的{userId}
就是一个路径变量,可以通过@PathVariable
来获取其值。
-
@RequestParam
:- 使用框架:Spring MVC(Web框架)。
- 用途:从请求的URL、表单数据或查询参数中获取请求参数的值。
- 场景:用于处理普通的表单提交或查询字符串参数。例如,
/search?keyword=spring
中的keyword=spring
就是一个查询参数,可以通过@RequestParam
来获取其值。
5.2 参数来源
-
@PathVariable
:- 参数来源于URL的路径部分。例如,在
/users/{userId}
中,{userId}
的值就是从URL的路径中提取出来的。
- 参数来源于URL的路径部分。例如,在
-
@RequestParam
:- 参数可以来源于URL的查询字符串部分(如
/search?keyword=spring
中的keyword
),也可以来源于表单数据(如POST请求中提交的表单字段)。
- 参数可以来源于URL的查询字符串部分(如
5.3 注意
-
@PathVariable
:- 通常与
@RequestMapping
或@GetMapping
、@PostMapping
等注解一起使用,这些注解定义了请求映射的URI模式。 - 可以使用
{variable}
作为占位符来引用路径变量。 - 可以接收多个路径变量,只需在方法参数中多次使用
@PathVariable
注解即可。 - 由于路径变量通常用于表示资源标识符(如用户ID、书籍ID等),因此在使用时应确保它们的唯一性和有效性。
- 错误处理:如果路径变量不存在或无法转换,Spring 会抛出
NoSuchRequestHandlingMethodException
。
- 通常与
-
@RequestParam
:- 可以指定
name
或value
属性来明确指定要接收的请求参数名称。 - 可以使用
required
属性来指定参数是否是必传的。如果不指定,默认为true
。如果参数不是必传的,应将其设置为false
,并考虑提供一个defaultValue
作为默认值。 - 当处理基本数据类型(如
int
、long
等)作为请求参数时,如果参数不是必传的且未提供默认值,则可能会引发异常。为了避免这种情况,可以将参数类型更改为相应的包装类型(如Integer
、Long
等),或者提供一个默认值。 - 如果请求参数与后端方法参数名不一致,可以通过
@RequestParam
的value
属性来映射它们之间的关系。 - 错误处理:如果查询参数不存在且
required = true
,Spring 会抛出MissingServletRequestParameterException
。
- 可以指定
6. 注意事项
- 确保路径变量的名字与控制器方法参数的名字匹配,或者在
@PathVariable
注解中明确指定变量名。 - 当处理多个路径变量时,保持 URL 设计的一致性和简洁性。
- 对于可选的路径变量,考虑使用默认值或进行适当的错误处理。