@ControllerAdvice注解是Spring3.2中新增的注解,学名是Controller增强器,作用是给Controller控制器添加统一的操作或处理
对于@ControllerAdvice,我们比较熟知的用法是结合@ExceptionHandler用于全局异常的处理,但其作用不止于此。ControllerAdvice拆开来就是Controller Advice,关于Advice,在Spring的AOP中,是用来封装一个切面所有属性的,包括切入点和需要织入的切面逻辑。这里ControllerAdvice也可以这么理解,其抽象级别应该是用于对Controller进行切面环绕的,而具体的业务织入方式则是通过结合其他的注解来实现的。@ControllerAdvice是在类上声明的注解,其用法主要有三点:
- 结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的。
- 结合方法型注解@InitBinder,用于request中自定义参数解析方式进行注册,从而达到自定义指定格式参数的目的。
- 结合方法型注解@ModelAttribute,表示其注解的方法将会在目标Controller方法执行之前执行。
从上面的讲解可以看出,@ControllerAdvice的用法基本是将其声明在某个bean上,然后在该bean的方法上使用其他的注解来指定不同的织入逻辑。不过这里@ControllerAdvice并不是使用AOP的方式来织入业务逻辑的,而是Spring内置对其各个逻辑的织入方式进行了内置支持。
全局异常处理器
/**
* 全局异常处理器
*/
@ControllerAdvice //控制器增强器
@Slf4j
public class GlobalHandlerExceptionResolver {
@ExceptionHandler(ServiceException.class)
@ResponseBody
public JsonResult<Void> allExceptionHandler(Exception e) {
log.info("================进入异常处理================");
JsonResult<Void> result=new JsonResult<Void>(e);
if (e instanceof UsernameDuplicateException){
result.setStatus(400); /** 用户名重复的异常 */
result.setMessage(e.getMessage());
} else if (e instanceof InsertException) {
result.setStatus(400); /** 用户注册时插入数据失败的异常 */
result.setMessage(e.getMessage());
}else if (e instanceof UserNotFoundException) {
result.setStatus(400); /** 用户不存在的异常 */
result.setMessage(e.getMessage());
}else if (e instanceof PasswordNotMatchException) {
result.setStatus(400); /** 密码验证失败的异常 */
result.setMessage(e.getMessage());
}else if (e instanceof UpdateException) {
result.setStatus(400); /** 用户数据更新失败的异常 */
result.setMessage(e.getMessage());
}else if (e instanceof FileSizeException) {
result.setStatus(400); /** 文件大小异常 */
result.setMessage(e.getMessage());
}else if (e instanceof FileEmptyException) {
result.setStatus(400); /** 文件为空 */
result.setMessage(e.getMessage());
}else if (e instanceof FileTypeException) {
result.setStatus(400); /** 文件类型异常 */
result.setMessage(e.getMessage());
}
return result;
}
}
响应体
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 响应结果类
* @param <E> 响应数据的类型
*/
@Data
@Accessors(chain = true) //chain属性:不写默认为false,当该值为 true 时,对应字段的 setter 方法调用后,会返回当前对象
public class JsonResult<E> implements Serializable {
/** 状态码 */
private Integer status;
/** 状态描述信息 */
private String message;
/** 数据 */
private E data;
public JsonResult() {
super();
}
public JsonResult(Integer status) {
super();
this.status = status;
}
/** 出现异常时调用 */
public JsonResult(Throwable e) {
super();
/** 获取异常对象中的异常信息 */
this.message = e.getMessage();
}
public JsonResult(Integer status, E data) {
super();
this.status = status;
this.data = data;
}
}
自定义异常类
/**
* 自定义异常:业务相关异常的基类
* */
public class ServiceException extends RuntimeException{
// Override Methods... 快捷键:Alt+insert 选中前五个
public ServiceException() {
super();
}
public ServiceException(String message) {
super(message);
}
public ServiceException(String message, Throwable cause) {
super(message, cause);
}
public ServiceException(Throwable cause) {
super(cause);
}
protected ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}