配置文件形式
<!-- 控制器异常处理,配置后,异常会打印到页面上,但是后台console就不不打印异常,很难找到问题所在。页面要是没el打印输出,更没法找原因了。要在代码里面trycatch打印出来才可以。 -->
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 配置异常的属性值为exp,那么在错误页面中可以通过 ${exp} 来获取异常的信息
如果不配置这个属性,它的默认值为exception -->
<property name="exceptionAttribute" value="exp"></property>
<property name="exceptionMappings">
<props>
<prop key="java.lang.Exception">
error_all
</prop>
</props>
</property>
</bean>
页面使用el表达式接收异常信息打印出来。
jsp页面:
故意输错id,打印出来异常信息,并不具体。
- 注意:这个坑点,异常会打印到页面上,但是后台console就不不打印异常,很难找到问题所在。页面要是没el打印输出,更没法找原因了。要在controller代码里面trycatch打印出来才可以。
继承SimpleMappingExceptionResolver类实现方式
新建类:CustomSimpleMappingExceptionResolver
/**
* 自定义统一异常处理,主要针对当前UI架构进行修改。如是加载页面就显示异常页面,ajax的话就返回异常信息
*/
public class CustomSimpleMappingExceptionResolver extends
SimpleMappingExceptionResolver {
private static Logger logger = Logger.getLogger("web");
/**
* 重写Spring统一异常处理方法
*/
@Override
protected ModelAndView doResolveException(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex){
logger.info("-------------------------->系统异常", ex);
// ex.printStackTrace();
logger.info("<--------------------------");
StringBuffer requestUrl = request.getRequestURL();
String contextPath = request.getContextPath();
String path = requestUrl.substring(requestUrl.indexOf(contextPath)+contextPath.length()+1);
String viewName = "error_all";
if(path.startsWith("mobile") || path.startsWith("m")){
viewName = "error_all";
}
//返回消息
ModelAndView mv = new ModelAndView();
mv.setViewName(viewName);
StringWriter sw = new StringWriter();
ex.printStackTrace(new PrintWriter(sw, true));
mv.addObject("exp", sw.toString());
//判断是否异常处理
if (!(request.getHeader("accept").indexOf("application/json") > -1 || (request
.getHeader("X-Requested-With") != null && request.getHeader(
"X-Requested-With").indexOf("XMLHttpRequest") > -1))) {
request.setAttribute("info", "操作失败,系统发生异常。");
Integer statusCode = determineStatusCode(request, viewName);
if (statusCode != null) {
applyStatusCodeIfPossible(request, response, statusCode);
}
return mv;
} else {// JSON格式返回
//否异步加载页面
if (request.getParameter("loadPage") != null) {
return mv;
}
//非异步加载页面,返回信息
Map<String,Object> map = new HashMap<String,Object>();
map.put("code", "01");
map.put("message", "异常");
return new ModelAndView(new MappingJacksonJsonView(),map);
}
}
}
同时配置文件增加bean:
<!-- 统一异常处理 -->
<bean class="com.tgb.exception.CustomSimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.exception">errot_all</prop>
</props>
</property>
</bean>
这样页面的异常信息可以通过代码来控制,同时可以对页面或者json请求进行响应。
注解形式@ExceptionHandler
其实等同于配置文件的形式,区别是要每个方法都写。
@RequestMapping("/exception")
@ExceptionHandler
public String exceptionTest(String id, Exception ex, HttpServletRequest request) {
User findById = userService.findById(Integer.parseInt(id));
System.out.println(" --------------" + findById.getUserName() + "-------- " + findById.getAge());
request.setAttribute("exp", ex.getMessage());
return "error_all";
}
总结
开发过程中要留意一下异常统一配置,如果是第一种配置的化,页面必须要EL输出,同时后台console要打印出来错误信息,不然什么都没有。一些老项目就是配置了这个,写代码些习惯了不在controller 捕获异常,导致页面没有错误信息,ajax报error,一脸懵逼。
同样使用注解形式的也是一样的,区别就是每个方法都手动的写返回页面。会占用业务里面的页面跳转,不建议使用。
使用继承类方式个人觉得比较好,统一打印异常,统一响应多种请求方式。对一类请求进行不用的异常返回。