java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringMVC异常处理

SpringMVC异常处理的三种方式

作者:兔子队列

在SpringMVC中异常处理是一个重要的方面,它帮助我们有效地处理应用程序中的异常情况,提高用户体验和系统的稳定性,这篇文章主要给大家介绍了关于SpringMVC异常处理的三种方式,需要的朋友可以参考下

HandlerExceptionResolver接口

在SpringMVC中,提供了一个全局异常处理器,用于对系统中出现的异常进行统一处理

在一般的系统中,DAO层、Service层及Controller层出现异常都以“throws Exception”的形式向上层抛出,最后都会由SpringMVC的前端控制器(DispatcherServlet)统一交给全局异常处理器进行异常处理

在SpringMVC中提供的HandlerExceptionResolver接口可以实现全局异常处理器

Spring MVC接口HandlerExceptionResolver用于抽象一个异常解析器

这种异常解析器被用于分析请求处理器Handler映射或者执行过程中的异常,将这些异常转换成其他形式展示给用户

可以看到,HandlerExceptionResolver接口中定义了一个名为resolveException的方法,该方法主要用于处理Controller中的异常

参数“Exception ex”即为Controller或其下层抛出的异常

参数“Object handler”就是处理器适配器要执行的Handler对象

resolveException方法的返回值类型是ModelAndView,也就是说,可以通过这个返回值来设置发送异常时的显示页面

典型的做法是转换成一个错误视图,或者返回某个HTTP状态码给请求端

使用HandlerExceptionResolver实现全局异常处理器;当抛出异常后,要有相应的符合用户体验的友好界面显示异常

综合实例:

(1)创建自定义异常类,名称为OperationException

注意:

Spring管理的事务,无论是声明式事务还是注解式事务默认是在抛出运行异常(RuntimeException异常)时,才会被Spring框架捕获到然后回滚

该自定义异常类继承的是RuntimeException类,因为一般项目的Service层逻辑都会使用Spring提供的事务管理,当Service层需要抛出自定义异常时,如果该自定义异常继承的是Exception类,则Spring提供的事务管理将会失效,所以这里的自定义异常类继承的是RuntimeException类,这样才不会使Spring提供的事务管理失效

(2)创建全局异常处理器OperationExceptionResolver类,该类实现HandlerExceptionResolver接口,并且实现resolveException方法

(3)创建名称为error.jsp的页面,符合用户体验的友好界面,用于显示异常信息

Spring MVC 为HandlerExceptionResolver提供了四个实现类

(1)ExceptionHandlerExceptionResolver

找到使用@ExceptionHandler注解的ServletInvocableHandlerMethod并调用,基于其执行结果构建ModelAndView

(2)SimpleMappingExceptionResolver

映射异常类名到视图名称,处理时使用此映射关系构建ModelAndView,或者使用缺省视图

(3)ResponseStatusExceptionResolver

如果异常是ResponseStatusException或者使用了注解@ResponseStatus,则利用这些信息将异常翻译成HTTP状态字调用相应的sendError,返回空ModelAndView

注意:该异常解析器会递归检查异常的cause异常

(4)DefaultHandlerExceptionResolver

Spring MVC缺省异常处理器,解析时将标准MVC异常翻译成HTTP状态字调用相应对象的方法#sendError,返回一个空ModelAndView对象(注意:不是null)

使用注解实现异常分类管理(@ControllerAdvice 和 @ExceptionHandler)

引言:

在开发中,我们会有如下的场景:某个接口中,存在一些业务异常

例如用户输入的参数校验失败、用户名密码不存在等

当触发这些业务异常时,我们需要抛出这些自定义的业务异常,并对其进行处理

一般我们要把这些异常信息的状态码和异常描述,友好地返回给调用者,调用者则利用状态码等信息判断异常的具体情况

过去,我们可能需要在 controller 层通过 try/catch 处理

首先 catch 自定义异常,然后 catch 其它异常

对于不同的异常,我们需要在 catch 的同时封装将要返回的对象

然而,这么做的弊端就是代码会变得冗长

每个接口都需要做 try/catch 处理,而且一旦需要调整,所有的接口都需要修改一遍,非常不利于代码的维护,如下段代码所示:

那么,有没有什么方法可以简便地处理这些异常信息呢?

答案是肯定的

Spring 3.2 中,新增了 @ControllerAdvice 注解,可以用于定义 @ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有 @RequestMapping 中

简单来说就是,可以通过 @ControllerAdvice 注解配置一个全局异常处理类,来统一处理 controller 层中的异常,于此同时 controller 中可以不用再写 try/catch,这使得代码既整洁又便于维护

综合实例:定义自定义异常

(1)自定义业务异常类

(2)@ControllerAdvice + @ExceptionHandler 配置全局异常处理类

@ControllerAdvice

类型:类注解;定义该类为全局异常处理类

@ExceptionHandler

类型:方法注解;定义该方法为异常处理方法

value 的值为需要处理的异常类的 class 文件

这样,就可以对不同的异常进行统一处理了

通常,为了使 controller 中不再使用任何 try/catch,也可以在 GlobalExceptionHandler 中对 Exception 做统一处理

这样其他没有用 @ExceptionHandler 配置的异常就都会统一被处理

遇到异常时抛出异常即可

在业务中,遇到业务异常的地方,直接使用 throw 抛出对应的业务异常即可

例如:

注意:

优点:

缺点:

使用 @ControllerAdvice 对不同的 Controller 分别捕获异常并处理

引言

@ControllerAdvice 指定 Controller 范围

(1)basePackages

(2)basePackageClasses

(3)assignableTypes

(4)annotations

例子

(1)创建三个 Controller

其中,BusinessException 是自定义的异常类

(2)创建两个全局异常处理类

(3)分别调用接口,查看错误日志

(1)调用 localhost:8080/test1

返回:GlobalExceptionHandler1 服务错误

即 MyController1 异常被 GlobalExceptionHandler1 全局异常类捕获

(2)调用 localhost:8080/test2

返回:GlobalExceptionHandler2 服务错误

即 MyController2 异常被 GlobalExceptionHandler2 全局异常类捕获

(3)调用 localhost:8080/test3

返回:

即 MyController3 异常没有被全局异常捕获

总结 

到此这篇关于SpringMVC异常处理的三种方式的文章就介绍到这了,更多相关SpringMVC异常处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文