Spring MVC 使用介绍(九)—— 异常处理
一、概述
Spring MVC异常处理功能的作用为:捕捉处理器的异常,并映射到相应视图
有4种方式:
- SimpleMappingExceptionResolver:通过配置的方式实现异常处理,该方式简单、无侵入性,但仅能获取到异常信息
- HandlerExceptionResolver:通过实现该接口并实例化为bean实现异常处理,该方式简单、无侵入性,并能够获取关于异常的更详细信息
- @ExceptionHandler:通过在控制器类或控制器类的基类中添加异常处理方法,从而实现单个控制器范围的异常处理,该方法对已有代码有侵入性
- web.xml的
标签: 可通过异常类型或error-code指定异常页面
多种方式的并存会增大维护的成本,因此异常处理方式选择其中一种,推荐使用SimpleMappingExceptionResolver,再配合web.xml中的
简单示例:
异常类
public class BusinessException extends RuntimeException { private String errorCode; public BusinessException(String errorCode, String msg) { super(msg); this.setErrorCode(errorCode); } public String getErrorCode() { return errorCode; } public void setErrorCode(String errorCode) { this.errorCode = errorCode; } }
public class ParameterException extends RuntimeException { public ParameterException(String msg) { super(msg); } }
控制器
@Controller public class TestController9 { @RequestMapping(value = "/controller.do", method = RequestMethod.GET) public void controller(HttpServletResponse response, Integer id) throws Exception { switch(id) { case 1: throw new BusinessException("10", "controller10"); case 2: throw new BusinessException("20", "controller20"); default: throw new ParameterException("Controller Parameter Error"); } } }
配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <mvc:annotation-driven /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> bean> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="defaultErrorView" value="error">property> <property name="exceptionAttribute" value="ex">property> <property name="exceptionMappings"> <props> <prop key="cn.matt.exception.BusinessException">error-businessprop> <prop key="cn.matt.exception.ParameterException">error-parameterprop> props> property> bean> <context:component-scan base-package="cn.matt" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.RestController" /> context:component-scan> beans>
error.jsp、error-business.jsp、error-parameter.jsp
<%@ page contentType="text/html; charset=UTF-8"%> <html> <head><title>Exception!title>head> <body> <% Exception e = (Exception)request.getAttribute("ex"); %> <H2>业务错误: <%= e.getClass().getSimpleName()%>H2> <hr /> <P>错误描述:P> <%= e.getMessage()%> <P>错误信息:P> <% e.printStackTrace(new java.io.PrintWriter(out)); %> body> html>
启动后,访问 http://localhost:8080/myweb/controller.do?id=1 即可验证
二、SimpleMappingExceptionResolver
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="defaultErrorView" value="error">property> <property name="exceptionAttribute" value="ex">property> <property name="exceptionMappings"> <props> <prop key="cn.matt.exception.BusinessException">error-businessprop> <prop key="cn.matt.exception.ParameterException">error-parameterprop> props> property> bean>
使用SimpleMappingExceptionResolver进行异常处理,具有集成简单、有良好的扩展性、对已有代码没有入侵性等优点,但该方法仅能获取到异常信息,若在出现异常时,对需要获取除异常以外的数据的情况不适用
具体如上例
三、HandlerExceptionResolver
@Component public class MyExceptionHandler implements HandlerExceptionResolver { public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { Mapmodel = new HashMap (); model.put("ex", ex); // 根据不同错误转向不同页面 if(ex instanceof BusinessException) { return new ModelAndView("error-business", model); }else if(ex instanceof ParameterException) { return new ModelAndView("error-parameter", model); } else { return new ModelAndView("error", model); } } }
使用实现HandlerExceptionResolver接口的异常处理器进行异常处理,具有集成简单、有良好的扩展性、对已有代码没有入侵性等优点,同时,在异常处理时能获取导致出现异常的对象,有利于提供更详细的异常处理信息。
测试方式为:在上例配置文件中注释掉SimpleMappingExceptionResolver的配置,并添加HandlerExceptionResolver的上述代码即可
四、@ExceptionHandler
@Controller public class TestController9 { @RequestMapping(value = "/controller.do", method = RequestMethod.GET) public void controller(HttpServletResponse response, Integer id) throws Exception { switch(id) { case 1: throw new BusinessException("10", "controller10"); case 2: throw new BusinessException("20", "controller20"); default: throw new ParameterException("Controller Parameter Error"); } } @ExceptionHandler public String exp(HttpServletRequest request, Exception ex) { request.setAttribute("ex", ex); // 根据不同错误转向不同页面 if(ex instanceof BusinessException) { return "error-business"; }else if(ex instanceof ParameterException) { return "error-parameter"; } else { return "error"; } } }
使用@ExceptionHandler注解实现异常处理,具有集成简单、扩展性好、不需要附加Spring配置等优点,但该方法对已有代码存在入侵性,在异常处理时不能获取除异常以外的数据。
测试方式为:在上例配置文件中注释掉SimpleMappingExceptionResolver的配置,并将控制器修改为上述代码即可
五、web.xml的
对于非控制器产生的异常,如404,spring mvc的异常机制无法捕获,此类异常可在web.xml中通过
<error-page> <exception-type>java.lang.Throwableexception-type> <location>/500.jsplocation> error-page> <error-page> <error-code>500error-code> <location>/500.jsplocation> error-page> <error-page> <error-code>404error-code> <location>/404.jsplocation> error-page>
补充:
异常输出为json字符串(而非页面)的方式如下:
@ExceptionHandler public void exp(HttpServletRequest request, HttpServletResponse response, Exception ex) throws IOException { response.setContentType("text/plain;charset=UTF-8"); response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); Mapmap = new HashMap (); map.put("errorCode", 200); map.put("errorMsg", ex.getMessage()); response.getWriter().write(JSON.toJSONString(map)); }
参考:
使用Spring MVC统一异常处理实战
springmvc处理异常的4种方式
Spring MVC 异常处理详解