Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 480|回复: 0

Spring Boot应用中的异常处理

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-8-30 16:07:37 | 显示全部楼层 |阅读模式

    楼主前几天写了一篇“Java子线程中的异常处理(通用)”文章,介绍了在多线程环境下3种通用的异常处理方法。

    但是平时大家的工作一般是基于开发框架进行的(比如Spring MVC,或Spring Boot),所以会有相应特定的异常处理方法,这篇文章要介绍的就是web应用中的异常处理。 

    想快速解决问题的小伙伴可以只看“解决办法”,想进一步了解细节的小伙伴还可以看“深入剖析”部分。

    适用场景

    使用Spring MVC或Spring Boot框架搭建的web应用

    解决办法

    @ControllerAdvice注解 + @ExceptionHandler注解

    实现一个异常处理类,在类上应用@ControllerAdvice注解,并在异常处理方法上应用@ExceptionHandler注解。那么在web应用中,当Controller的@RequestMapping方法抛出指定的异常类型时,@ExceptionHandler修饰的异常处理方法就会执行。

    示例:

     1 @ControllerAdvice  2 public class WebServerExceptionHandler {
     3     Logger log = LoggerFactory.getLogger(this.getClass());
     4 
     5     public WebServerExceptionHandler() {
     6     }
     7 
     8     // 指定捕获的异常类型,这里是自定义的SomeException
     9     @ExceptionHandler({SomeException.class}) 10     public ResponseEntity<WebServerExceptionResponse> handle(HttpServletResponse response, SomeException ex) {
    11         WebServerExceptionResponse body = new WebServerExceptionResponse();
    12         body.setStatus(ex.getStatus());
    13         body.setMessage(ex.getMessage());
    14         this.log.info("handle SomeException, status:{}, message:{}",  new Object[]{body.getStatus(), body.getMessage()});
    15         return new ResponseEntity(body, HttpStatus.valueOf(ex.getStatus()));
    16     }
    17 
    18     // 指定捕获的异常类型,这里是自定义的OtherException
    19     @ExceptionHandler({OtherException.class}) 20     public ResponseEntity<WebServerExceptionResponse> handle(HttpServletResponse response, OtherException ex) {
    21         WebServerExceptionResponse body = new WebServerExceptionResponse();
    22         body.setStatus(ex.getStatus());
    23         body.setMessage(ex.getMessage());
    24         this.log.info("handle OtherException, status:{}, message:{}",  new Object[]{body.getStatus(), body.getMessage()});
    25         return new ResponseEntity(body, HttpStatus.valueOf(ex.getStatus()));
    26     }
    27 }

     深入剖析

    @ControllerAdvice的定义如下: 

     1 @Target(ElementType.TYPE)
     2 @Retention(RetentionPolicy.RUNTIME)
     3 @Documented
     4 @Component
     5 public @interface ControllerAdvice {
     6 
     7     String[] value() default {};
     8 
     9     String[] basePackages() default {};
    10 
    11     Class<?>[] basePackageClasses() default {};
    12 
    13     Class<?>[] assignableTypes() default {};
    14 
    15     Class<? extends Annotation>[] annotations() default {};
    16 
    17 }

    可以看出它应用在TYPE类型的元素上(也即class或interface),运行时生效。

    作用是Controller类的帮助注解,一般搭配@ExceptionHandler注解,用来处理Controller的@RequestMapping修饰的方法抛出的异常。

    楼主根据源码的注释整理了5个参数的含义,它们都是用来限定需要处理的Controller的:

    • value():等同于basePackages,表示需要被处理的Controller包名数组,例如 @ControllerAdvice("org.my.pkg")。如果不指定,就代表处理所有的Controller类
    • basePackages():表示需要被处理的Controller包名数组,例如 @ControllerAdvice(basePackages={"org.my.pkg","org.my.other.pkg"})
    • basePackageClasses():通过标记类来指定Controller包名数组
    • assignableTypes():通过类的Class对象来指定Controller包名数组
    • annotations():被注解修饰的Controller需要被处理

    性能考虑:不要指定过多的参数和异常处理策略,因为异常检查和处理都是在运行时做的。

     

    @ExceptionHandler的定义如下:

     1 @Target(ElementType.METHOD)
     2 @Retention(RetentionPolicy.RUNTIME)
     3 @Documented
     4 public @interface ExceptionHandler {
     5 
     6     /**
     7      * Exceptions handled by the annotated method. If empty, will default to any
     8      * exceptions listed in the method argument list.
     9      */
    10     Class<? extends Throwable>[] value() default {};
    11 
    12 }

    可以看出它作用在方法上面,而且参数很好理解,就是需要处理的异常类的Class对象数组。

    但是,它对修饰的异常处理方法的参数和返回值有限定,楼主根据源码的注释整理如下:

    (1)异常处理方法的参数限定,可以是以下类型,顺序任意:

    •  异常类对象
    • HttpServletRequest、HttpServletResponse
    • HttpSession
    • InputStream/Reader、OutputStream/Writer

    (2)异常处理方法的返回值限定,最终会写入response流:

    • ResponseEntity
    • HttpServletResponse
    • ModelAndView
    • Model
    • Map
    • View 

    总结

    以上就是在Spring web应用中的异常处理方法:使用@ControllerAdvice搭配@ExceptionHandler修饰自定义异常处理方法,处理来自Controller类中的@RequestMapping方法抛出的异常。

    使用时需要根据实际情况,合理设置@ControllerAdvice和@ExceptionHandler的参数。

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-22 23:23 , Processed in 0.060209 second(s), 28 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表