使用 @RestControllerAdvice
的主要场景包括:
- 全局异常处理:处理所有控制器中抛出的未捕获异常。
- 数据校验失败处理:处理 Bean Validation 校验失败的情况。
- 自定义响应:统一定义响应格式或错误信息。
@RestControllerAdvice
注解的类通常与以下组件结合使用:
@ExceptionHandler
:用于处理特定的异常类型。@ResponseStatus
:用于定义异常的HTTP状态。@ExceptionHandler
方法可以访问异常对象、请求对象(WebRequest
)、响应对象等,以构造合适的响应。
以下是一个简单的示例,演示如何使用 @RestControllerAdvice
:
java
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
// 处理自定义异常
@ExceptionHandler(CustomException.class)
public ResponseEntity<String> handleCustomException(CustomException ex, WebRequest request) {
// 构造错误信息
String error = "An error occurred: " + ex.getMessage();
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
// 可以添加更多的异常处理方法
}
在这个示例中,GlobalExceptionHandler
类使用 @RestControllerAdvice
注解标记,使其成为全局异常处理器。类中的 handleCustomException
方法使用 @ExceptionHandler
注解标记,用于处理 CustomException
类型的异常。
使用 @RestControllerAdvice
可以集中处理异常,使控制器代码更简洁、更专注于业务逻辑,同时提高异常处理的可维护性。
一个模拟权限校验的案例
首先自定义一个权限不够的异常
public class PermissionException extends Exception{
// 构造函数
public PermissionException() {
super();
}
public PermissionException(String message) {
super(message);
}
public PermissionException(String message, Throwable cause) {
super(message, cause);
}
public PermissionException(Throwable cause) {
super(cause);
}
}
然后用注解的方式写一个异常处理类
@RestControllerAdvice
public class PermissionExceptionHandler {
@ExceptionHandler(PermissionException.class)
public Map handleMyCustomException(PermissionException ex) {
Map<String, String> msg = new HashMap<>();
msg.put("status","500");
msg.put("msg","错误,没有权限");
return msg;
}
}
然后写一个处理权限校验的拦截器
/*
* preHandle在执行处理器方法之前执行
* postHandle在执行处理器方法之后执行
* afterCompletion在这次请求完成后执行
* */
@Component
public class PermissionInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String auth = request.getParameter("auth");
System.out.println(auth);
if ("0".equals(auth)){
throw new PermissionException();
}
//返回true放行,返回false不放行
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
然后把拦截器注册到spring中
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private HandlerInterceptor permissionInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(permissionInterceptor)
.addPathPatterns("/**") // 拦截所有请求
.excludePathPatterns("/ignoreThis"); // 排除不需要拦截的请求
}
}
然后你请求http://localhost:8080/user/1?auth=1
你会发现auth=1的时候拦截器放行
auth=0的时候会被拦截器拦截,并且抛出我们自定义的异常,然后自定义异常会被我们写的异常处理器监听到,最终给客户端返回没有权限