摘要:挺多人咨詢的,異常處理用切面注解去實現去全局異常處理。全局異常處理類,代碼如下代碼解析如下抽象類是用來處理全局錯誤時進行擴展和實現注解標記的切面排序,值越小擁有越高的優先級,這里設置優先級偏高。
本文內容
為什么要全局異常處理?
WebFlux REST 全局異常處理實戰
小結
摘錄:只有不斷培養好習慣,同時不斷打破壞習慣,我們的行為舉止才能夠自始至終都是正確的。一、為什么要全局異常處理?
前后端分離開發,一般提供 REST API,正常返回會有響應體,異常情況下會有對應的錯誤碼響應。
挺多人咨詢的,Spring Boot MVC 異常處理用切面 @RestControllerAdvice 注解去實現去全局異常處理。那 WebFlux 如何處理異常?如何實現統一錯誤碼異常處理?
全局異常處理的好處:
異常錯誤碼等統一維護
避免一些重復代碼
二、WebFlux REST 全局異常處理實戰下面介紹如何統一攔截異常,進行響應處理。
2.1 工程信息運行環境:JDK 7 或 8,Maven 3.0+
技術棧:SpringBoot 2.1.3
代碼地址:https://github.com/JeffLi1993...
模塊工程名: 2-x-spring-boot-webflux-handling-errors
工程結構:
├── pom.xml └── src └── main ├── java │?? └── org │?? └── spring │?? └── springboot │?? ├── Application.java │?? ├── error │?? │?? ├── GlobalErrorAttributes.java │?? │?? ├── GlobalErrorWebExceptionHandler.java │?? │?? └── GlobalException.java │?? ├── handler │?? │?? └── CityHandler.java │?? └── router │?? └── CityRouter.java └── resources └── application.properties
application.properties 無須配置,默認即可
Application Spring Boot 應用啟動類,是可以用來啟動 Spring Boot 應用。其包含了 @SpringBootApplication 注解和 SpringApplication 類,并調用 SpringApplication 類的 run() 方法,就可以啟動該應用。
具體實現類的關系圖如下:
圖片上傳失敗,見原文 https://www.bysocket.com/archives/2272
2.2 CityRouter 路由器類城市路由器代碼如下:
@Configuration public class CityRouter { @Bean public RouterFunctionrouteCity(CityHandler cityHandler) { return RouterFunctions.route(RequestPredicates.GET("/hello").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), cityHandler::helloCity); } }
RouterFunctions 對請求路由處理類,即將請求路由到處理器,這將一個 GET 請求 /hello 路由到處理器 cityHandler 的 helloCity 方法上。跟 Spring MVC 模式下的 HandleMapping 類似。
RouterFunctions.route(RequestPredicate, HandlerFunction) 方法,對應的 參是請求參數和處理函數,如果請求匹配,就調 對應的處理器函數。
2.3 CityHandler 服務處理類城市服務器處理類,代碼如下:
@Component public class CityHandler { public MonohelloCity(ServerRequest request) { return ServerResponse.ok().body(sayHelloCity(request), String.class); } private Mono sayHelloCity(ServerRequest request) { Optional cityParamOptional = request.queryParam("city"); if (!cityParamOptional.isPresent()) { throw new GlobalException(HttpStatus.INTERNAL_SERVER_ERROR, "request param city is ERROR"); } return Mono.just("Hello," + cityParamOptional.get()); } }
Mono:實現發布者,并返回 0 或 1 個元素,即單對象。Mono 是響應流 Publisher 具有基礎 rx 操作符。可以成功發布元素或者錯誤。用 Mono 作為返回對象,是因為返回包含了一個 ServerResponse 對象,而不是多個元素。
ServerResponse 是對響應的封裝,可以設置響應狀態,響應頭,響應正文。比如 ok 代表的是 200 響應碼、MediaType 枚舉是代表這文本內容類型、返回的是 String 的對象。
ServerRequest 是對請求的封裝。從請求中拿出 city 的值,如果沒有的話則拋出對應的異常。GlobalException 是封裝的全局異常。
Mono.justOrEmpty():從一個 Optional 對象或 null 對象中創建 Mono。
2.4 GlobalError 處理類如圖:
圖片上傳失敗,見原文 https://www.bysocket.com/archives/2272
GlobalException 全局異常類,代碼如下:
public class GlobalException extends ResponseStatusException { public GlobalException(HttpStatus status, String message) { super(status, message); } public GlobalException(HttpStatus status, String message, Throwable e) { super(status, message, e); } }
GlobalErrorAttributes 全局異常屬性值類,代碼如下:
@Component public class GlobalErrorAttributes extends DefaultErrorAttributes { @Override public MapgetErrorAttributes(ServerRequest request, boolean includeStackTrace) { Map map = super.getErrorAttributes(request, includeStackTrace); if (getError(request) instanceof GlobalException) { GlobalException ex = (GlobalException) getError(request); map.put("exception", ex.getClass().getSimpleName()); map.put("message", ex.getMessage()); map.put("status", ex.getStatus().value()); map.put("error", ex.getStatus().getReasonPhrase()); return map; } map.put("exception", "SystemException"); map.put("message", "System Error , Check logs!"); map.put("status", "500"); map.put("error", " System Error "); return map; } }
重寫了父類 DefaultErrorAttributes 默認錯誤屬性類的 getErrorAttributes 獲取錯誤屬性方法,從服務請求封裝 ServerRequest 中獲取對應的異常。
然后判斷是否是 GlobalException,如果是 CityHandler 服務處理類拋出的 GlobalException,則返回對應的異常的信息。
GlobalErrorWebExceptionHandler 全局異常處理類,代碼如下:
@Component @Order(-2) public class GlobalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler { public GlobalErrorWebExceptionHandler(GlobalErrorAttributes g, ApplicationContext applicationContext, ServerCodecConfigurer serverCodecConfigurer) { super(g, new ResourceProperties(), applicationContext); super.setMessageWriters(serverCodecConfigurer.getWriters()); super.setMessageReaders(serverCodecConfigurer.getReaders()); } @Override protected RouterFunctiongetRoutingFunction(final ErrorAttributes errorAttributes) { return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse); } private Mono renderErrorResponse(final ServerRequest request) { final Map errorPropertiesMap = getErrorAttributes(request, false); return ServerResponse.status(HttpStatus.BAD_REQUEST) .contentType(MediaType.APPLICATION_JSON_UTF8) .body(BodyInserters.fromObject(errorPropertiesMap)); } }
代碼解析如下:
AbstractErrorWebExceptionHandler 抽象類是用來處理全局錯誤時進行擴展和實現
@Order 注解標記 AspectJ 的切面排序,值越小擁有越高的優先級,這里設置優先級偏高。
構造函數將 GlobalErrorAttributes 全局異常屬性值類設置到 AbstractErrorWebExceptionHandler 抽象類的局部變量中。
重寫 getRoutingFunction 方法,設置對應的 RequestPredicates 和 Mono
將 GlobalErrorAttributes 的全局異常屬性值 map,設置到新的 ServerResponse 即可。
到此基本結束。Spring Boot MVC 錯誤碼如何實戰,參考地址:https://www.bysocket.com/arch...
2.5 運行驗證在 IDEA 中執行 Application 類啟動,任意正常模式或者 Debug 模式。然后打開瀏覽器訪問:
http://localhost:8080/hello
異常界面如下:
圖片上傳失敗,見原文 https://www.bysocket.com/archives/2272
可見,這是在 CityHandler 城市服務處理類邏輯中拋出的全局異常信息。那么正常情況會是如何?
改下 URL ,訪問如下:
http://localhost:8080/hello?city=WenLing
正常界面如下:
圖片上傳失敗,見原文 https://www.bysocket.com/archives/2272
三、小結在 Spring 框架中沒有代表錯誤響應的類,只是返回響應對象,一個 Map。如果需要定義業務的錯誤碼返回體,參考錯誤碼如何實戰,參考地址:https://www.bysocket.com/arch...。
本文重點還是有別于 Spring Boot 傳統 MVC 模式統一異常處理,實戰了 WebFlux 全局異常處理機制。實戰中這塊擴展需要考慮:
異常分層,從基類中擴展出來
錯誤碼設計分層,易擴展,比如在錯誤碼中新增調用量字段...
代碼示例本文示例讀者可以通過查看下面倉庫的中的模塊工程名: 2-x-spring-boot-webflux-handling-errors:
Github:https://github.com/JeffLi1993/springboot-learning-example
Gitee:https://gitee.com/jeff1993/springboot-learning-example
如果您對這些感興趣,歡迎 star、follow、收藏、轉發給予支持!
參考資料WebFlux REST API 全局異常處理:https://www.bysocket.com/arch...
https://dzone.com/articles/ex...
以下專題教程也許您會有興趣《Spring Boot 2.x 系列教程》 https://www.bysocket.com/spri...
《Java 核心系列教程》 https://www.bysocket.com/arch...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74138.html
摘要:響應式編程是基于異步和事件驅動的非阻塞程序,只是垂直通過在內啟動少量線程擴展,而不是水平通過集群擴展。三特性常用的生產的特性如下響應式編程模型適用性內嵌容器組件還有對日志消息測試及擴展等支持。 摘要: 原創出處 https://www.bysocket.com 「公眾號:泥瓦匠BYSocket 」歡迎關注和轉載,保留摘要,謝謝! 02:WebFlux 快速入門實踐 文章工程: JDK...
摘要:使用則需要及以上版本。開發使用框架七系列教程目錄系列教程大綱快速入門實踐實踐整合整合中和實踐整合中實現緩存中實現通信集成測試及部署實戰圖書管理系統 WebFlux 系列教程大綱 一、背景 大家都知道,Spring Framework 是 Java/Spring 應用程序跨平臺開發框架,也是 Java EE(Java Enterprise Edition) 輕量級框架,其 Spring ...
摘要:來源是最流行的用于開發微服務的框架。以下依次列出了最佳實踐,排名不分先后。這非常有助于避免可怕的地獄。推薦使用構造函數注入這一條實踐來自的項目負責人。保持業務邏輯免受代碼侵入的一種方法是使用構造函數注入。 showImg(https://mmbiz.qpic.cn/mmbiz_jpg/R3InYSAIZkHQ40ly9Oztiart2lESCyjCH0JwFRp3oErlYobhibM...
摘要:下一代服務端開發下一代服務端開發第部門快速開始第章快速開始環境準備,,快速上手實現一個第章企業級服務開發從到語言的缺點發展歷程的缺點為什么是產生的背景解決了哪些問題為什么是的發展歷程容器的配置地獄是什么從到下一代企業級服務開發在移動開發領域 《 Kotlin + Spring Boot : 下一代 Java 服務端開發 》 Kotlin + Spring Boot : 下一代 Java...
摘要:上一章我們提到過與,對于具體的介紹沒說到,這一章我在這里簡單介紹一下,既然提到和,那肯定得提到什么是響應式編程,什么是。 showImg(https://segmentfault.com/img/remote/1460000018819338?w=1024&h=500); 上一章我們提到過Mono 與 Flux,對于具體的介紹沒說到,這一章我在這里簡單介紹一下,既然提到Mono和Flu...
閱讀 1876·2021-09-28 09:36
閱讀 2426·2021-09-08 09:35
閱讀 3067·2019-08-30 15:53
閱讀 1554·2019-08-30 14:08
閱讀 665·2019-08-29 18:40
閱讀 2843·2019-08-29 13:57
閱讀 2702·2019-08-29 13:55
閱讀 681·2019-08-26 13:45