Spring MVC 的SimpleMappingExceptionResolver是一个简单的异常处理bean,说他简单是因为SimpleMappingExceptionResolver只能获得内置的异常信息,用户无法将自定义的异常信息带到页面上供用户查看,且SimpleMappingExceptionResolver不支持ajax的异常处理。为了能够让异常体制更具个性化。我们常做的方法是实现HandlerExceptionResolver接口自定义自己的异常处理器。下面介绍另外一种方法:重写SimpleMappingExceptionResolver来实现异常的个性化。
SimpleMappingExceptionResolver异常处理其核心是doResolveException()
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) {
String viewName = this.determineViewName(ex, request);
if(viewName != null) {
Integer statusCode = this.determineStatusCode(request, viewName);
if(statusCode != null) {
this.applyStatusCodeIfPossible(request, response, statusCode.intValue());
}
return this.getModelAndView(viewName, ex, request);
} else {
return null;
}
}
所以我们要做的就是重写这个方法
String viewName = this.determineViewName(ex, request);
if(viewName != null) {
Integer statusCode = this.determineStatusCode(request, viewName);
if(statusCode != null) {
this.applyStatusCodeIfPossible(request, response, statusCode.intValue());
}
return this.getModelAndView(viewName, ex, request);
} else {
return null;
}
}
package com.me.common.exception;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.io.IOException;
import java.util.Properties;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.me.endpoint.GrantResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
public class MyExceptionResolver extends SimpleMappingExceptionResolver {
private String defaultErrorView;
private Properties exceptionMappings;
public MyExceptionResolver() {
}
@Override
public void setDefaultErrorView(String defaultErrorView) {
this.defaultErrorView = defaultErrorView;
super.setDefaultErrorView(defaultErrorView);
}
@Override
public void setExceptionMappings(Properties exceptionMappings) {
this.exceptionMappings = exceptionMappings;
super.setExceptionMappings(exceptionMappings);
}
@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) {
boolean isAjax = this.isJsonRequest(handler);
return isAjax? this.jsonExceptionHandler(response, ex): this.generalExceptionHandler(request, response, ex);
}
private boolean isJsonRequest(Object handler) {
HandlerMethod method = (HandlerMethod)handler;
ResponseBody body = (ResponseBody)method.getMethodAnnotation(ResponseBody.class);
return body != null;
}
//ajax异步请求
private ModelAndView jsonExceptionHandler(HttpServletResponse response, Exception e) {
ServletOutputStream stream = null;
try {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
stream = response.getOutputStream();
String errorMsg = "系统出错了";
if(e instanceof GenericException || e instanceof EcouponException){
errorMsg = e.getMessage();
}
stream.write(JSON.toJSONBytes( new GrantResult("faild", errorMsg), new SerializerFeature[]{SerializerFeature.QuoteFieldNames}));
} catch (Exception var16) {
} finally {
if(stream != null) {
try {
stream.close();
} catch (IOException var15) {
var15.printStackTrace();
}
}
}
return new ModelAndView();
}
//普通请求
private ModelAndView generalExceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception ex) {
String errorLog = String.format("web请求[%s]发生异常:%s", new Object[]{request.getServletPath(), ex.getMessage()});
this.logger.error(errorLog, ex);
ModelAndView mav = new ModelAndView();
String errorMsg = "系统出错了";
if(ex instanceof GenericException || ex instanceof EcouponException){
errorMsg = ex.getMessage();
}
mav.addObject("msg", errorMsg);
String name = ex.getClass().getName();
String path = this.exceptionMappings.getProperty(name);
String wrapperPath = StringUtils.isEmpty(path)?defaultErrorView:path;
mav.setViewName(wrapperPath);
return mav;
}
}
最后配置该bean:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.io.IOException;
import java.util.Properties;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.me.endpoint.GrantResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
public class MyExceptionResolver extends SimpleMappingExceptionResolver {
private String defaultErrorView;
private Properties exceptionMappings;
public MyExceptionResolver() {
}
@Override
public void setDefaultErrorView(String defaultErrorView) {
this.defaultErrorView = defaultErrorView;
super.setDefaultErrorView(defaultErrorView);
}
@Override
public void setExceptionMappings(Properties exceptionMappings) {
this.exceptionMappings = exceptionMappings;
super.setExceptionMappings(exceptionMappings);
}
@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) {
boolean isAjax = this.isJsonRequest(handler);
return isAjax? this.jsonExceptionHandler(response, ex): this.generalExceptionHandler(request, response, ex);
}
private boolean isJsonRequest(Object handler) {
HandlerMethod method = (HandlerMethod)handler;
ResponseBody body = (ResponseBody)method.getMethodAnnotation(ResponseBody.class);
return body != null;
}
//ajax异步请求
private ModelAndView jsonExceptionHandler(HttpServletResponse response, Exception e) {
ServletOutputStream stream = null;
try {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
stream = response.getOutputStream();
String errorMsg = "系统出错了";
if(e instanceof GenericException || e instanceof EcouponException){
errorMsg = e.getMessage();
}
stream.write(JSON.toJSONBytes( new GrantResult("faild", errorMsg), new SerializerFeature[]{SerializerFeature.QuoteFieldNames}));
} catch (Exception var16) {
} finally {
if(stream != null) {
try {
stream.close();
} catch (IOException var15) {
var15.printStackTrace();
}
}
}
return new ModelAndView();
}
//普通请求
private ModelAndView generalExceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception ex) {
String errorLog = String.format("web请求[%s]发生异常:%s", new Object[]{request.getServletPath(), ex.getMessage()});
this.logger.error(errorLog, ex);
ModelAndView mav = new ModelAndView();
String errorMsg = "系统出错了";
if(ex instanceof GenericException || ex instanceof EcouponException){
errorMsg = ex.getMessage();
}
mav.addObject("msg", errorMsg);
String name = ex.getClass().getName();
String path = this.exceptionMappings.getProperty(name);
String wrapperPath = StringUtils.isEmpty(path)?defaultErrorView:path;
mav.setViewName(wrapperPath);
return mav;
}
}
<bean class="com.me.common.exception.XExceptionResolver">
<!-- view name resolved using bean of type InternalResourceViewResolver (declared in mvc-view-config.xml) -->
<property name="defaultErrorView" value="exception"/>
<!-- needed otherwise exceptions won't be logged anywhere -->
<property name="exceptionMappings">
<props>
<prop key="com.me.common.exception.GenericException">error/error</prop>
<prop key="com.me.common.exception.EcouponException">error/error</prop>
<prop key="java.lang.Exception">error/error</prop>
</props>
</property>
</bean>
<!-- view name resolved using bean of type InternalResourceViewResolver (declared in mvc-view-config.xml) -->
<property name="defaultErrorView" value="exception"/>
<!-- needed otherwise exceptions won't be logged anywhere -->
<property name="exceptionMappings">
<props>
<prop key="com.me.common.exception.GenericException">error/error</prop>
<prop key="com.me.common.exception.EcouponException">error/error</prop>
<prop key="java.lang.Exception">error/error</prop>
</props>
</property>
</bean>