SpringMVC全局异常处理+拦截器使用+参数校验
SpringMVC 是 Spring 框架中用于构建 Web 应用程序的模块。为了提高应用程序的稳定性和用户体验,全局异常处理、拦截器的使用和参数校验是必须掌握的技术。以下将详细介绍这些内容。
全局异常处理
全局异常处理能够有效捕获并处理应用程序中的异常,防止异常信息直接暴露给用户,从而提高应用的安全性和用户体验。
1. 使用 @ControllerAdvice 注解
@ControllerAdvice
是 Spring 提供的一个用于全局处理控制器里异常的注解。它可以捕获所有控制器中的异常,并进行统一处理。
示例代码:
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)public ResponseEntity<String> handleException(Exception e) {return new ResponseEntity<>("服务器内部错误:" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);}@ExceptionHandler(IllegalArgumentException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException e) {return new ResponseEntity<>("无效参数:" + e.getMessage(), HttpStatus.BAD_REQUEST);}
}
在上述代码中,@ExceptionHandler
注解指定了不同的异常处理方法,@ResponseStatus
注解用于设置返回的 HTTP 状态码。
2. 使用 @ExceptionHandler 注解
@ExceptionHandler
注解可以直接在控制器中使用,用于处理特定方法的异常。
示例代码:
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.http.HttpStatus;@Controller
public class MyController {@RequestMapping("/example")public String exampleMethod() {// 代码可能抛出异常throw new IllegalArgumentException("Invalid argument");}@ExceptionHandler(IllegalArgumentException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public String handleIllegalArgumentException(IllegalArgumentException e) {return "error/400"; // 返回视图名}
}
拦截器的使用
拦截器(Interceptor)是 AOP(面向切面编程)在 Spring 中的应用之一,可以在请求到达控制器之前和之后执行逻辑,用于处理身份验证、日志记录等任务。
1. 实现 HandlerInterceptor 接口
要创建一个拦截器,需要实现 HandlerInterceptor
接口,并重写其方法。
示例代码:
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 请求处理之前执行System.out.println("拦截器:请求处理之前");return true; // 返回 true 表示继续处理请求,返回 false 表示中断请求}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// 请求处理之后,视图渲染之前执行System.out.println("拦截器:请求处理之后,视图渲染之前");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 完全处理完请求之后执行System.out.println("拦截器:请求完全处理之后");}
}
2. 注册拦截器
拦截器需要在配置类中注册才能生效。
示例代码:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate MyInterceptor myInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor).addPathPatterns("/**"); // 拦截所有请求}
}
参数校验
参数校验是确保传入的请求参数符合预期的一种手段,可以有效防止无效数据导致的异常和错误。
1. 使用 JSR-303/JSR-380 注解
Spring MVC 支持 JSR-303/JSR-380(Bean Validation),可以使用注解对请求参数进行校验。
示例代码:
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;public class User {@NotBlank(message = "用户名不能为空")@Size(min = 3, max = 20, message = "用户名长度必须在3到20之间")private String username;@NotBlank(message = "密码不能为空")@Size(min = 6, max = 20, message = "密码长度必须在6到20之间")private String password;// Getter 和 Setter
}
2. 在控制器中使用 @Valid 注解
在控制器方法参数中使用 @Valid
注解进行参数校验,并使用 BindingResult
对象捕获校验结果。
示例代码:
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;@RestController
public class UserController {@PostMapping("/register")public ResponseEntity<String> register(@Valid @RequestBody User user, BindingResult bindingResult) {if (bindingResult.hasErrors()) {return new ResponseEntity<>(bindingResult.getFieldError().getDefaultMessage(), HttpStatus.BAD_REQUEST);}return new ResponseEntity<>("注册成功", HttpStatus.OK);}
}