目录
- 一、简介
- 二、@ResponseBody注解
- 三、@RequestMapping注解
- 四、@ModelAttribute注解(不常用)
-
- 1、基本概念
- [2、方法级别的 @ModelAttribute](#2、方法级别的 @ModelAttribute)
- [3、参数级别的 @ModelAttribute](#3、参数级别的 @ModelAttribute)
- [五、@ExceptionHandler 注解](#五、@ExceptionHandler 注解)
- [六、@ControllerAdvice 全局异常处理](#六、@ControllerAdvice 全局异常处理)
- 七、全局异常处理实战
一、简介
SpringMVC的注解有很多,常用的注解有下面这几个:

1、为什么要使用注解
使用注解可以简化配置,提高代码的可读性和可维护性。通过注解可以实现依赖注入,减少手动管理对象的代码量。注解还支持面向切面编程,实现切面、切入点和通知等。此外,注解提供了声明式事务管理的支持,简化了事务配置和管理。注解还可以用于组件扫描和自动装配,提高开发效率。最后,注解在测试时也有很好的支持。总之,注解使得代码更简洁、灵活,并能更好地利用框架的功能和特性。
代码简洁:减少XML配置,代码更易读
开发快速:自动完成常见任务,减少样板代码
类型安全:编译时检查,减少运行时错误
灵活强大:支持各种Web开发需求
易于测试:注解使单元测试更简单
现代化:符合现代Java开发最佳实践
二、@ResponseBody注解
1、基本概念
@ResponseBody 注解用于将方法返回值直接写入HTTP响应体中,而不是解析为视图名称。它告诉Spring:"这个方法返回的就是数据,不要把它当作视图名"。
2、基本语法
java
@Controller
public class UserController {
@GetMapping("/user/{id}")
@ResponseBody
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
}
3、基本用法
1、在@Controller类中使用
java
@Controller
@RequestMapping("/web")
public class WebController {
// 返回视图名称(默认行为)
@GetMapping("/users")
public String userList(Model model) {
model.addAttribute("users", userService.findAll());
return "user-list"; // 返回视图名,由视图解析器处理
}
// 返回数据(使用@ResponseBody)
@GetMapping("/api/users")
@ResponseBody
public List<User> getUsers() {
return userService.findAll(); // 直接返回数据,不经过视图解析器
}
// 混合使用:同一控制器中既有页面又有API
@GetMapping("/user/{id}/profile")
public String userProfile(@PathVariable Long id, Model model) {
model.addAttribute("user", userService.findById(id));
return "user-profile"; // 返回页面
}
@GetMapping("/user/{id}/data")
@ResponseBody
public User getUserData(@PathVariable Long id) {
return userService.findById(id); // 返回JSON数据
}
}
2、返回不同类型的数据
java
@Controller
public class VariousResponseController {
// 返回对象(自动转为JSON)
@GetMapping("/user/{id}")
@ResponseBody
public User getUser(@PathVariable Long id) {
return userService.findById(id);
// 响应:{"id": 123, "name": "John", "email": "john@example.com"}
}
// 返回字符串
@GetMapping("/status")
@ResponseBody
public String getStatus() {
return "Server is running";
// 响应:"Server is running"
}
// 返回数字
@GetMapping("/count")
@ResponseBody
public int getUserCount() {
return userService.getCount();
// 响应:42
}
// 返回布尔值
@GetMapping("/check/{email}")
@ResponseBody
public boolean checkEmail(@PathVariable String email) {
return userService.existsByEmail(email);
// 响应:true
}
// 返回集合
@GetMapping("/all-users")
@ResponseBody
public List<User> getAllUsers() {
return userService.findAll();
// 响应:[{"id":1,"name":"John"},{"id":2,"name":"Jane"}]
}
// 返回Map
@GetMapping("/stats")
@ResponseBody
public Map<String, Object> getStats() {
Map<String, Object> stats = new HashMap<>();
stats.put("userCount", userService.getCount());
stats.put("activeUsers", userService.getActiveCount());
stats.put("timestamp", LocalDateTime.now());
return stats;
// 响应:{"userCount": 100, "activeUsers": 85, "timestamp": "2024-01-15T10:30:00"}
}
}
@ResponseBody是@RestController的组成部分之一
三、@RequestMapping注解
1、基本概念
@RequestMapping 是Spring MVC中最基础、最强大的注解,用于将HTTP请求映射到特定的处理方法上。它可以用在类级别和方法级别。
2、基本语法
java
@Controller
@RequestMapping("/users") // 类级别:定义基本路径
public class UserController {
@RequestMapping("/profile") // 方法级别:组合成 /users/profile
public String userProfile() {
return "profile";
}
}
3、支持的方法类型
1、指定HTTP方法
java
@Controller
@RequestMapping("/products")
public class ProductController {
// 指定GET方法
@RequestMapping(value = "/list", method = RequestMethod.GET)
public String productList() {
return "product-list";
}
// 指定POST方法
@RequestMapping(value = "/create", method = RequestMethod.POST)
public String createProduct() {
return "redirect:/products/list";
}
// 指定多个HTTP方法
@RequestMapping(value = "/update", method = {RequestMethod.PUT, RequestMethod.PATCH})
public String updateProduct() {
return "success";
}
// 不指定method,默认支持所有HTTP方法
@RequestMapping("/all-methods")
public String handleAllMethods() {
return "all-methods";
}
}
2、专用注解(推荐)
@RequestMapping注解可以大致分为以下的四种:@GetMapiing、@PostMapping、@PutMapping、@DeleteMapping。
java
@RestController
@RequestMapping("/api")
public class ModernController {
// 等价于 @RequestMapping(method = RequestMethod.GET)
@GetMapping("/users")
public List<User> getUsers() {
return userService.findAll();
}
// 等价于 @RequestMapping(method = RequestMethod.POST)
@PostMapping("/users")
public User createUser(@RequestBody User user) {
return userService.save(user);
}
// 等价于 @RequestMapping(method = RequestMethod.PUT)
@PutMapping("/users/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
return userService.update(id, user);
}
// 等价于 @RequestMapping(method = RequestMethod.DELETE)
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Long id) {
userService.delete(id);
}
// 等价于 @RequestMapping(method = RequestMethod.PATCH)
@PatchMapping("/users/{id}")
public User patchUser(@PathVariable Long id, @RequestBody Map<String, Object> updates) {
return userService.partialUpdate(id, updates);
}
}
四、@ModelAttribute注解(不常用)
1、基本概念
@ModelAttribute 用于将请求参数绑定到模型对象 上,主要用于表单数据处理 和模型数据预加载。
2、方法级别的 @ModelAttribute
1、预加载数据(在控制器方法执行前)
java
@Controller
@RequestMapping("/users")
public class UserController {
// 在每个控制器方法执行前都会调用
@ModelAttribute("categories")
public List<String> loadCategories() {
return Arrays.asList("Admin", "User", "Guest", "Manager");
}
@ModelAttribute("departments")
public List<Department> loadDepartments() {
return departmentService.findAll();
}
// 使用预加载的数据
@GetMapping("/create")
public String showCreateForm(Model model) {
// categories 和 departments 已经自动添加到model中
model.addAttribute("user", new User());
return "user-create";
}
}
2、条件性预加载
java
@Controller
public class ConditionalModelAttribute {
// 只在特定条件下预加载
@ModelAttribute("currentUser")
public User loadCurrentUser(HttpSession session) {
Long userId = (Long) session.getAttribute("currentUserId");
if (userId != null) {
return userService.findById(userId);
}
return null;
}
@ModelAttribute("appConfig")
public Map<String, Object> loadConfig() {
Map<String, Object> config = new HashMap<>();
config.put("appName", "My Application");
config.put("version", "1.0.0");
config.put("maxFileSize", "10MB");
return config;
}
}
3、参数级别的 @ModelAttribute
1、绑定表单数据
java
@Controller
@RequestMapping("/products")
public class ProductController {
// 显示表单
@GetMapping("/create")
public String showCreateForm(Model model) {
model.addAttribute("product", new Product());
return "product-create";
}
// 处理表单提交
@PostMapping("/create")
public String createProduct(@ModelAttribute Product product,
BindingResult result) {
if (result.hasErrors()) {
return "product-create"; // 返回表单页面显示错误
}
productService.save(product);
return "redirect:/products";
}
}
2、自定义模型属性名
java
@Controller
public class CustomNameController {
@PostMapping("/register")
public String registerUser(@ModelAttribute("newUser") User user) {
// 模型属性名为 "newUser" 而不是 "user"
userService.register(user);
return "redirect:/login";
}
@GetMapping("/edit")
public String editUser(@RequestParam Long id, Model model) {
User user = userService.findById(id);
model.addAttribute("editingUser", user); // 手动设置属性名
return "user-edit";
}
@PostMapping("/update")
public String updateUser(@ModelAttribute("editingUser") User user) {
userService.update(user);
return "redirect:/users";
}
}
五、@ExceptionHandler 注解
1、基本概念
@ExceptionHandler 用于在控制器内部处理特定类型的异常,提供优雅的错误处理机制。
2、基本用法
控制器内部的异常处理:
java
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
// 处理当前控制器中的 UserNotFoundException
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException ex) {
ErrorResponse error = new ErrorResponse("USER_NOT_FOUND", ex.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
// 处理参数验证异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationErrors(MethodArgumentNotValidException ex) {
List<String> errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(error -> error.getField() + ": " + error.getDefaultMessage())
.collect(Collectors.toList());
ErrorResponse errorResponse = new ErrorResponse("VALIDATION_FAILED", "数据验证失败", errors);
return ResponseEntity.badRequest().body(errorResponse);
}
}
六、@ControllerAdvice 全局异常处理
1、基本概念
@ControllerAdvice 是一个组件注解 ,用于定义全局的异常处理、数据绑定和数据预处理。它让异常处理代码能够跨控制器重用。
2、核心作用
java
@ControllerAdvice
public class GlobalExceptionHandler {
// 这里的方法会应用到所有 @Controller 和 @RestController
}
✅ 全局异常处理:处理所有控制器的异常
✅ 全局数据绑定:为所有控制器预加载数据
✅ 全局数据预处理:预处理所有控制器的请求数据
3、基本用法
java
@ControllerAdvice
public class BasicExceptionHandler {
// 处理所有 NullPointerException
@ExceptionHandler(NullPointerException.class)
public ResponseEntity<String> handleNullPointer(NullPointerException ex) {
return ResponseEntity.badRequest().body("空指针异常: " + ex.getMessage());
}
// 处理所有 Exception
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleAllExceptions(Exception ex) {
return ResponseEntity.status(500).body("系统错误: " + ex.getMessage());
}
}
七、全局异常处理实战
1、后端统一返回结果实体类
java
package com.sky.result;
import lombok.Data;
import java.io.Serializable;
/**
* 后端统一返回结果
* @param <T>
*/
@Data
public class Result<T> implements Serializable {
private Integer code; //编码:1成功,0和其它数字为失败
private String msg; //错误信息
private T data; //数据
public static <T> Result<T> success() {
Result<T> result = new Result<T>();
result.code = 1;
return result;
}
public static <T> Result<T> success(T object) {
Result<T> result = new Result<T>();
result.data = object;
result.code = 1;
return result;
}
public static <T> Result<T> error(String msg) {
Result result = new Result();
result.msg = msg;
result.code = 0;
return result;
}
}
2、全局异常处理实现类
java
package com.sky.handler;
import com.sky.exception.BaseException;
import com.sky.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.sql.SQLIntegrityConstraintViolationException;
/**
* 全局异常处理器,处理项目中抛出的业务异常
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 捕获业务异常
* @param ex
* @return
*/
@ExceptionHandler
public Result exceptionHandler(BaseException ex){
log.error("异常信息:{}", ex.getMessage());
return Result.error(ex.getMessage());
}
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
log.error("异常信息:{}", ex.getMessage());
String[] strings = ex.getMessage().split(" ");
String msg = strings[2] + "已存在";
return Result.error(msg);
}
}
使用@RestControllerAdvice统一返回json数据格式,利用@ExceptionHandler处理每一份异常对应的类,如果是这个异常类就会返回相对应的处理方式。