第一步编写实现类
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);
}