Spring MVC框架统一处理异常
在使用Spring MVC框架时,控制器(Controller)可以不处理异常(如果执行过程中出现异常,则自动抛出),框架提供了统一处理异常的机制
关于统一处理异常
-
统一处理异常的代码应该编写在专门的类中,并且,在此类上添加@ControllerAdvice/@RestControllerAdvice注解 @ControllerAdvice/@RestControllerAdvice注解的类中的特定方法将作用于每一次处理请求的过程中 其实,统一的处理异常的代码可以写在牟哥控制器中,但是,将职能作用与此控制器中各处理请求的方法,无法作用于其他控制器中处理请求的方法 在类中自定义方法来处理异常 注解:@ExceptionHandler 访问权限:应该public 返回值类型:设计原则可以参考控制器中处理请求的方法 方法名称:自定义 参数列表:必须包含异常类型的参数,且此参数就是SpringMVC框架调用控制器方法是捕获的异常,另外,可按需添加HttpServerRequest,HttpServletResponse等少量限定类型的参数 例如 package cn.tedu.csmall.product.handler; import cn.tedu.csmall.product.ex.ServiceException; import cn.tedu.csmall.product.web.JsonResult; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler public JsonResult<Void> handleServiceException(ServiceException e) { log.debug("处理ServiceException,serviceCode={},message={}", e.getServiceCode(), e.getMessage()); return JsonResult.fail(e); } }
在以上方法中,方法的参数时ServiceException,则此方法就是用于处理ServiceException及其子孙类异常的,不可以处理其他种类的异常
在同一个项目中,可以有多个以上处理异常的类,或同一个处理异常的类中可以有第一个处理异常的方法,只要这些方法处理的异常不冲突即可,并且,这些方法处理的异常允许在父子级继承关系,例如某个方法处理ServiceException,另一个方法处理RuntimeException,当出现ServiceException,仍会按照处理ServiceException的方法进行处理!
强烈建议在每个项目中都添加一个处理Throwable的方法,避免项目出现500错误!例如
package cn.tedu.csmall.product.handler;
import cn.tedu.csmall.product.ex.ServiceException;
import cn.tedu.csmall.product.web.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler
public JsonResult<Void> handleServiceException(ServiceException e) {
log.debug("处理ServiceException,serviceCode={},message={}", e.getServiceCode(), e.getMessage());
return JsonResult.fail(e);
}
@ExceptionHandler
public JsonResult<Void> handleThrowable(Throwable e) {
log.debug("处理Throwable");
e.printStackTrace();
Integer serviceCode = 99999;
String message = "程序运行过程中出现未知错误,请联系系统管理员!";
return JsonResult.fail(serviceCode, message);
}
}
注意:以上处理Throwable的方法,并不是真正意义的‘处理”了异常,在此方法中,应该通过日志输出异常的详情信息,并且,在后续出现相关异常时,在此类中补充对这些异常的进准处理!
另外,在@ExceptionHandler中,可以配置异常类型的参数,此参数是异常类型的数组,用于指定需要处理哪些种类的异常,但是,通常并不需要进行此项配置,因为方法的参数就可以直接表示处理哪种异常!此注解参数大多应用于“多种不相关的异常使用同一种处理方式”的情景!
