Spring MVC框架的统一处理异常机制
由于Service在处理业务,如果视为”失败“,将抛出异常,并且,抛出时还会封装”失败“的描述文本,而Controller每次调用Service的任何方法时,都会使用try..catch
进行捕获并处理,并且,处理的代码都是相同的(暂时是return e.getMessage();
),这样的做法是非常固定的,导致在Controller中存在大量的try...catch
(处理任何请求,调用Service时都是这样的代码)。
Spring MVC提供了统一处理异常的机制,它可以使得Controller不再处理异常,改为抛出异常,而Spring MVC在调用Controller处理请求时,会捕获Controller抛出的异常并尝试处理。
关于处理异常的方法:
- 访问权限:应该是
public
- 返回值类型:参考处理请求的方法
- 方法名称:自定义
- 参数列表:至少需要添加1个异常类型的参数,表示你希望处理的异常,也是Spring MVC框架调用Controller的方法时捕获到的异常
- 注解:
@ExceptionHandler
- 如果将处理异常的方法定义在某个Controller中,仅作用于当前Controller中所有处理请求的方法,对别的Controller中处理请求的方法是不生效的!Spring MVC建议将处理异常的代码写在专门的类中,并且,在类上添加
@RestControllerAdvice
注解,当添加此注解后,此类中处理异常的代码将作用于整个项目每次处理请求的过程中 - 允许存在多个处理异常的方法,只要这些方法处理的异常类型不直接冲突即可
- 即:不允许2个处理异常的方法都处理同一种异常
- 即:允许多个处理异常的方法中处理的异常存在继承关系,例如A方法处理
NullPointerException
,B方法处理RuntimeException
在实际处理时,推荐添加一下对Throwable
处理的方法,以避免某些异常没有被处理,导致响应500错误。
关于处理异常的类,暂定为:
package cn.tedu.csmall.product.ex.handler;
import cn.tedu.csmall.product.ex.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理器
*
* @author java@tedu.cn
* @version 0.0.1
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
public GlobalExceptionHandler() {
System.out.println("创建全局异常处理器对象:GlobalExceptionHandler");
}
@ExceptionHandler
public String handleServiceException(ServiceException e) {
log.debug("捕获到ServiceException:{}", e.getMessage());
return e.getMessage();
}
@ExceptionHandler
public String handleThrowable(Throwable e) {
log.debug("捕获到Throwable:{}", e.getMessage());
e.printStackTrace(); // 强烈建议
return "服务器运行过程中出现未知错误,请联系系统管理员!";
}
}