而像IOException这类跟外在环境有关的异常,几乎是不可避免的(指不定哪一天哪一秒网络就挂了),但是当不期而遇时,程序还是要有所作为,所以编译器有必要督促一下程序员,Check一下,看看是否对这些可能不期而至的异常进行了处理。当Exception对象传递到某个节点后,程序就可以执行一些措施了,比如:给用户返回一个提示("系统繁忙,请重试"),给监控平台推送一个异常消息等等。
二、异常的统一返回处理 1、服务器处理 下面列举Tomcat和Nginx为例 Tomcat是Servlet容器,主要处理动态请求,在web.xml下配置,按http返回码或Exception类型来处理:
<error-page> <error-code>404</error-code> <location>/WEB-INF/views/error/404.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/WEB-INF/views/error/500.jsp</location> </error-page> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/WEB-INF/views/error/throwable.jsp</location> </error-page> Nginx是反向代理服务器,通过Http返回码也可以很方便地指定异常时的返回页面:
server { listen 80 ; server_name xx.com ; root /var/www ; index index.html ; error_page 404 /404.html ; location = /404.html { root /usr/share/nginx/html; } } 2、框架处理 下面列举Spring MVC的处理方式 (1)使用Spring MVC自带的简单异常处理器SimpleMappingExceptionResolver; (2)实现接口HandlerExceptionResolver 自定义异常处理器; (建议使用,可支持ajax等扩展) (3)使用@ExceptionHandler注解实现异常处理; 第(1)种,在spring-mvc.xml下配置
<!-- 将Controller抛出的异常转到特定视图 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!-- 不同异常分开跳转--> <!-- 可以自定义不同的异常--> <prop key="com.test.MyException1">/error/e1</prop> <prop key="com.test.MyException2">/error/e2</prop> <!-- 如果不想自定义异常,只配置下面的即可--> <prop key="java.lang.Throwable">/error/500</prop> </props> </property> </bean> 缺点:无法处理不需要返回html的请求;
第(2)种,自定义HandlerExceptionResolver接口的实现类
/** * 自定义异常处理器:支持ajax * */ public class MyExceptionHandler implements HandlerExceptionResolver { public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { /* 区分ajax */ boolean isAjax = request.getHeader("X-Requested-With") != null && "XMLHttpRequest".equals(request .getHeader("X-Requested-With").toString()); if (!isAjax) { if (ex instanceof com.test.MyException1) { return new ModelAndView("/error/e1"); } else if (ex instanceof com.test.MyException1) { return new ModelAndView("/error/e2"); } else { return new ModelAndView("/error/500"); } } String jsonRes = "{\"message\":\"" + "系统异常" + "\"}";// 自定义结构和前台对接 PrintWriter out = null; try { response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=UTF-8"); out = response.getWriter(); out.print(jsonRes); out.flush(); } catch (IOException e) { e.printStackTrace(); } finally { out.close(); } return null; } } 并在spring-mvc.xml下注册处理器
<bean id="exceptionHandler" class="com.test.MyExceptionHandler"/> 优点:可以处理ajax请求,也方便编码实现功能扩展,比如异常的监控等。 第(3)种,@ExceptionHandler注解
@Controller public class TestExceptionHandlerController { @ExceptionHandler({ MyException1.class }) public String exception(MyException1 e) { return "/error/e1"; } @RequestMapping("/marry") public void test() { throw new MyException1("有问题"); } } 缺点:@ExceptionHandler的方法,必须和可能抛异常的方法在一同个Controller下。(不建议使用) PS:实际情况,会将返回码的映射交给服务器,将动态请求的一些自定义异常或者功能扩展交给框架。
