背景:最近在开发过程中遇到了一个@ControllerAdvice注解不生效的bug,排查了一下,特此记录一下,希望大家不要想我一样犯这种低级错误;
@ControllerAdvice注解简单说明
@ControllerAdvice的实际上就是一个@Component,用于对Controller进行切面环绕处理,默认是全局,可配置。作用在类上的注解,其主要用法有三个:(主要用法就是对异常的处理)
- 结合@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常(catch的异常不会触发哦),从而达到不同类型的异常区别处理的目的 (常用)
- 结合@InitBinder,用于request中自定义参数解析方式进行注册,从而达到自定义指定格式参数的目的
- 结合@ModelAttribute,表示其注解的方法将会在目标Controller方法执行之前执行。
定义的ExceptionAdvice类
package com.central.manager.config;
import com.central.common.exception.DefaultExceptionAdvice;
import org.springframework.web.bind.annotation.ControllerAdvice;
/**
* @author kiwi
* @date 2022/08/30
*/
@ControllerAdvice
public class ExceptionAdvice extends DefaultExceptionAdvice {
}
######################分割线############################################
package com.central.common.exception;
import com.central.common.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.*;
import java.sql.SQLException;
/**
* 异常通用处理
*
* @author kiwi
*/
@ResponseBody
@Slf4j
public class DefaultExceptionAdvice {
/**
* IllegalArgumentException异常处理返回json
* 返回状态码:400
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({IllegalArgumentException.class})
public Result badRequestException(IllegalArgumentException e) {
return defHandler("参数解析失败", e);
}
/**
* AccessDeniedException异常处理返回json
* 返回状态码:403
*/
@ResponseStatus(HttpStatus.FORBIDDEN)
@ExceptionHandler({AccessDeniedException.class})
public Result badMethodExpressException(AccessDeniedException e) {
return defHandler("没有权限请求当前方法", e);
}
/**
* 返回状态码:405
*/
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
public Result handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
return defHandler("不支持当前请求方法", e);
}
/**
* 返回状态码:415
*/
@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
@ExceptionHandler({HttpMediaTypeNotSupportedException.class})
public Result handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
return defHandler("不支持当前媒体类型", e);
}
/**
* SQLException sql异常处理
* 返回状态码:500
*/
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler({SQLException.class})
public Result handleSQLException(SQLException e) {
return defHandler("服务运行SQLException异常", e);
}
/**
* BusinessException 业务异常处理
* 返回状态码:500
*/
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(BusinessException.class)
public Result handleException(BusinessException e) {
return defHandler("业务异常", e);
}
/**
* IdempotencyException 幂等性异常
* 返回状态码:200
*/
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(IdempotencyException.class)
public Result handleException(IdempotencyException e) {
return Result.failed(e.getMessage());
}
/**
* 所有异常统一处理
* 返回状态码:500
*/
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(Exception.class)
public Result handleException(Exception e) {
return defHandler("未知异常", e);
}
/**
*空指针异常
* @param e
* @return
*/
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(NullPointerException.class)
public Result nullException(Exception e) {
return defHandler("空指针异常", e);
}
private Result defHandler(String msg, Exception e) {
log.error(msg, e);
return Result.failed(msg);
}
}
项目中也没有其他的Aspect类进行try操作,但就是不生效;
后面发现这个ExceptionAdvice没有被引用的高亮,后面就根据这个排查,发现是我的config包路径写错了地方
config和manager同级了,启动类肯定扫描不到这个包,自然也就不会生效
修改之后就可以正常的返回我们自己对异常的处理了
开发的过程中还是要避免这种低级吃错误,之前没发现这个高亮的问题,我一直找是不是哪里有try/catch处理,耽误了很多时间,特此记录