控制器发生异常 eofexception_Spring MVC的异常处理机制

6372702f45c7cad83413f27b6ec2d735.png

一、Spring MVC异常处理概述

Spring MVC 通过 HandlerExceptionResolver(接口)处理程序的异常,HandlerExceptionResolver接口的实现类:

9f74a18bcffa7af9be49c9cae9989fa6.png

对应于这几个实现类,Spring MVC提供了多种方式将异常转换为响应:

  • 默认的异常响应
  • 将异常映射为指定的HTTP状态码
  • 在控制器类中编写异常响应方法
  • 在控制器通知类中集中响应异常
  • 在配置文件中配置异常响应

一、默认的异常响应

对于一些异常:

271c9065924e75ad743875e3ef5ff702.png

Spring MVC默认会将这些异常交给DefaultHandlerExceptionResolver处理,映射为HTTP状态吗。

示例:

@RequestMapping(value="/testDefaultHandlerExceptionResolver", method=RequestMethod.POST)
public String testDefaultHandlerExceptionResolver() {
    System.out.println("testDefaultHandlerExceptionResolver");
    return "success";
}

使用GET方式访问这个映射,就会默认映射为HTTP状态码405:

19311fc9cc679762ec09bde4a22f584a.png

二、将异常映射为指定的HTTP状态码

对于上面所说的将异常映射为默认的HTTP状态码,Spring MVC也可以通过ResponseStatusExceptionResolver类将异常映射为我们指定的HTTP状态码。

首先需要编写一个自定义异常类,例如禁止某个参数的异常类:

@ResponseStatus(value=HttpStatus.FORBIDDEN, reason="This Argument is forbidden!")
public class ForbiddenArgumentException extends RuntimeException{
}

上述异常会被映射为value中指定的HttpStatus.FORBIDDEN状态,reason指定了异常信息。

在控制器类的方法中使用这个异常:

@RequestMapping(value="/testResponseStatusExceptionResolver")
public String testResponseStatusExceptionResolver(@RequestParam("i") int i){
    if(i == 0){
        throw new ForbiddenArgumentException();
    }
    System.out.println("testResponseStatusExceptionResolver...");
    return "success";
}

当使用参数i=0访问该URL时,会触发ForbiddenArgumentException异常,并被映射为HTTP状态码403:

a2c0887b23f3abe948cd904307f0e4ca.png

三、在控制器类中编写异常响应方法

有时候需要在控制器类的处理请求方法中编写try..catch异常处理代码,这通常会使增加该方法内的代码和逻辑。为了将处理请求方法中的异常处理代码剥离,我们可以在控制器类中编写异常响应方法,在该方法中处理异常。

比如下面这个处理请求方法如果接收的参数为0时,会触发java.lang.ArithmeticException异常:

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

可以在控制器类中编写异常响应方法处理异常:

@ExceptionHandler(value={java.lang.ArithmeticException.class})
public ModelAndView handleException(Exception ex){
    ModelAndView mv = new ModelAndView("error");
    mv.addObject("exception", ex);
    return mv; 
}

这里有几点需要注意:

  • 如果有多个异常响应方法,则按异常类型匹配程度,顺序执行。
  • 异常对象(上面的Exception ex)不能通过Map集合方式传递给视图,只能通过ModelAndView传递。

四、在控制器通知类中集中响应异常

如果多个控制器类中都会抛出某个特定的异常,那么就需要在所有的控制器方法中重复相同的@ExceptionHandler方法。我们可以编写控制器通知类集中响应异常。

比如可以编写一个控制器通知类响应上面的java.lang.ArithmeticException异常:

@ControllerAdvice
public class ExceptionAdviceHandler {
	@ExceptionHandler(value={java.lang.ArithmeticException.class})
	public ModelAndView handleException(Exception ex){
	    ModelAndView mv = new ModelAndView("error");
	    mv.addObject("exception", ex);				// 将异常对象传递给视图
	    return mv; 
	}
}

如果控制器类中有@ExceptionHandler方法,那么控制器方法触发异常时,本类中的@ExceptionHandler方法会响应,而控制器通知类中的@ExceptionHandler方法不会响应。所以总结起来就是控制器类中的@ExceptionHandler方法总是会屏蔽控制器通知类中的@ExceptionHandler方法。

五、在配置文件中配置异常响应

如果希望对所有异常进行统一处理,可以使用 SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常。这些上面的几种方式都能实现,但是这种方式是通过配置Spring的配置文件实现的。

这里就不介绍这种方法了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值