Spring MVC的Controller统一异常处理:HandlerExceptionResolver

第一步编写实现类

package
bdc.base; import java.io.IOException; import java.sql.SQLException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.DataAccessException; import org.springframework.transaction.TransactionException; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import bdc.common.SimpleJSONResult; import bdc.exception.ArgumentRuntimeException; import bdc.exception.BusinessRuntimeException; import com.fasterxml.jackson.databind.ObjectMapper; /** * 全局异常处理器 * * @author gx * */ public class ExceptionResolver implements HandlerExceptionResolver { private static final Logger logger = LoggerFactory .getLogger(ExceptionResolver.class); @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) { Class<?> clazz = exception.getClass(); StringBuilder builder = new StringBuilder(); if (exception instanceof ArgumentRuntimeException) { builder.append("处理时参数错误:"); } else if (exception instanceof BusinessRuntimeException) { builder.append("业务处理错误:"); } else if (SQLException.class.isAssignableFrom(clazz) || DataAccessException.class.isAssignableFrom(clazz) || TransactionException.class.isAssignableFrom(clazz)) { // 违反主键或唯一约束 if (exception.getMessage().contains("唯一")) { builder.append("数据已存在:"); } else { builder.append("数据库访问异常:"); } } else { builder.append("非预期的异常:"); } Throwable cause = exception.getCause(); if(cause == null){ builder.append(exception.getMessage()); } else { builder.append(cause); } String msg = builder.toString(); logger.error(msg, exception); HandlerMethod method = (HandlerMethod) handler; ResponseBody responseBody = method.getMethodAnnotation(ResponseBody.class); if (responseBody == null) { ModelAndView view = new ModelAndView("errorView"); view.addObject("msg", msg); return view; } response.setContentType("application/json;charset=UTF-8"); try { new ObjectMapper().writeValue(response.getWriter(), new SimpleJSONResult( false, msg)); } catch (IOException e) { e.printStackTrace(); } return null; } }

第二步:将HandlerExceptionResolver实现类配置到SpringMVC配置文件中

<!-- 异常处理 -->
<bean id="exceptionResolver" class="bdc.base.ExceptionResolver" />

第三步:针对异常在web.xml统一处理

  <error-page>
    <error-code>404</error-code>
    <location>/error</location>
  </error-page>
  <error-page>
    <error-code>500</error-code>
    <location>/error</location>
  </error-page>
  <error-page>
    <exception-type>java.lang.Exception</exception-type>
    <location>/error</location>
  </error-page>

第四步:controller接口

  @RequestMapping("/error")
  public ModelAndView error(HttpServletRequest request,
      HttpServletResponse response, Model model) {
    Integer statusCode = (Integer) request
        .getAttribute("javax.servlet.error.status_code");
    Exception exception = (Exception) request
        .getAttribute("javax.servlet.error.exception");
    if (statusCode == null)
      return null;
    StringBuilder builder = new StringBuilder();
    String msg;
    switch (statusCode) {
    case 404:
      msg = builder
          .append(request.getAttribute("javax.servlet.forward.request_uri"))
          .append(",资源不存在").toString();
      logger.warn(msg);
      break;
    default:
      msg = builder.append("非预期的异常:").append(exception.getMessage()).toString();
      logger.error(msg, exception);
      break;
    }
    if (isAjax(request)) {
      response.setContentType("application/json;charset=UTF-8");
      try {
        new ObjectMapper().writeValue(response.getWriter(),
            failureJsonResult(msg));
      } catch (IOException e) {
        e.printStackTrace();
      }
      return null;
    }
    ModelAndView view = new ModelAndView("errorView");
    view.addObject("msg", msg);
    return view;
  } 

  private boolean isAjax(HttpServletRequest request) {
    return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
  }

 

以上为全局异常处理

 

 

 

附加手动抛出异常

根据不同报错信息实现抛出是业务错误还是什么别的错误

package bdc.exception;

public class ArgumentRuntimeException extends RuntimeException {
    private static final long serialVersionUID = 1L;

    public ArgumentRuntimeException() {
        super();
    }

    public ArgumentRuntimeException(String msg) {
        super(msg);
    }

    public ArgumentRuntimeException(String msg, Throwable cause) {
        super(msg, cause);
    }

    public ArgumentRuntimeException(Throwable cause) {
        super(cause);
    }
}
package bdc.exception;

public class BusinessRuntimeException extends RuntimeException {
  private static final long serialVersionUID = 1L;

  public BusinessRuntimeException() {
    super();
  }

  public BusinessRuntimeException(String msg) {
    super(msg);
  }

  public BusinessRuntimeException(String msg, Throwable cause) {
    super(msg, cause);
  }

  public BusinessRuntimeException(Throwable cause) {
    super(cause);
  }
}
package bdc.exception;

public class UnexpectedRuntimeException extends RuntimeException {
  private static final long serialVersionUID = 1L;

  public UnexpectedRuntimeException() {
    super();
  }

  public UnexpectedRuntimeException(String msg) {
    super(msg);
  }

  public UnexpectedRuntimeException(String msg, Throwable cause) {
    super(msg, cause);
  }

  public UnexpectedRuntimeException(Throwable cause) {
    super(cause);
  }
}

使用: 

try {
      //具体业务代码
} catch (ParseException e) {
      throw new UnexpectedRuntimeException("日期格式错误",e);
}
posted @ 2019-03-01 09:47  高木子  阅读(1149)  评论(0编辑  收藏  举报