全局异常处理及自定义异常类
全局异常处理
定义一个处理类,使用@ControllerAdvice注解。
@ControllerAdvice注解:控制器增强,一个被@Component注册的组件。
配合@ExceptionHandler来增强所有的@requestMapping方法。
例如:@ExceptionHandler(Exception.class) 用来捕获@requestMapping的方法中所有抛出的exception。
代码:
@ControllerAdvice
public class GlobalDefultExceptionHandler {
//声明要捕获的异常
@ExceptionHandler(Exception.class)
@ResponseBody
public String defultExcepitonHandler(HttpServletRequest request,Exception e) {
return “error”;
}
}
这样,全局异常处理类完毕。可以添加自己的逻辑。
然后还有一个问题,有的时候,我们需要业务逻辑时抛出自定义异常,这个时候需要自定义业务异常类。
定义class:BusinessException ,使他继承于RuntimeException.
说明:因为某些业务需要进行业务回滚。但spring的事务只针对RuntimeException的进行回滚操作。所以需要回滚就要继承RuntimeException。
public class BusinessException extends RuntimeException{
}
然后,现在来稍微完善一下这个类。
当我们抛出一个业务异常,一般需要错误码和错误信息。有助于我们来定位问题。
所以如下:
public class BusinessException extends RuntimeException{
//自定义错误码
private Integer code;
//自定义构造器,只保留一个,让其必须输入错误码及内容
public BusinessException(int code,String msg) {
super(msg);
this.code = code;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
这时候,我们发现还有一个问题,如果这样写,在代码多起来以后,很难管理这些业务异常和错误码之间的匹配。所以在优化一下。
把错误码及错误信息,组装起来统一管理。
定义一个业务异常的枚举
public enum ResultEnum {
UNKONW_ERROR(-1,"未知错误"),
SUCCESS(0,"成功"),
ERROR(1,"失败"),
;
private Integer code;
private String msg;
ResultEnum(Integer code,String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
这个时候,业务异常类:
public class BusinessException extends RuntimeException{
private static final long serialVersionUID = 1L;
private Integer code; //错误码
public BusinessException() {}
public BusinessException(ResultEnum resultEnum) {
super(resultEnum.getMsg());
this.code = resultEnum.getCode();
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
然后再修改一下全局异常处理类:
@ControllerAdvice
public class GlobalDefultExceptionHandler {
//声明要捕获的异常
@ExceptionHandler(Exception.class)
@ResponseBody
public <T> Result<?> defultExcepitonHandler(HttpServletRequest request,Exception e) {
e.printStackTrace();
if(e instanceof BusinessException) {
Log.error(this.getClass(),"业务异常:"+e.getMessage());
BusinessException businessException = (BusinessException)e;
return ResultUtil.error(businessException.getCode(), businessException.getMessage());
}
//未知错误
return ResultUtil.error(-1, "系统异常:\\n"+e);
}
}
判断这个是否是业务异常。和系统异常就可以分开处理了。
全局异常处理配置
springboot Restful使用
@ControllerAdvice、@ExceptionHandler、@ResponseBody实现全局异常处理
@ControllerAdvice
注解定义全局异常处理类@ExceptionHandler
指定自定义错误处理方法拦截的异常类型
同一个异常被小范围的异常类和大范围的异常处理器同时覆盖,会选择小范围的异常处理器
1.定义异常业务类
public class ExceptionVO {
private String errorCode;
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
}
2.定义自定义异常
package exception;
public class NotFoundException extends SystemException {
public NotFoundException(String message) {
super(message);
}
}
public class SystemException extends RuntimeException {
private static final long serialVersionUID = 1095242212086237834L;
protected Object errorCode;
protected Object[] args;
public SystemException() {
super();
}
public SystemException(String message, Throwable cause) {
super(message, cause);
}
public SystemException(String message) {
super(message);
}
public SystemException(String message, Object[] args, Throwable cause) {
super(message, cause);
this.args = args;
}
public SystemException(String message, Object[] args) {
super(message);
this.args = args;
}
public SystemException(Object errorCode, String message, Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}
public SystemException(Object errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public SystemException(Object errorCode, String message, Object[] args, Throwable cause) {
super(message, cause);
this.args = args;
this.errorCode = errorCode;
}
public SystemException(Object errorCode, String message, Object[] args) {
super(message);
this.args = args;
this.errorCode = errorCode;
}
public SystemException(Throwable cause) {
super(cause);
}
public Object[] getArgs() {
return args;
}
public Object getErrorCode() {
return errorCode;
}
}
3.定义全局异常处理类
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import NotFoundException;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import ExceptionVO;
@ControllerAdvice("web") //指定异常处理期拦截范围
public class WebExceptionHandler {
static Logger LOG = LoggerFactory.getLogger(WebExceptionHandler.class);
@Autowired
private MessageSource messageSource;
@ExceptionHandler(FieldException.class)
@ResponseStatus(HttpStatus.CONFLICT) //指定http响应状态
@ResponseBody
@ExceptionHandler(NotFoundException.class)//指定异常类型
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
public ExceptionVO handleNotFoundException(NotFoundException e) {
ExceptionVO vo = new ExceptionVO();
fillExceptionVO(e, vo);
return vo;
}
@ExceptionHandler(SystemException.class)
@ResponseStatus(HttpStatus.CONFLICT)
@ResponseBody
public ExceptionVO handleSystemException(SystemException e) {
ExceptionVO vo = new ExceptionVO();
fillExceptionVO(e, vo);
return vo;
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(Exception.class)
public void globalError(Exception e) {
LOG.error(e.getMessage(), e);
}
private void fillExceptionVO(SystemException e, ExceptionVO vo) {
if (e.getMessage() != null) {
String message = e.getMessage();
try {
message = messageSource.getMessage(e.getMessage(), e.getArgs(), LocaleContextHolder.getLocale());
} catch (NoSuchMessageException ex) {
; // ignore
}
vo.setMessage(message);
}
vo.setErrorCode(String.valueOf(e.getErrorCode()));
}
}
springboot 返回 ModelAndView
package exception.handler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
@Commpent
public class OverallExceptionHandler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2,
Exception ex) {
ModelAndView mav = new ModelAndView();
System.out.println(ex.getMessage());
mav.addObject("errMsg", ex.getMessage());
mav.setViewName("error");
return mav;
}
}
其它方式:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public ModelAndView resolveException(HttpServletRequest request, Exception ex) throws Exception {
ModelAndView mav = new ModelAndView();
System.out.println(ex.getMessage());
mav.addObject("errMsg", ex.getMessage());
mav.setViewName("error");
return mav;
}
}
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。