在学习过程中,dao层会经常往service层抛异常,再向controller层抛出异常。此时要么控制器层异常继续抛向页面, 要么在控制器层中做大量异常判断,返回相应视图。无法统一管理控制器层的异常,而不是每个控制器都做异常判断。
由网上资料我发现了一个办法:通过SimpleMappingExceptionResolver接口实现异常处理。
有2步
1. 创建SimpleMappingExceptionResolver子类,并实现doResolveException 方法。
2. 在spring 配置文件中配置bean信息。
spring配置:
<!-- 异常处理 -->
<bean id="exceptionResolver"
class="com.**.**.exception.CustomSimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!-- 不同异常跳转不同异常页面 -->
<prop key="com.**.**.exception.CustomException">error/CE</prop>
<prop key="com.**.**.exception.CustomerLoginTimeOutException">error/CustomerLoginTimeOutException</prop>
<prop key="com.**.**.exception.PropertyLoginTimeOutException">error/PropertyLoginTimeOutException</prop>
</props>
</property>
<!-- 默认错误页面,当找不到上面mappings中指定的异常对应视图时,使用本默认配置 -->
<property name="defaultErrorView" value="/error/500" />
<!-- 默认HTTP状态码 -->
<property name="defaultStatusCode" value="500" />
</bean>
CustomSimpleMappingExceptionResolver 类配置:
//import com.alibaba.fastjson.support.spring.FastJsonJsonView;
public class CustomSimpleMappingExceptionResolver extends SimpleMappingExceptionResolver {
static Log log = LogFactory.getLog(CustomSimpleMappingExceptionResolver.class);
@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
// Expose ModelAndView for chosen error view.
String viewName = determineViewName(ex, request);
HandlerMethod mathod = (HandlerMethod) handler;
ResponseBody body = mathod.getMethodAnnotation(ResponseBody.class);
// 判断有没有@ResponseBody的注解没有的话调用父方法
if (body == null) {
// return super.doResolveException(request, response, handler, ex);
Integer statusCode = determineStatusCode(request, viewName);
if (statusCode != null) {
applyStatusCodeIfPossible(request, response, statusCode);
}
request.setAttribute("errorMsg", ex.getMessage());
return getModelAndView(viewName, ex, request);
}
ModelAndView mv = new ModelAndView();
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);
// }
// request.setAttribute("errorMsg", ex.getMessage());
// return getModelAndView(viewName, ex, request);
// } else {// JSON格式返回
try {
// 设置ContentType
log.info(ex.getMessage());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
// 避免乱码
response.setCharacterEncoding("UTF-8");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
PrintWriter writer = response.getWriter();
JSONObject jo = new JSONObject();
if (ex instanceof BusinessException) {
jo.put("code", ((BusinessException) ex).getCode());
jo.put("message", ((BusinessException) ex).getMessage());
if (null != ((BusinessException) ex).getData()) {
jo.put("data", ((BusinessException) ex).getData());
}
}
// else if(ex instanceof AgentLoginTimeOutException){
// jo.put("code", 8001);
// jo.put("message", ((AgentLoginTimeOutException)ex).getMessage());
// }else if(ex instanceof ManagerLoginTimeOutException){
// jo.put("code", 8001);
// jo.put("message", ((ManagerLoginTimeOutException)ex).getMessage());
// }else if(ex instanceof CustomerLoginTimeOutException){
// jo.put("code", 8001);
// jo.put("message", ((CustomerLoginTimeOutException)ex).getMessage());
// }
log.info(jo.toString());
// System.out.println(jo.toString());
writer.write(jo.toString());
writer.flush();
} catch (Exception e) {
}
// return getModelAndView(viewName, ex, request);
// 或者使用view视图返回
// FastJsonJsonView view = new FastJsonJsonView();
// Map<String, Object> attributes = new HashMap<String, Object>();
// attributes.put("success", Boolean.FALSE);
// attributes.put("msg", ex.getMessage());
// view.setAttributesMap(attributes);
// mv.setView(view);
// return mv;
return mv;
// }
} else {
return mv;
}
}
}
开发过程中要留意一下异常统一配置,写代码习惯了不在controller 捕获异常,导致页面没有错误信息,ajax报error,一脸懵逼。使用继承类方式我觉得比较好,统一打印异常,统一响应多种请求方式。对一类请求进行不用的异常返回。