SpringMVC 统一异常处理
程序员文章站
2022-05-28 16:17:41
...
先说说 网上流传的几种处理方式:
方式1:使用SimpleMappingExceptionResolver实现异常处理 (试验过, 对于表单请求异常 和ajax 请求异常处理不方便) 实验的结果就是判断 如果出现404 500错误,判断不出来源是ajax 还是 普通页面请求 所以放弃了
方法二:@ExceptionHandler + @ControllerAdvice
问题是:可以正确获取 所有的异常 ,但是request 和response 获取不到 异常后 应该返回的 status 比如 404 500 415
方法3: web.xml + controller 来实现
web.xml 中配置
方式1:使用SimpleMappingExceptionResolver实现异常处理 (试验过, 对于表单请求异常 和ajax 请求异常处理不方便) 实验的结果就是判断 如果出现404 500错误,判断不出来源是ajax 还是 普通页面请求 所以放弃了
package cn.mwee.wpos.report.cache; import cn.mwee.utils.error.ThrowableUtil; import cn.mwee.wpos.report.consts.ResultCode; import cn.mwee.wpos.service.conts.ErrorCode; import cn.mwee.wpos.service.conts.ErrorDesc; import cn.mwee.wpos.service.dto.common.ErrorResult; import com.alibaba.fastjson.JSON; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; /** * Created by luob on 2017/6/27. */ public class GlobalExceptionResolver extends SimpleMappingExceptionResolver { @Override protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex){ String viewName = determineViewName(ex,request); response.setCharacterEncoding("UTF-8"); String requestType = request.getHeader("X-Requested-With"); if (viewName != null) {// JSP格式返回 if (!(request.getHeader("accept").indexOf("application/json") > -1 || (request .getHeader("X-Requested-With") != null && request .getHeader("X-Requested-With").indexOf("XMLHttpRequest") > -1))) { // 如果不是异步请求 // Apply HTTP status code for error views, if specified. // Only apply it if we're processing a top-level request. Integer statusCode = determineStatusCode(request, viewName); if (statusCode != null){ applyStatusCodeIfPossible(request, response, statusCode); } return getModelAndView(viewName, ex, request); } else {// JSON格式返回 try { PrintWriter writer = response.getWriter(); Map<String,Object> result=new HashMap<>(); ErrorResult error=new ErrorResult(ErrorCode.FAIL, ErrorDesc.FAIL, ThrowableUtil.getStackTrace(ex)); result.put(ResultCode.ERROR,error); writer.write(JSON.toJSONString(result)); writer.flush(); writer.close(); } catch (IOException e) { e.printStackTrace(); } return null; } } else{ return null; } } }
方法二:@ExceptionHandler + @ControllerAdvice
问题是:可以正确获取 所有的异常 ,但是request 和response 获取不到 异常后 应该返回的 status 比如 404 500 415
package cn.mwee.wpos.report.controller; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.beans.ConversionNotSupportedException; import org.springframework.beans.TypeMismatchException; import org.springframework.http.HttpStatus; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.validation.BindException; import org.springframework.web.HttpMediaTypeNotAcceptableException; import org.springframework.web.HttpMediaTypeNotSupportedException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingPathVariableException; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.async.AsyncRequestTimeoutException; import org.springframework.web.multipart.support.MissingServletRequestPartException; import org.springframework.web.servlet.NoHandlerFoundException; import javax.servlet.http.HttpServletRequest; @ControllerAdvice @Slf4j public class ErrorHandlerController { @ExceptionHandler(value = Exception.class) public String exception(HttpServletRequest request, Exception ex) { log.info("ErrorHandlerController.exception"); request.setAttribute("httpStatus", Integer.toString(getHttpStatus(ex).value())); request.setAttribute("httpMessage", getHttpStatus(ex).getReasonPhrase()); request.setAttribute("errorType", ex.getClass().getName()); request.setAttribute("errorMessage", ex.getMessage()); request.setAttribute("errorStackTrace", ExceptionUtils.getStackTrace(ex)); //必须是 forward 否则 /error 区分不了 ajax 和普通的请求 return "forward:/error"; } public HttpStatus getHttpStatus(Exception ex) { if (ex instanceof org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException) { return HttpStatus.NOT_FOUND; } else if (ex instanceof HttpRequestMethodNotSupportedException) { return HttpStatus.METHOD_NOT_ALLOWED; } else if (ex instanceof HttpMediaTypeNotSupportedException) { return HttpStatus.UNSUPPORTED_MEDIA_TYPE; } else if (ex instanceof HttpMediaTypeNotAcceptableException) { return HttpStatus.NOT_ACCEPTABLE; } else if (ex instanceof MissingPathVariableException) { return HttpStatus.INTERNAL_SERVER_ERROR; } else if (ex instanceof MissingServletRequestParameterException) { return HttpStatus.BAD_REQUEST; } else if (ex instanceof ServletRequestBindingException) { return HttpStatus.BAD_REQUEST; } else if (ex instanceof ConversionNotSupportedException) { return HttpStatus.INTERNAL_SERVER_ERROR; } else if (ex instanceof TypeMismatchException) { return HttpStatus.BAD_REQUEST; } else if (ex instanceof HttpMessageNotReadableException) { return HttpStatus.BAD_REQUEST; } else if (ex instanceof HttpMessageNotWritableException) { return HttpStatus.INTERNAL_SERVER_ERROR; } else if (ex instanceof MethodArgumentNotValidException) { return HttpStatus.BAD_REQUEST; } else if (ex instanceof MissingServletRequestPartException) { return HttpStatus.BAD_REQUEST; } else if (ex instanceof BindException) { return HttpStatus.BAD_REQUEST; } else if (ex instanceof NoHandlerFoundException) { return HttpStatus.NOT_FOUND; } else if (ex instanceof AsyncRequestTimeoutException) { return HttpStatus.SERVICE_UNAVAILABLE; } else { return HttpStatus.INTERNAL_SERVER_ERROR; } } }
方法3: web.xml + controller 来实现
web.xml 中配置
<!--error page--> <error-page> <location>/error</location> </error-page>
package cn.mwee.wpos.report.controller.error; import cn.mwee.utils.error.ThrowableUtil; import cn.mwee.utils.log4j2.LogData; import cn.mwee.utils.uuid.UUIDUtil; import cn.mwee.wpos.common.utils.AlfredCommonUtils; import cn.mwee.wpos.report.consts.ResultCode; import cn.mwee.wpos.service.conts.ErrorCode; import cn.mwee.wpos.service.conts.ErrorDesc; import cn.mwee.wpos.service.dto.common.ErrorResult; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.NoHandlerFoundException; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import org.springframework.web.util.WebUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.Map; @Controller public class ErrorController { /** * 异常页面 * @param ex * @param response * @return */ @RequestMapping(path = "/error") public ModelAndView errorHtml(HttpServletRequest request,Exception ex,HttpServletResponse response) { int status=response.getStatus(); ModelAndView modelAndView; if(status == 403 || status == 404 || status == 500) { modelAndView = new ModelAndView("error/" +status); }else{ modelAndView = new ModelAndView("error/error"); } modelAndView.addObject("status",status); return modelAndView; } /** * 异常json * @param ex * @param response * @return */ @RequestMapping(path = "/error",consumes = MediaType.APPLICATION_JSON_UTF8_VALUE) @ResponseBody public Map<String, Object> errorJson(HttpServletRequest request,Exception ex,HttpServletResponse response) { Map<String,Object> result=new HashMap<>(); Object obj=request.getAttribute(DispatcherServlet.EXCEPTION_ATTRIBUTE); if(obj == null){ obj=request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE); } if(obj !=null && obj instanceof Exception){ ex=(Exception)obj; } ErrorResult error=new ErrorResult(ErrorCode.FAIL, ErrorDesc.FAIL, ThrowableUtil.getStackTrace(ex)); result.put(ResultCode.ERROR,error); return result; } }
上一篇: 黄鳝收购价格,你不知道的黄鳝