我们知道,系统中异常包括:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。在开发中,不管是dao层、service层还是controller层,都有可能抛出异常,在springmvc中,能将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护。
①1.Spring自带异常处理器
Spring中自带了一个异常处理器SimpleMappingExceptionResolver,它实现了HandlerExceptionResolver,使用SimpleMappingExceptionResolver需要在Spring.xml中配置以下节点
<!--参数方法名解析器-->
<bean id="methodNameResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/day10Exception/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--扫描包下所有的被标注的类-->
<context:component-scan base-package="cn.happy.day10Exception"/>
<!--异常处理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!--默认错误视图-->
<property name="defaultErrorView" value="error"/>
<!--异常类型-->
<property name="exceptionAttribute" value="ex"/>
</bean>
2.自定义一个异常
//自定义异常
public class UserNameException extends Exception {
//重写构造
public UserNameException() {
super();
}
public UserNameException(String message) {
super(message);
}
}
3.测试程序
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class FirstController {
@RequestMapping("/first")
public String doFirst(String username,int age) throws Exception {
//如果用户名不等于admin就出错
if(!username.equals("admin")){
throw new UserNameException("用户名错误");
}
//跳转到doSecond页面
return "doSecond";
}
}
然后我们在前台输入url来测试http://localhost:8080/first?username=admin1,故意传一个错误的值,程序就会转到默认错误视图页面。
②异常处理器提升版
需要在SimpleMappingExceptionResolver节点添加一个exceptionMappings属性,它是properties类型
<!--异常处理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!--默认错误视图-->
<property name="defaultErrorView" value="error"/>
<!--异常类型-->
<property name="exceptionAttribute" value="ex"/>
<property name="exceptionMappings">
<props>
<!--key:异常类型 val:出现异常后转到的页面-->
<prop key="UserNameException">name</prop>
<prop key="AgeException">age</prop>
</props>
</property>
</bean>
Key值代表自定义的异常类型,value代表出现当前异常后转向的jsp页面
③自定义异常处理器
自定义异常类型处理器需要实现HandlerExceptionResolver接口
//自定义异常处理器
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
/**
*
* @param httpServletRequest 请求
* @param httpServletResponse 响应
* @param o object对象
* @param e 返回异常类型
* @return
*/
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
//创建视图模型对象
ModelAndView mv=new ModelAndView();
//错误信息使用el方式打印出错误信息
mv.addObject("ex",e);
//判断异常类型
if(e instanceof UserNameException){
//如果是UserNameException异常则转到name.jsp页面
mv.setViewName("name");
}
if (e instanceof AgeException){
//如果是AgeException异常则转到name.jsp页面
mv.setViewName("age");
}
//返回视图对象
return mv;
}
}
处理器类
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Created by Administrator on 2018/3/30.
*/
@Controller
public class FirstController {
@RequestMapping("/first")
public String doFirst(String username,int age) throws Exception {
if(!username.equals("admin")){
throw new UserNameException("用户名错误");
}
if(age>60){
throw new AgeException("年龄错误");
}
return "doSecond";
}
}
最后配置Spring.xml
配置自定义的异常处理器的bean
<!--参数方法名解析器-->
<bean id="methodNameResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/day11selfException/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--扫描包下所有的被标注的类-->
<context:component-scan base-package="cn.happy.day11selfException"/>
<!--自定义异常处理器-->
<bean class="cn.happy.day11selfException.MyHandlerExceptionResolver"/>
④使用注解方式注册异常处理器
@ExceptionHandler()用来捕获系统发生的异常,默认捕获所有异常。它只有一个参数,是一个Class类型的数组,可以用来捕获class类型的异常。
自定义异常类
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Created by Administrator on 2018/3/30.
*/
@Controller
public class FirstController {
//只捕获UserNameException和AgeException类型的异常
@ExceptionHandler({UserNameException.class,AgeException.class})
public ModelAndView resolveException( Exception e) {
ModelAndView mv=new ModelAndView();
mv.addObject("ex",e);
//判断异常类型是否为UserNameException异常
if(e instanceof UserNameException){
//发生异常后要转到的页面
mv.setViewName("name");
}
//判断异常类型是否为AgeException异常
if (e instanceof AgeException){
//跳转页面
mv.setViewName("age");
}
//返回模型视图对象
return mv;
}
//URL
@RequestMapping("/first")
public String doFirst(String username,int age) throws Exception {
if(!username.equals("admin")){
throw new UserNameException("用户名错误");
}
if(age>60){
throw new AgeException("年龄错误");
}
return "doSecond";
}
}
Spring.xml配置
<!--参数方法名解析器-->
<bean id="methodNameResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/day11selfException/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--扫描包下所有的被标注的类-->
<context:component-scan base-package="cn.happy.day12annotationException"/>