SpringMVC作为一个优秀的Web层开发框架,在框架中已经集成了异常处理机制,可以帮我们灵活地处理程序中发生的异常,提高了我们程序的稳定性,令我们对程序运行中发生的异常更加可以控制,这篇记录的就是SpringMVC框架中的对于异常的处理机制。
本文中的所有程序都是基于SSM框架环境。对于搭建SSM环境有疑问的参考这篇文章:
没有异常处理机制的时候吗,页面会出现类似这样的页面:
对于用户来说,这样的提示并不友好。SpringMVC中对于这种情况的处理机制,就被称作是异常处理机制。该机制可以让用户访问程序的时候,如果发生程序异常,那么会选择一种友好的方式提醒用户。而且在正式开发中,完全可以由前端开发人员制作一个精美友好的错误页面,让用户可以获得良好的访问体验。
系统中异常包括两类:预期异常(检查型异常)和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息, 后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端控制器交由异常处理器进行异常处理,如下图
SpringMVC中对于异常的处理机制一共有三种,分别是:
SimpleMappingExceptionResolver
下面介绍了不止这些异常处理机制。
准备一个controller类:
package com.bones.controller;
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;
@Controller
public class ExceptionTestController {
@RequestMapping("demo1.do")
public String testDemo1(){
int i = 1/0;//模拟异常
return "success.jsp";
}
@RequestMapping("demo2.do")
public String testDemo2(){
String s = null;
System.out.println(s.length());
return "success.jsp";
}
@ExceptionHandler(value = {ArithmeticException.class})
public ModelAndView handleException(){
ModelAndView mv = new ModelAndView();
mv.setViewName("error1.jsp");
return mv;
}
}
其中访问
demo1.do
,因为有ArithmeticException
所以会被捕获,执行handleException()
方法,但是访问demo2.do
,因为不是ArithmeticException
所以页面还是报错:如果希望这个空指针异常也能被捕获的话,那么需要修改
@ExceptionHandler
注解的参数:@ExceptionHandler(value = {ArithmeticException.class,NullPointerException.class}) public ModelAndView handleException(){ ModelAndView mv = new ModelAndView(); mv.setViewName("error1.jsp"); return mv; }
简单看一下注解@ExceptionHandler
的源码:
value属性值需要传入一个Throwable
类型的字节码。所以上面是这么写的:
@ExceptionHandler(value = {ArithmeticException.class,NullPointerException.class})
在Controller中写一个方法,并在该方法上使用@ExceptionHandler
注解,当这个Controller中发生异常的时候,该注解的方法就会处理异常。
value值不写的时候,默认就是不处理任何异常。
这个注解的缺点就是:只能处理当前Controller中的异常。
package com.bones.exceptionhandler;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = {ArithmeticException.class,NullPointerException.class})
public ModelAndView handleException(){
ModelAndView mv = new ModelAndView();
mv.setViewName("error1.jsp");
return mv;
}
}
注意要包扫描:applicationContext.xml
中
<context:component-scan base-package="com.bones.service,com.bones.exceptionhandler"/>
注意:@ControllerAdvice+@ExceptionHandler定义的是全局异常处理器,但是如果controller内部还用
@ExceptionHandler
还定义异常处理,则controller中的异常处理优先于全局异常处理器
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.ArithmeticException">redirect:/error1.jspprop>
<prop key="java.lang.NullPointerException">redirect:/error2.jspprop>
props>
property>
bean>
GlobleExceptionHandler
package com.bones.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import java.util.Properties;
@Configuration
public class GlobleExceptionHandler {
@Bean
public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
Properties properties = new Properties();
properties.put("java.lang.ArithmeticException","error1.jsp");
properties.put("java.lang.NullPointerException","error1.jsp");
resolver.setExceptionMappings(properties);
return resolver;
}
}
注意还要加上包扫描:
<context:component-scan base-package="com.bones.service,com.bones.config"/>
package com.bones.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Configuration
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
ModelAndView mv = new ModelAndView();
if (ex instanceof NullPointerException){
mv.setViewName("error1.jsp");
}
if (ex instanceof ArithmeticException){
mv.setViewName("error2.jsp");
}
mv.addObject("msg",ex);
return mv;
}
}
以上4中SpringMVC的异常处理机制各有优劣,各位在使用SpringMVC的异常处理机制的时候,可以根据实际需求和自身喜好来进行配置开发。