SpringMVC 统一异常处理

先说说 网上流传的几种处理方式:
方式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;
}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值