Spring Boot應用中的異常處理


樓主前幾天寫了一篇“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的參數。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM