目录
- 一、简介
- 一、@Controller注解和@RestController注解
- 二、@RequestParam注解
- 三、@PathVariable注解
- 四、@RequestBody注解
- 五、@PathVariable、@RequestBody、@RequestParam注解之间的区别
一、简介
SpringMVC的注解有很多,常用的注解有下面这几个:

1、为什么要使用注解
使用注解可以简化配置,提高代码的可读性和可维护性。通过注解可以实现依赖注入,减少手动管理对象的代码量。注解还支持面向切面编程,实现切面、切入点和通知等。此外,注解提供了声明式事务管理的支持,简化了事务配置和管理。注解还可以用于组件扫描和自动装配,提高开发效率。最后,注解在测试时也有很好的支持。总之,注解使得代码更简洁、灵活,并能更好地利用框架的功能和特性。
代码简洁:减少XML配置,代码更易读
开发快速:自动完成常见任务,减少样板代码
类型安全:编译时检查,减少运行时错误
灵活强大:支持各种Web开发需求
易于测试:注解使单元测试更简单
现代化:符合现代Java开发最佳实践
一、@Controller注解和@RestController注解
1、@Controller注解
@Controller 是Spring MVC中用于标记类作为控制器的注解,主要用于传统的Web页面应用。
java
@Controller
@RequestMapping("/web")
public class UserWebController {
@Autowired
private UserService userService;
// 返回视图名称,由视图解析器解析为具体页面
@GetMapping("/users")
public String getUserList(Model model) {
List<User> users = userService.findAll();
model.addAttribute("users", users);
return "user-list"; // 返回视图名,对应 user-list.jsp/html
}
// 返回JSON数据,需要额外添加@ResponseBody
@GetMapping("/users/json")
@ResponseBody
public List<User> getUsersJson() {
return userService.findAll();
}
// 处理表单提交
@PostMapping("/users")
public String createUser(@ModelAttribute User user) {
userService.save(user);
return "redirect:/web/users"; // 重定向
}
// 显示用户详情页面
@GetMapping("/users/{id}")
public String getUserDetail(@PathVariable Long id, Model model) {
User user = userService.findById(id);
model.addAttribute("user", user);
return "user-detail";
}
}
根据上面的例子可以看出来:
@Controller 主要用途是返回页面(视图)
处理 ModelAndView 中的 View 部分
返回视图:默认返回视图名称,由视图解析器渲染HTML页面需要@ResponseBody:如果要返回JSON/XML数据,需要额外添加@ResponseBody
适合:传统Web应用,需要服务端渲染页面的场景
2、@RestController注解
@RestController 是Spring 4.0引入的注解,是@Controller和@ResponseBody的组合,专门用于RESTful Web服务。
@RestController是前后端分离开发主要的控制器注解。
java
@RestController
@RequestMapping("/api/v1")
public class UserApiController {
@Autowired
private UserService userService;
// 自动返回JSON数据,不需要@ResponseBody
@GetMapping("/users")
public List<User> getAllUsers() {
return userService.findAll();
}
@GetMapping("/users/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.findById(id);
if (user != null) {
return ResponseEntity.ok(user);
} else {
return ResponseEntity.notFound().build();
}
}
@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
User savedUser = userService.save(user);
return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);
}
@PutMapping("/users/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id,
@Valid @RequestBody User user) {
User updatedUser = userService.update(id, user);
return ResponseEntity.ok(updatedUser);
}
@DeleteMapping("/users/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build();
}
// 返回自定义响应结构
@GetMapping("/users/{id}/profile")
public ApiResponse<UserProfile> getUserProfile(@PathVariable Long id) {
UserProfile profile = userService.getProfile(id);
return ApiResponse.success(profile);
}
}
自动@ResponseBody:所有方法自动添加@ResponseBody,直接返回数据
返回JSON/XML:默认返回数据而不是视图名称
适合:REST API、前后端分离应用
@Controller和@RestController注解的区别如下图:

二、@RequestParam注解
@RequestParam 用于从HTTP请求的查询参数或表单数据 中提取值到控制器方法的参数中。
@RequestParam注解是用来解析下面的情况的:/users?page=1&name=john。
@RequestParam注解能使用在所有的请求方法中包括(GET、POST、PUT、DELETE)等,但是只能解析HTTP请求的查询参数或表单数据,不能解析请求体。
java
@RestController
public class UserController {
// 基本用法:从URL参数获取值
// 访问:/search?keyword=java
@GetMapping("/search")
public String search(@RequestParam String keyword) {
return "Searching for: " + keyword;
}
// 多个参数
// 访问:/users?page=1&size=20
@GetMapping("/users")
public List<User> getUsers(
@RequestParam int page,
@RequestParam int size) {
return userService.findUsers(page, size);
}
}
请求参数为一个参数的情况下,可以忽略使用@RequestParam注解,但是请求参数为多个的时候必须使用@RequestParam注解
1、注解属性详解
1、name / value 属性
java
@RestController
public class ExampleController {
// 参数名与方法参数名不同时使用
// 访问:/api?user_name=john
@GetMapping("/api")
public String example(
@RequestParam(name = "user_name") String username,
@RequestParam(value = "user_age") Integer age) {
return "Username: " + username + ", Age: " + age;
}
// name和value是等价的
@GetMapping("/test")
public String test(
@RequestParam("first_name") String firstName, // 使用value
@RequestParam(name = "last_name") String lastName) { // 使用name
return firstName + " " + lastName;
}
}
name 和 value 属性是等价的 ,用于指定请求参数的名称,当方法参数名与URL参数名不一致时使用。
场景1:参数名与方法参数名一致(不需要指定)
java
@RestController
public class SimpleController {
// 方法参数名与URL参数名一致时,不需要指定name/value
// 访问:/user?userId=123&username=john
@GetMapping("/user")
public User getUser(
@RequestParam Long userId, // 自动匹配 userId 参数
@RequestParam String username // 自动匹配 username 参数
) {
return userService.findUser(userId, username);
}
}
场景2:参数名与方法参数名不一致(需要指定name/value)
java
@RestController
public class ComplexController {
// 方法参数名与URL参数名不一致时,需要使用name/value指定
// 访问:/search?q=springboot&cat=technology
@GetMapping("/search")
public List<Item> searchItems(
@RequestParam("q") String keyword, // URL参数是q,方法参数是keyword
@RequestParam(name = "cat") String category, // URL参数是cat,方法参数是category
@RequestParam(value = "p") int page // URL参数是p,方法参数是page
) {
return searchService.search(keyword, category, page);
}
}
2、required 属性
@RequestParam 注解主要用于从请求 URL 的查询参数或表单数据中提取值。
required 属性用于控制该参数是否必须由客户端提供,required属性的默认值为tue,即是必须传的。
重要:当你使用 required = false 时,对应的方法参数类型必须是能够接受 null 值的,例如:
所有引用类型(如 String, Integer, Long, 自定义对象等)。
如果使用基本数据类型(如 int, long, boolean),因为它们不能为 null,Spring 会尝试绑定一个默认值(如 0 或false),但这通常不是我们想要的行为,容易引发逻辑错误。
请求参数中必须为引用类型数据
java
@RestController
public class RequiredExampleController {
// 必需参数(默认true)
// 访问必须包含id参数:/user?id=123
@GetMapping("/user")
public User getUser(@RequestParam Long id) {
return userService.findById(id);
}
// 可选参数
// 访问可以不带sort参数:/products 或 /products?sort=name
@GetMapping("/products")
public List<Product> getProducts(
@RequestParam(required = false) String sort) {
if (sort != null) {
return productService.findAllSorted(sort);
}
return productService.findAll();
}
// 混合使用
@GetMapping("/search")
public List<Item> searchItems(
@RequestParam String keyword, // 必需
@RequestParam(required = false) String category, // 可选
@RequestParam(required = false) Double minPrice) { // 可选
return itemService.search(keyword, category, minPrice);
}
}
3、defaultValue 属性
defaultValue 属性用于为请求参数指定一个默认值。当客户端没有在请求中提供该参数时,Spring 会自动使用这个默认值。
自动设置
required = false:一旦你设置了defaultValue,required属性就会被自动视为false,即使你显式地写成required = true也会被忽略。因为既然有默认值,这个参数就不再是"必需"的了。
类型转换:defaultValue是一个字符串,但 Spring 会自动将其转换为方法参数的实际类型(如int, long,boolean等)。
设置了defaultValue的话,required如果没有被设置的话,就会自动被设置为false的。
java
@RestController
public class DefaultValueController {
// 提供默认值
// 访问 /page 或 /page?num=5 都可以
@GetMapping("/page")
public String getPage(
@RequestParam(defaultValue = "1") int pageNum) {
return "Page number: " + pageNum;
}
// 常用分页参数
@GetMapping("/items")
public Page<Item> getItems(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(defaultValue = "id") String sortBy,
@RequestParam(defaultValue = "asc") String direction) {
return itemService.getItems(page, size, sortBy, direction);
}
// 字符串默认值
@GetMapping("/filter")
public List<Product> filterProducts(
@RequestParam(defaultValue = "") String name,
@RequestParam(defaultValue = "all") String category,
@RequestParam(defaultValue = "0") double minPrice) {
return productService.filter(name, category, minPrice);
}
}
2、高级用法
特殊情况:什么时候可以省略@RequestParam注解?
只有在 POJO 对象作为参数 时才可以省略注解,Spring 会尝试将请求参数按名称匹配到对象的属性上。
1、映射到对象
java
// 搜索参数对象
public class SearchCriteria {
private String keyword;
private String category;
private Double minPrice;
private Double maxPrice;
private String sortBy;
// getter和setter
}
@RestController
public class SearchController {
// Spring自动将参数映射到对象属性
// 访问:/search?keyword=phone&category=electronics&minPrice=100
@GetMapping("/search")
public List<Product> searchProducts(SearchCriteria criteria) {
return productService.search(criteria);
}
}
2、数组/列表参数
java
@RestController
public class ArrayParamController {
// 多选参数
// 访问:/products?categories=electronics&categories=books
@GetMapping("/products")
public List<Product> getByCategories(
@RequestParam List<String> categories) {
return productService.findByCategories(categories);
}
// 数组形式
// 访问:/users?ids=1,2,3,4 或 /users?ids=1&ids=2&ids=3
@GetMapping("/users")
public List<User> getUsersByIds(@RequestParam Long[] ids) {
return userService.findByIds(ids);
}
// 整数列表
@GetMapping("/orders")
public List<Order> getOrdersByStatus(
@RequestParam(defaultValue = "1,2,3") List<Integer> statuses) {
return orderService.findByStatusIn(statuses);
}
}
3、Map接收所有参数
java
@RestController
public class MapParamController {
// 接收所有查询参数到Map中
@GetMapping("/filter")
public List<Item> filterItems(
@RequestParam Map<String, String> allParams) {
return itemService.filterByMultipleCriteria(allParams);
}
// 带前缀的参数映射
@GetMapping("/advanced-search")
public List<Product> advancedSearch(
@RequestParam Map<String, Object> searchParams) {
// 可以处理各种类型的参数值
return productService.advancedSearch(searchParams);
}
}
三、@PathVariable注解
1、基础概念
@PathVariable 用于从URL路径模板中提取值到控制器方法的参数中,是RESTful API设计的核心注解。
2、基本语法
1、单个路径变量
java
@RestController
@RequestMapping("/api")
public class UserController {
// 访问:GET /api/users/123
@GetMapping("/users/{id}")
public User getUserById(@PathVariable Long id) {
return userService.findById(id);
}
// 访问:GET /api/products/abc-123
@GetMapping("/products/{productCode}")
public Product getProduct(@PathVariable String productCode) {
return productService.findByCode(productCode);
}
}
2、多个路径变量
java
@RestController
public class OrderController {
// 访问:GET /users/123/orders/456
@GetMapping("/users/{userId}/orders/{orderId}")
public Order getOrder(
@PathVariable Long userId,
@PathVariable Long orderId) {
return orderService.findUserOrder(userId, orderId);
}
// 访问:GET /categories/electronics/products/laptop
@GetMapping("/categories/{categoryName}/products/{productName}")
public List<Product> getProducts(
@PathVariable String categoryName,
@PathVariable String productName) {
return productService.findByCategoryAndName(categoryName, productName);
}
}
3、注解属性详解
1、name / value 属性
name 和 value 属性是完全等价的,都用于指定路径变量名
当路径变量名与方法参数名一致时,可以省略
当名称不一致时,必须显式指定
@PathVariable的name/value属性和@RequestParam的name/value属性一样。
java
@RestController
public class PathVariableController {
// ✅ 情况1:名称一致,可以省略(最常用)
// 访问:GET /api/v1/users/123
@GetMapping("/api/v1/users/{userId}")
public User getUserV1(@PathVariable Long userId) {
return userService.findById(userId);
}
// ✅ 情况2:名称不一致,必须指定(使用value)
// 访问:GET /api/v2/users/123
@GetMapping("/api/v2/users/{userId}")
public User getUserV2(@PathVariable("userId") Long id) {
return userService.findById(id);
}
// ✅ 情况3:名称不一致,必须指定(使用name)
@GetMapping("/api/v3/users/{userId}")
public User getUserV3(@PathVariable(name = "userId") Long userIdentifier) {
return userService.findById(userIdentifier);
}
// ✅ 情况4:显式使用value属性
@GetMapping("/api/v4/users/{userId}")
public User getUserV4(@PathVariable(value = "userId") Long uid) {
return userService.findById(uid);
}
// ❌ 错误示例:名称不一致且未指定
@GetMapping("/api/error/users/{userId}")
public User getErrorUser(@PathVariable Long id) { // 编译错误!
return userService.findById(id);
}
}
2、required 属性详解
与@RequestParam一致。
java
@RestController
public class RequiredController {
// ✅ required默认为true - 路径变量必须存在
// 访问:GET /required/users/123 ✅
// 访问:GET /required/users/ ❌ 会404(路由不匹配)
@GetMapping("/required/users/{id}")
public User getRequiredUser(@PathVariable Long id) {
return userService.findById(id);
}
}
java
@RestController
public class OptionalPathVariableController {
// ✅ 方案1:通过数组定义多个路由模式
// 访问:GET /optional/users ✅ 获取所有用户
// 访问:GET /optional/users/123 ✅ 获取特定用户
@GetMapping({"/optional/users", "/optional/users/{id}"})
public Object getUsers(@PathVariable(required = false) Long id) {
if (id != null) {
return userService.findById(id); // 返回单个用户
} else {
return userService.findAll(); // 返回用户列表
}
}
// ✅ 方案2:使用Optional包装(Java 8+)
@GetMapping({"/optional2/users", "/optional2/users/{id}"})
public Object getUsersOptional(@PathVariable Optional<Long> id) {
return id.map(userService::findById)
.orElse(userService.findAll());
}
// ✅ 方案3:多级可选路径
@GetMapping({
"/categories",
"/categories/{categoryId}",
"/categories/{categoryId}/products",
"/categories/{categoryId}/products/{productId}"
})
public Object getHierarchicalData(
@PathVariable(required = false) Long categoryId,
@PathVariable(required = false) Long productId) {
if (categoryId == null) {
return categoryService.findAll(); // 所有分类
} else if (productId == null) {
return productService.findByCategory(categoryId); // 分类下所有商品
} else {
return productService.findByIdAndCategory(productId, categoryId); // 特定商品
}
}
}
四、@RequestBody注解
1、基本概念
@RequestBody 用于将 HTTP请求体 中的数据绑定到方法的参数上,主要用于处理JSON、XML等格式的请求数据。
2、基本语法
1、接收简单对象
java
@RestController
public class UserController {
// 接收JSON对象
// 请求体:{"name": "John", "email": "john@example.com", "age": 25}
@PostMapping("/users")
public User createUser(@RequestBody User user) {
return userService.save(user);
}
// 接收Map
// 请求体:{"username": "john", "password": "123456"}
@PostMapping("/auth/register")
public ResponseEntity<?> register(@RequestBody Map<String, Object> userData) {
String username = (String) userData.get("username");
String password = (String) userData.get("password");
return ResponseEntity.ok(authService.register(username, password));
}
}
2、接收复杂嵌套对象
java
// 复杂对象定义
public class OrderRequest {
private Long userId;
private List<OrderItem> items;
private Address shippingAddress;
private PaymentInfo paymentInfo;
// getters and setters
}
public class OrderItem {
private Long productId;
private Integer quantity;
private BigDecimal price;
// getters and setters
}
@RestController
public class OrderController {
// 接收复杂嵌套对象
// 请求体:{
// "userId": 123,
// "items": [
// {"productId": 1, "quantity": 2, "price": 99.99},
// {"productId": 2, "quantity": 1, "price": 149.99}
// ],
// "shippingAddress": {"street": "123 Main St", "city": "New York"},
// "paymentInfo": {"cardNumber": "4111111111111111", "expiry": "12/25"}
// }
@PostMapping("/orders")
public Order createOrder(@RequestBody OrderRequest orderRequest) {
return orderService.createOrder(orderRequest);
}
}
注意,使用 @RequestBody 注解时需要确保请求体数据的格式与方法参数类型匹配。例如,如果控制器方法的参数是 String 类型,那么请求体中的数据应该是纯文本格式的。
总之,@RequestBody 注解是用于获取 POST 请求体中的数据并在控制器方法中使用的重要注解,可以方便地将请求体中的数据转换成 Java 对象并进行相应的处理。
五、@PathVariable、@RequestBody、@RequestParam注解之间的区别

@RequestParam 用于从HTTP请求的查询参数或表单数据中提取值到控制器方法的参数中。
@PathVariable 用于从URL路径模板中提取值到控制器方法的参数中,是RESTful API设计的核心注解。
@RequestBody 用于将 HTTP请求体 中的数据绑定到方法的参数上,主要用于处理JSON、XML等格式的请求数据。
@PathVariable:URL路径中的资源ID(/users/123)
@RequestParam:URL问号后的查询条件(/users?name=john)
@RequestBody:请求体中的复杂数据(JSON对象)