Spring MVC(五)——异常处理(统一异常处理)

Spring MVC中异常的处理是交给HandlerExceptionResolver实现类的异常处理链来完成的;
HandlerExceptionResolver的实现类,默认有如下:

实现类描述
SimpleMappingExceptionResolver异常类名和错误视图名之间的映射。用于在浏览器应用程序中呈现错误页。
DefaultHandlerExceptionResolver解决SpringMVC引发的异常并将其映射到HTTP状态代码
ResponseStatusExceptionResolver使用@responsestatus注释解析异常,并根据注释中的值将其映射到HTTP状态代码。
ExceptionHandlerExceptionResolver通过调用@controller或@controlleradvice类中的@exceptionhandler方法来解决异常。

可以配置多个HandlerExceptionResolver实现类bean,然后通过order属性来指定顺序,order的值越大,在异常链中,越靠后。


配置SimpleMappingExceptionResolver异常处理

以SimpleMappingExceptionResolver为例子,我要将系统中的业务发生的异常,转到特定的错误页面中去。
首先,在系统的webapp/views/error目录中,添加错误页(比如arrayIndexOutOfBoundsExceptionError.jsp和nullPointerExceptionError.jsp);
这个时候我想做的是,如果系统中发生了数组越界的异常,那么就进入arrayIndexOutOfBoundsExceptionError页面 ,如果发生了空指针异常,那么就进入nullPointerExceptionError页面。
具体做法如下:
配置异常处理器:

<!-- 异常处理器 -->
<bean id="simpleMappingExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
 <property name="exceptionMappings">
 	<props>
 		<prop key="java.lang.NullPointerException">/error/nullPointerExceptionError</prop>
 		<prop key="java.lang.ArrayIndexOutOfBoundsException">/error/arrayIndexOutOfBoundsExceptionError</prop>
 	</props>
 </property>
</bean>

现在,模拟一下系统发生异常:

@GetMapping("exception")
public String testException(String value) {
	if("NullPointerException".equals(value)) {
		throw new NullPointerException();
	}else if("ArrayIndexOutOfBoundsException".equals(value)) {
		throw new ArrayIndexOutOfBoundsException();
	}
	
	String viewName = "/test/testPage";
	return viewName;
}

当访问:http://fyk:8080/app/test/exception?requisiteParam=fyk&value=ArrayIndexOutOfBoundsException的时候,代码就会抛出数组越界的异常,此时就会进入arrayIndexOutOfBoundsExceptionError.jsp错误页。
当然,SimpleMappingExceptionResolver这个类是Spring提供的,我们也可以自己实现HandlerExceptionResolver接口,然后在跳转到错误页的时候,带上一些信息。


使用@ExceptionHandler注解异常

把上一步中xml里配置的异常处理配置删掉,然后在controller中,写如下代码:

@ExceptionHandler(Exception.class)
public ModelAndView handleIOException(Exception ex) {
	ModelAndView modelAndView = new ModelAndView();
    if(ex instanceof NullPointerException) {
    	modelAndView.setViewName("/error/nullPointerExceptionError");
    }else {
    	modelAndView.setViewName("/error/arrayIndexOutOfBoundsExceptionError");
    }
    return modelAndView;
}

需要说明的是,@ExceptionHandler注解,可以接受一个参数为异常类型的数组作为参数;另外,也可以不用给任何值,此时,方法中的参数,就是相当于他的值了。
另外,这个handleIOException方法,还可以接受HttpServletRequest参数,返回值也可以是String类型——这种情况下会被解析为视图名——可以是ModelAndView类型的对象,也可以是ResponseEntity。或者你还可以在方法上添加@ResponseBody注解以使用消息转换器会转换信息为特定类型的数据,然后把它们写回到响应流中。
初看,以上介绍的两种方式,都可以达到同样的效果,但是使用@ExceptionHandler方式,只有在该controller下有效,并没有达到全局配置的效果。当然,可以写在一个基础父类中,让所有的controller都继承这个父类。这样做,似乎有点侵略性。以下介绍一种终结方式。


@ControllerAdvice与@ExceptionHandler的组合使用

这个是在做微服务的时候遇到的一个实际场景:在前后端分离的情况下,整个系统返回的数据格式,都应该统一,所以我们对整个系统会抛出的异常进行了自定义,所以一般而言,系统抛出的异常都会是自定义异常。(唉,算了,在这个文章中先不说这个了,在写微服务的时候,再详细说。)
总之,现在要做的就是,实现一个Spring MVC的全局统一异常处理:

@ControllerAdvice
@Slf4j
public class BaseControllerConfig {

	@ResponseBody
	@ExceptionHandler({ Exception.class }) // 指定拦截异常的类型
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) // 返回的http状态码:500
	public FykResponseEntity<Object> customExceptionHandler(Exception e) {
		FykResponseEntity<Object> responseEntity = new FykResponseEntity<>();
		if (e instanceof CustomException) {
			CustomException customException = (CustomException) e;
			responseEntity.setErrCode(customException.getErrCode());
			responseEntity.setCustomMess(customException.getCustomMess());
		} else {
			log.error(e.getMessage(), e);
			responseEntity.setErrCode(ExceptionCode.UNDEFINED_ERR.getErrCode());
			responseEntity.setCustomMess("未定义异常");
		}
		return responseEntity;
	}
}

在使用的时候,把这个类注入到spring中就ok了。至于@ExceptionHandler和它修饰的方法,和上小节中叙述的是一样的。而@ResponseStatus的作用的,将http的响应状态设置为500。

源码地址:https://gitee.com/fyk_wq/spring-stuty

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring MVC提供了一个很好的机制来处理应用程序中的异常——统一异常处理。通过使用统一异常处理,您可以将应用程序中发生的所有异常都交给一个中央异常处理器来处理,从而简化了应用程序的错误处理流程,并提高了代码的可维护性。 实现统一异常处理的步骤如下: 1.创建一个异常处理类,该类必须实现`HandlerExceptionResolver`接口。 ```java public class ExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ModelAndView mav = new ModelAndView(); mav.addObject("exception", ex); mav.setViewName("error"); return mav; } } ``` 2.在Spring配置文件中配置异常处理器。 ```xml <bean class="com.example.ExceptionResolver"/> ``` 3.在控制器中抛出异常。 ```java @RequestMapping(value = "/test") public String test() throws Exception { throw new Exception("测试异常处理"); } ``` 4.创建一个错误页面,用于显示异常信息。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Error</title> </head> <body> <h1>Error</h1> <p>${exception.message}</p> </body> </html> ``` 当您运行应用程序并访问`/test`URL时,应用程序将抛出一个异常,并且异常处理器将捕获该异常并将其转发到错误页面,以便您可以查看异常的详细信息。 需要注意的是,统一异常处理只适用于在控制器中发生的异常。如果您的应用程序中的其他组件(如拦截器、过滤器等)抛出了异常,您需要手动处理这些异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值