SpringMVC-异常处理

SpringMVC通过HandlerExceptionResolver接口来处理程序的异常,包括Handler映射、数据绑定和目标方法执行时发生的异常。


1. HandlerExceptionResolver

  HandlerExceptionResolver的具体实现类主要有:
  这里写图片描述
  其中,DispatcherServlet会默认装配HandlerExceptionResolver,在SpringMVC配置文件中没有使用mvc:annotation-driven配置时,其自动装配的HandlerExceptionResolver如下:
  这里写图片描述
  然而,在开发中通常会在SpringMVC配置文件中使用mvc:annotation-driven配置,其自动装配的HandlerExceptionResolver如下:
  这里写图片描述


2. ExceptionHandlerExceptionResolver

  如下Handler类和异常处理类针对算术异常的处理优先级为:TestExceptionHandler的handleArithmeticException()方法 > TestExceptionHandler的handleRuntimeException()方法 > SpringMVCExceptionHandler的handleArithmeticException()方法。

package com.qiaobc.springmvc.exception;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class TestExceptionHandler {

    @ExceptionHandler({RuntimeException.class})
    public ModelAndView handleRuntimeException(Exception exception) {
        System.out.println("局部异常处理之运行时异常 : " + exception);
        ModelAndView modelAndView = new ModelAndView("error");
        modelAndView.addObject("EXCEPTION", exception);
        return modelAndView;
    }

    /**
     * 关于SpringMVC的异常处理问题:
     *  1). @ExceptionHandler标记的方法为(局部)异常处理方法,在当前处理器的目标方法发生指定异常时被执行
     *  2). @ExceptionHandler标记的方法的入参中可以加入Exception类型的参数,其即为所发生的异常对象
     *  3). @ExceptionHandler标记的方法的入参中不能添加Map类型的参数,可使用ModelAndView将异常信息传到目标页面
     *  4). @ExceptionHandler标记的方法具有优先级的问题,先进行精确匹配,再进行模糊匹配
     *  5). 若当前Handler中没有@ExceptionHandler标记的方法,则发生异常时:
     *          查找@ControllerAdvice标记的类中的@ExceptionHandler方法(全局异常处理)
     */
    @ExceptionHandler({ArithmeticException.class})
    public ModelAndView handleArithmeticException(Exception exception) {
        System.out.println("局部异常处理之算术异常 : " + exception);
        ModelAndView modelAndView = new ModelAndView("error");
        modelAndView.addObject("EXCEPTION", exception);
        return modelAndView;
    }

    @RequestMapping("/testExceptionHandlerExceptionResolver")
    public String testExceptionHandlerExceptionResolver(@RequestParam("count") int count) {
        System.out.println("Result : " + 10 / count);
        return "success";
    }

}
package com.qiaobc.springmvc.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice
public class SpringMVCExceptionHandler {

    @ExceptionHandler({ArithmeticException.class})
    public ModelAndView handleArithmeticException(Exception exception) {
        System.out.println("全局异常处理之算术异常 : " + exception);
        ModelAndView modelAndView = new ModelAndView("error");
        modelAndView.addObject("EXCEPTION", exception);
        return modelAndView;
    }

}

3. ResponseStatusExceptionResolver

  该异常处理类可以对@ResponseStatus注解进行解析(将异常转化为HTTP状态码),并使用该注解的属性值(HTTP状态码)响应请求页面。

  ①. @ResponseStatus注解修饰异常类时

package com.qiaobc.springmvc.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value=HttpStatus.FORBIDDEN, reason="用户名和密码不匹配!")
public class UserNameNotMatchPassword extends RuntimeException {
    private static final long serialVersionUID = 1L;
}

  说明:若在处理器的目标方法中抛出该异常,且ExceptionHandlerExceptionResolver不解析时,由于触发的异常带有@ResponseStatus注解,ResponseStatusExceptionResolver会对该异常进行解析,并响应HttpStatus.FORBIDDEN代码给客户端。

@Controller
public class TestExceptionHandler {
    @RequestMapping("/testResponseStatusExceptionResolver")
    public String testResponseStatusExceptionResolver(@RequestParam("status") int status) {
        if(status == 99) {
            throw new UserNameNotMatchPassword();
        }
        System.out.println("testResponseStatusExceptionResolver...");
        return "success";
    }
}

  ②. @ResponseStatus注解修饰目标方法时
  由于该方法带有@ResponseStatus注解,故执行该目标方法且status不为99时,ResponseStatusExceptionResolver会对其进行解析,并直接响应HttpStatus.NOT_FOUND代码给客户端;若status为99则会响应HttpStatus.FORBIDDEN代码给客户端。

@Controller
public class TestExceptionHandler {
    @ResponseStatus(value=HttpStatus.NOT_FOUND, reason="测试")
    @RequestMapping("/testResponseStatusExceptionResolver")
    public String testResponseStatusExceptionResolver(@RequestParam("status") int status) {
        if(status == 99) {
            throw new UserNameNotMatchPassword();
        }
        System.out.println("testResponseStatusExceptionResolver...");
        return "success";
    }
}

4. DefaultHandlerExceptionResolver

  该异常处理类可以对Spring的特殊异常进行处理,并将其转化为对应的HTTP状态码,进而响应为客户端。

/**
 * DefaultHandlerExceptionResolver : 主要对Spring的特殊异常进行处理,具体参看源代码
 * 请求:<a href="testDefaultHandlerExceptionResolver">Test DefaultHandlerExceptionResolver</a>
 * @return
 */
@RequestMapping(value="/testDefaultHandlerExceptionResolver", method=RequestMethod.POST)
public String testDefaultHandlerExceptionResolver() {
    return "success";
}

5. SimpleMappingExceptionResolver

  如果希望对所有异常进行统一处理,可以使用该异常解析器将异常类名映射为视图名,即发生指定异常时所转向的页面。

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <!-- 配置将异常信息放入request请求域的EXCEPTION属性中,若不配置则默认放入exception属性中 -->
    <property name="exceptionAttribute" value="EXCEPTION"></property>
    <!-- 配置发生指定异常时转向的页面 -->
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>
        </props>
    </property>
</bean>
/**
 * 使用SimpleMappingExceptionResolver处理java.lang.ArrayIndexOutOfBoundsException
 */
@RequestMapping("/testSimpleMappingExceptionResolver")
public String testSimpleMappingExceptionResolver(@RequestParam("index") int index) {
    int[] arrays = new int[10];
    for(int i = 0; i < arrays.length; i++) {
        arrays[i] = 3 * i;
    }
    System.out.println(arrays[index]);
    return "success";
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值