日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring中Controller层、Filter层、Interceptor层全局统一异常处理

發布時間:2025/6/17 javascript 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring中Controller层、Filter层、Interceptor层全局统一异常处理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Controller層、Filter層、Interceptor層全局統一異常處理

SpringBoot為異常處理提供了很多優秀的方法,但是像我這種新手在處理異常時還是會覺得一頭包,終于我痛定思痛,總結了一下統一異常處理的辦法,讓異常處理變得上流。

本片文章較長,我先定義以下后面會用到的類

/*** @author ht113* * 錯誤dto,就是從后端返回到前端的錯誤信息,下面這個作為例子比較簡單*/ @Data public class ErrorInfo {String datetime;String msg;String url;HttpStatus httpStatus;public ErrorInfo(String datetime, String message, String url, HttpStatus httpStatus) {this.datetime = datetime;this.msg = message;this.url = url;this.httpStatus = httpStatus;} }

自定義抽象異常類

/*** @author ht113*** 基本抽象類,所以我自定義的異常類都繼承自此方法*/ public abstract class AbstractBaseException extends Exception{private ErrorInfo errorInfo;public AbstractBaseException(String msg){super(msg);}public AbstractBaseException(String msg, Throwable cause){super(msg, cause);}public void setErrorInfo(ErrorInfo errorInfo){this.errorInfo = errorInfo;}//這是唯一的抽象方法,也是子類必須實現的方法,以此達到使自定義異常對應到不同的http狀態@NonNullpublic abstract HttpStatus getHttpStatus();}

以下兩個是自定義的異常類,對應的http狀態分別為NOT_FOUND和INTERNAL_SERVER_ERROR,即404和500

public class MyExceptionA extends AbstractBaseException {public MyExceptionA(String msg) {super(msg);}public MyExceptionA(String msg, Throwable cause){super(msg, cause);}@Overridepublic HttpStatus getHttpStatus() {return HttpStatus.NOT_FOUND;} }public class MyExceptionB extends AbstractBaseException {public MyExceptionB(String msg) {super(msg);}public MyExceptionB(String msg, Throwable cause){super(msg, cause);}@Overridepublic HttpStatus getHttpStatus() {return HttpStatus.INTERNAL_SERVER_ERROR;} }

1.一般Controller層的統一異常處理

@ExceptionHandler

在Spring中,我們可以通過對Controller中的方法添加@ExceptionHandler注釋來實現對同一個Controller中路由方法拋出的異常進行處理,來達到我們想要的異常處理效果

/*** @author ht113*/ @RestController public class HelloController {@RequestMapping("/")public String hello() throws AbstractBaseException{throw new MyExceptionA("exception A test");}//需要捕獲的異常的類@ExceptionHandler(MyExceptionA.class)public String exceptionHandlerA(){return "exception A caught successfully";}}

處理效果:

是個好方法,但是有個致命缺點,就是處理方法不能在Controller間共享,如果我在另一個Controller中拋出自定義異常就要重新實現一次,太拉垮了。

/*** @author ht113*/ @RestController public class HelloController2 {@RequestMapping("/hello2")public String hello2() throws AbstractBaseException {throw new MyExceptionA("exception A test");}}

@ControllerAdvice

通過對Controller添加注釋@ControllerAdvice可以實現Controller層的全局異常處理,處理方法和@ExceptionHandler相同,但是可以在Controller中共享,實例如下:

/*** @author ht113*/ @ControllerAdvice public class MyHandler {@ExceptionHandler(AbstractBaseException.class)public ResponseEntity<ErrorInfo> handler(HttpServletRequest request, AbstractBaseException e){return ResponseEntity.status(e.getHttpStatus()).body(new ErrorInfo(new Date().toString(), e.getMessage(),request.getRequestURL().toString(), e.getHttpStatus()));}}

測試類

/*** @author ht113*/ @RestController public class HelloController {@RequestMapping("/1/testA")public void hello() throws AbstractBaseException{throw new MyExceptionA("exception A test from Controller1");}@RequestMapping("/1/testB")public void hello1() throws AbstractBaseException{throw new MyExceptionB("exception B test from Controller1");}}/*** @author ht113*/ @RestController public class HelloController2 {@RequestMapping("/2/testA")public void hello() throws AbstractBaseException {throw new MyExceptionA("exception A test from Controller2");}@RequestMapping("/2/testB")public void hello1() throws AbstractBaseException{throw new MyExceptionB("exception B test from Controller2");}}

測試結果





我們所有的自定義異常,只要繼承自AbstractBaseException都可以被hander()方法捕獲,進行統一異常處理,當然也可以根據異常的不同進行特定的處理,只需要在MyHandler類中添加新的處理方法即可

2.Filter層、Interceptor層異常統一處理

過濾器Filter和過濾器Interceptor攔截器的使用總是后端開發不可避免的一部分,有時候我們需要在過濾器或攔截器中進行邏輯處理,拋出異常,那么這里拋出的異常可以被@ControllerAdvice注釋的異常處理類捕獲嗎?答案是Filter不會,而Interceptor可以,Filter是基于Servlet框架編寫的,Interceptor是基于SpringMVC框架的,SpingMVC不會對Filter中的異常統一處理,所以這里被拋出的異常不能被捕獲,那我們如何讓不能被捕獲的異常被被捕獲呢?

答案有兩個:

  • 直接在doFilterInternal()中處理異常,直接return給客戶端
  • 通過HandlerExceptionResolver主動對異常進行捕獲(當然了前面的Controller層的全局處理也可以用這種方式)
  • 本例選擇方法2,便于實現真正的統一。

    Filter、Interception、Controller處理流程:

    用上面提到的testA進行測試,結果如下(如果Controller中拋出異常,那么postHandler不會調用):

    HandlerExceptionResolver類圖:

    如何使用HandlerExceptionResolver?

  • 如果自定義異常類,考慮加上 ResponseStatus 注解;
  • 對于沒有 ResponseStatus注解的異常,可以通過使用 ExceptionHandler + ControllerAdvice注解,或者通過配置SimpleMappingExceptionResolver,來為整個Web應用提供統一的異常處理。
  • 如果應用中有些異常處理方式,只針對特定的Controller使用,那么在這個Controller中使用 ExceptionHandler 注解。
  • 不要使用過多的異常處理方式,不然的話,維護起來會很苦惱,因為異常的處理分散在很多不同的地方。
  • Filter中捕獲異常

    /*** @author ht113*/ @Component public class MyFilter extends OncePerRequestFilter {@Autowired@Qualifier("handlerExceptionResolver")private HandlerExceptionResolver handlerExceptionResolver;@Overrideprotected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {System.out.println("==============i'm in filter===================");handlerExceptionResolver.resolveException(httpServletRequest, httpServletResponse,null,new MyExceptionA("exception A test in filter"));return;//捕獲異常后就直接推出了//filterChain.doFilter(httpServletRequest, httpServletResponse);//System.out.println("===============i'm out filter===================");} }

    用的是MyExceptionA,結果如下


    Interceptor中捕獲異常

    /*** @author ht113*/ public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("=============i'm in interceptor============");throw new MyExceptionA("exception A test in interceptor");//return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("=============i'm out interceptor============");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("=============i'm out interceptor============");} }

    由于ExceptionHandler可以直接捕獲Interceptor中的異常,所以在Interceptor中自定義異常和Controller中一樣使用就可以。

    由于ExceptionHandler可以直接捕獲Interceptor中的異常,所以在Interceptor中自定義異常和Controller中一樣使用就可以。

    OVER!

    總結

    以上是生活随笔為你收集整理的Spring中Controller层、Filter层、Interceptor层全局统一异常处理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。