欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringMVC(十七)_异常处理

程序员文章站 2022-04-17 14:40:11
...

       前言:本篇主要介绍SpringMVC的数据绑定流程中数据校验的相关概念与用法

       Spring MVC 通过HandlerExceptionResolver处理程序的异常,包括 Handler 映射、数据绑定以及目标方法执行时发生的异常。测试页面如下:

SpringMVC(十七)_异常处理
            
    
    博客分类: SpringMVC SpringMVC异常处理 
  

1. HandlerExceptionResolver的实现类

SpringMVC(十七)_异常处理
            
    
    博客分类: SpringMVC SpringMVC异常处理 
      DispatcherServlet 会默认装配HandlerExceptionResolver实现类

      若没有使用 <mvc:annotation-driven/> 配置:

  • AnnotationMethodHandlerExceptionResolver(已过时);
  • ResponseStatusExceptionResolver;
  • DefaultHandlerExceptionResolver;

       若使用 <mvc:annotation-driven/> 配置

  • ExceptionHandlerExceptionResolver;
  • ResponseStatusExceptionResolver;
  • DefaultHandlerExceptionResolver;

       使用SpringMVC作为MVC框架时,一般都需要配置<mvc:annotation-driven/>,ExceptionHandlerExceptionResolver也是主要处理Hander中异常的主要手段。

2. ExceptionHandlerExceptionResolver

       ExceptionHandlerExceptionResolver主要处理控制器Handler中用@ExceptionHandler注解定义的方法。

      @ExceptionHandler 注解定义的方法优先级问题:例如. 发生的是NullPointerException,但是声明的异常有RuntimeException 和 Exception,此候会根据异常的最近继承关系找到继承深度最浅的那个@ExceptionHandler注解方法,即标记了 RuntimeException 的方法。

       ExceptionHandlerMethodResolver内部若找不到@ExceptionHandler注解的方法,会全局找@ControllerAdvice中的@ExceptionHandler方法。

 

       后台测试代码:

@RequestMapping("/testExceptionHandlerExceptionResolver.action")
public String testExceptionHandlerExceptionResolver(@RequestParam("i") int i){
    System.out.println("result: " + (10 / i));   // 除数为0的话会出现ArithmeticException运行时异常
    return "success";
}

/**
 * 1. 在 @ExceptionHandler 方法的入参中可以加入 Exception 类型的参数, 该参数即对应发生的异常对象
 * 2. @ExceptionHandler 方法的入参中不能传入 Map. 若希望把异常信息传导页面上, 需要使用 ModelAndView 作为返回值
 * 3. @ExceptionHandler 方法标记的异常有优先级的问题. 
 * 4. @ControllerAdvice: 如果在当前 Handler 中找不到 @ExceptionHandler 方法来出来当前方法出现的异常, 
 * 则将去 @ControllerAdvice 标记的类中查找 @ExceptionHandler 标记的方法来处理异常. 
 */
@ExceptionHandler({ArithmeticException.class})
public ModelAndView handleArithmeticException(Exception ex){
    System.out.println("【ArithmeticException】: " + ex);
    ModelAndView mv = new ModelAndView("error");
    mv.addObject("exception", ex);
    return mv;
}

@ExceptionHandler({RuntimeException.class})
public ModelAndView handleArithmeticException2(Exception ex){
    System.out.println("【RuntimeException】: " + ex);
    ModelAndView mv = new ModelAndView("error");
    mv.addObject("exception", ex);
    return mv;
}

        如果testExceptionHandlerExceptionResolver方法抛出ArithmeticException异常,根据异常优先级,会先被handleArithmeticException方法捕获。如果上述handleArithmeticException和handleArithmeticException2异常处理方法都未定义,但在SpringMVCTestExceptionHandler类中定义异常处理,如下所示:

@ControllerAdvice
public class SpringMVCTestExceptionHandler {

    @ExceptionHandler({ArithmeticException.class})
    public ModelAndView handleArithmeticException(Exception ex){
        System.out.println("【ControllerAdvice】" + ex);
        ModelAndView mv = new ModelAndView("error");
        mv.addObject("exception", ex);
        return mv;
    }
    
}

        处理器内部若找不到@ExceptionHandler注解的方法,会全局找@ControllerAdvice中的@ExceptionHandler方法进行异常处理。

 

 3. ResponseStatusExceptionResolver

         控制器方法上或是修饰异常类使用@ResponseStatus 注解,则ResponseStatusExceptionResolver会使用这个注解的属性进行处理

         后台测试代码:

         1. 首先@ResponseStatus修饰异常处理类:

@ResponseStatus(value=HttpStatus.FORBIDDEN, reason="自定义异常")
public class CustomizedException extends RuntimeException{
    private static final long serialVersionUID = 1L;
}

           2. 然后是@ResponseStatus在控制器中修饰方法(测试中同时是功能处理方法):

@ResponseStatus(reason="测试",value=HttpStatus.NOT_FOUND)
@RequestMapping("/testResponseStatusExceptionResolver.action")
public String testResponseStatusExceptionResolver(@RequestParam("i") int i){
    if(i == 13){
        throw new CustomizedException();
    }
    System.out.println("testResponseStatusExceptionResolver...");
    
    return "success";
}

           说明:若i == 13,则返回异常类定义的响应;若i  != 13,则返回异常方法定义的响应。

         3. 前台代码略,可参见附件代码

        4. 测试结果

            (测试的时候将ExceptionHandlerExceptionResolver对异常处理的操作去掉,以免会捕获i == 13时抛出的自定义异常!)

            当i == 13时

SpringMVC(十七)_异常处理
            
    
    博客分类: SpringMVC SpringMVC异常处理 
               当 i != 13时:

SpringMVC(十七)_异常处理
            
    
    博客分类: SpringMVC SpringMVC异常处理  4. DefaultHandlerExceptionResolver

        DefaultHandlerExceptionResolver对一些特殊的异常进行处理,如:

  • NoSuchRequestHandlingMethodException;

  • HttpRequestMethodNotSupportedException;

  • HttpMediaTypeNotSupportedException;

  • HttpMediaTypeNotAcceptableException等

        此处举个实例,方法不仅支持POST方法,前台以GET方式映射:
@RequestMapping(value="/testDefaultHandlerExceptionResolver.action",method=RequestMethod.POST)
public String testDefaultHandlerExceptionResolver(){
    System.out.println("testDefaultHandlerExceptionResolver...");
    return "success";
}
       测试结果为:
 SpringMVC(十七)_异常处理
            
    
    博客分类: SpringMVC SpringMVC异常处理 
 

5. SimpleMappingExceptionResolver

       如果希望对所有异常进行统一处理,可以使用SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常。
       在SpringMVC配置文件中配置SimpleMappingExceptionResolver:
<!-- 配置使用 SimpleMappingExceptionResolver 来映射异常 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionAttribute" value="ex"></property>
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.ArrayIndexOutOfBoundsException">error_</prop>
        </props>
    </property>
</bean> 
        将所有ArrayIndexOutOfBoundsException异常想页面视图名为error_的视图报告,异常参数为ex。

        后台测试代码为:

@RequestMapping("/testSimpleMappingExceptionResolver.action")
public String testSimpleMappingExceptionResolver(@RequestParam("i") int i){
    String [] vals = new String[10];
    System.out.println(vals[i]);
    return "success";
}

          vals数组大小为10,若入参的i大小超过9,则会数组越界,会抛出java.lang.ArrayIndexOutOfBoundsException异常。

        前台代码如下(入参i=22):

<a href="testSimpleMappingExceptionResolver.action?i=22">测试SimpleMappingExceptionResolver</a>

         测试结果如下,可见数组越界异常正确传给错误页面同一接收。

SpringMVC(十七)_异常处理
            
    
    博客分类: SpringMVC SpringMVC异常处理  

 代码下载来源:http://super-wangj.iteye.com/blog/2388430

  • SpringMVC(十七)_异常处理
            
    
    博客分类: SpringMVC SpringMVC异常处理 
  • 大小: 9.4 KB
  • SpringMVC(十七)_异常处理
            
    
    博客分类: SpringMVC SpringMVC异常处理 
  • 大小: 11.4 KB
  • SpringMVC(十七)_异常处理
            
    
    博客分类: SpringMVC SpringMVC异常处理 
  • 大小: 9.2 KB
  • SpringMVC(十七)_异常处理
            
    
    博客分类: SpringMVC SpringMVC异常处理 
  • 大小: 8 KB
  • SpringMVC(十七)_异常处理
            
    
    博客分类: SpringMVC SpringMVC异常处理 
  • 大小: 12.2 KB
  • SpringMVC(十七)_异常处理
            
    
    博客分类: SpringMVC SpringMVC异常处理 
  • 大小: 4.4 KB