统一异常处理
在Spring MVC应用中,不管是怎样对底层数据库的操作还是业务层或者控制层的操作
都会遇到不可避免的各种异常需要处理,如果每个过程都单独对异常进行处理,那么
系统的代码耦合度高,工作量大且不好统一,维护工作也很麻烦。
如果将所有类型的异常从各个层中解耦出来,这样既保证了相关处理过程的功能单一
又实现了异常信息的统一处理和维护。
1、实例介绍
模拟实例在请求的url中出现数学异常 i =10 /0;跳转到指定的页面。
同时可以指定其他的错误机制,此时仅仅作为列子:
搭建基本的测试环境:
MyFormatter.java
public class MyFormatter implements Formatter<Date> { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); @Override public Date parse(String s, Locale locale) throws ParseException { return simpleDateFormat.parse(s); } @Override public String print(Date date, Locale locale) { return simpleDateFormat.format(date); } }
MyException.java
public class MyException extends Exception { public MyException() { super(); } public MyException(String msg) { super(msg); } }
error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" isErrorPage="true" %> <html> <head> <title>Title</title> </head> <body> error:<%=exception.getMessage()%> </body> </html>
ErrorSql.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java"
isErrorPage="true" %>
<html> <head> <title>Title</title> </head> <body>
error:<%=exception.getMessage()%>
</body> </html>
test.java
@Controller public class test { @RequestMapping("/test") public String test(){ int i = 10 /0; System.out.println(i); return "addGoods"; } }
配置文件:
<?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.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <mvc:annotation-driven></mvc:annotation-driven> <context:component-scan base-package="controller"/> <!--视图解析--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="suffix" value=".jsp"/> <property name="prefix" value="/WEB-INF/jsp/"/> </bean> <!--注册Formatter --> <bean id="formattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="formatters"> <set> <bean class="formatter.MyFormatter"></bean> </set> </property> </bean> <mvc:annotation-driven conversion-service="formattingConversionService"></mvc:annotation-driven> </beans>
2、SimpleMappingExceptionResolver
org.springframework.web.servlet.handler.SimpleMappingExceptionResolver类统一处理异常时需要在配置文件中指定
配置异常类和View的对应关系。
dispatcher-servlet.xml
<context:component-scan base-package="controller"/> <!--视图解析--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="suffix" value=".jsp"/> <property name="prefix" value="/WEB-INF/jsp/"/> </bean> <!--注册Formatter --> <bean id="formattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="formatters"> <set> <bean class="formatter.MyFormatter"></bean> </set> </property> </bean> <mvc:annotation-driven conversion-service="formattingConversionService"></mvc:annotation-driven> <!--异常--> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="defaultErrorView" value="erroes/error" /> </bean>
启动测试:
其他使用方法:
<!--异常-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!--定义默认异常处理的页面 -->
<property name="defaultErrorView" value="erroes/error" />
<!--定义异常吃力页面来获取异常信息的变量名,默认时exception -->
<property name="exceptionAttribute" value="ex"/>
<!--定义需要特殊处理的异常,用类名或者路径名作为key,异常页名作为值 -->
<property name="exceptionMappings">
<props>
<prop key="exception.MyException" >MyException</prop>
</props>
</property>
</bean>
3、HandlerExceptionResolver
org.springframework.web.servlet.HandlerExceptionResolver接口用于解析请求处理过程中所产生的异常
开发者可以根据该接口的实现类进行Spring MVC应用的异常统一处理。
MyExceptionHandler.java
package exception; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; public class MyExceptionHandler implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) { Map<String,Object> model = new HashMap<String, Object>(); model.put("ex",e); //根据转向不同的页面统一处理 if(e instanceof SQLException){ return new ModelAndView("erroes/ErrorSql",model); }else { return new ModelAndView("erroes/error",model); } } }
此时可同时处理多个异常,因为只是测试所以就简单的写了两个!!!
需要将是实现类在配置文件中托管给spring MVC框架才能进行统一的异常处理。
配置文件:
<mvc:annotation-driven></mvc:annotation-driven> <context:component-scan base-package="controller"/> <!--视图解析--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="suffix" value=".jsp"/> <property name="prefix" value="/WEB-INF/jsp/"/> </bean> <!--注册Formatter --> <bean id="formattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="formatters"> <set> <bean class="formatter.MyFormatter"></bean> </set> </property> </bean> <mvc:annotation-driven conversion-service="formattingConversionService"></mvc:annotation-driven> <!-- 托管MyExceptionHandler--> <bean class="exception.MyExceptionHandler"></bean>
测试:
4、@ExceptionHandler
创建BaseController类,并在该注解中使用@ExceptionHandler注解声明异常处理的方法
BaseController.java
package controller; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.sql.SQLException; public abstract class BaseController { //异常的注解方式 @ExceptionHandler public String exception(HttpServletRequest request, HttpServletResponse response, Object o, Exception e){ request.setAttribute("ex",e); //根据转向不同的页面统一处理 if(e instanceof SQLException){ return "erroes/ErrorSql"; }else { return "erroes/error"; } } }
将所有都需要异常处理的Controller都继承上述的类:
@Controller public class testexController extends BaseController { @RequestMapping("/test1") public String test(){ int i = 10 /0; System.out.println(i); return "addGoods"; } }
此时的配置文件:
<mvc:annotation-driven></mvc:annotation-driven> <context:component-scan base-package="controller"/> <!--视图解析--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="suffix" value=".jsp"/> <property name="prefix" value="/WEB-INF/jsp/"/> </bean> <!--注册Formatter --> <bean id="formattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="formatters"> <set> <bean class="formatter.MyFormatter"></bean> </set> </property> </bean> <mvc:annotation-driven conversion-service="formattingConversionService"></mvc:annotation-driven>
测试:
基于异常的处理就是以上的三种方法,此时都是简单的测试,具体的根据自身的需要去实现。