最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Cloud Gateway全局異常處理的方法詳解

 更新時間:2018年10月11日 11:21:26   作者:猿天地  
這篇文章主要給大家介紹了關(guān)于Spring Cloud Gateway全局異常處理的相關(guān)資料,需要的朋友可以參考下

前言

Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技術(shù)開發(fā)的網(wǎng)關(guān),Spring Cloud Gateway旨在為微服務(wù)架構(gòu)提供一種簡單而有效的統(tǒng)一的API路由管理方式。Spring Cloud Gateway作為Spring Cloud生態(tài)系中的網(wǎng)關(guān),目標(biāo)是替代Netflix ZUUL,其不僅提供統(tǒng)一的路由方式,并且基于Filter鏈的方式提供了網(wǎng)關(guān)基本的功能,例如:安全,監(jiān)控/埋點(diǎn),和限流等。

Spring Cloud Gateway 的特征:

  • 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0動態(tài)路由
  • Predicates 和 Filters 作用于特定路由
  • 集成 Hystrix 斷路器
  • 集成 Spring Cloud DiscoveryClient
  • 易于編寫的 Predicates 和 Filters
  • 限流
  • 路徑重寫

Spring Cloud Gateway中的全局異常處理不能直接用@ControllerAdvice來處理,通過跟蹤異常信息的拋出,找到對應(yīng)的源碼,自定義一些處理邏輯來符合業(yè)務(wù)的需求。

網(wǎng)關(guān)都是給接口做代理轉(zhuǎn)發(fā)的,后端對應(yīng)的都是REST API,返回?cái)?shù)據(jù)格式都是JSON。如果不做處理,當(dāng)發(fā)生異常時,Gateway默認(rèn)給出的錯誤信息是頁面,不方便前端進(jìn)行異常處理。

需要對異常信息進(jìn)行處理,返回JSON格式的數(shù)據(jù)給客戶端。下面先看實(shí)現(xiàn)的代碼,后面再跟大家講下需要注意的地方。
自定義異常處理邏輯:

package com.cxytiandi.gateway.exception;

import java.util.HashMap;
import java.util.Map;

import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;

/**
 * 自定義異常處理
 * 
 * <p>異常時用JSON代替HTML異常信息<p>
 * 
 * @author yinjihuan
 *
 */
public class JsonExceptionHandler extends DefaultErrorWebExceptionHandler {

 public JsonExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
 ErrorProperties errorProperties, ApplicationContext applicationContext) {
 super(errorAttributes, resourceProperties, errorProperties, applicationContext);
 }

 /**
 * 獲取異常屬性
 */
 @Override
 protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
 int code = 500;
 Throwable error = super.getError(request);
 if (error instanceof org.springframework.cloud.gateway.support.NotFoundException) {
 code = 404;
 }
 return response(code, this.buildMessage(request, error));
 }

 /**
 * 指定響應(yīng)處理方法為JSON處理的方法
 * @param errorAttributes
 */
 @Override
 protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
 return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
 }

 /**
 * 根據(jù)code獲取對應(yīng)的HttpStatus
 * @param errorAttributes
 */
 @Override
 protected HttpStatus getHttpStatus(Map<String, Object> errorAttributes) {
 int statusCode = (int) errorAttributes.get("code");
 return HttpStatus.valueOf(statusCode);
 }

 /**
 * 構(gòu)建異常信息
 * @param request
 * @param ex
 * @return
 */
 private String buildMessage(ServerRequest request, Throwable ex) {
 StringBuilder message = new StringBuilder("Failed to handle request [");
 message.append(request.methodName());
 message.append(" ");
 message.append(request.uri());
 message.append("]");
 if (ex != null) {
 message.append(": ");
 message.append(ex.getMessage());
 }
 return message.toString();
 }

 /**
 * 構(gòu)建返回的JSON數(shù)據(jù)格式
 * @param status 狀態(tài)碼
 * @param errorMessage 異常信息
 * @return
 */
 public static Map<String, Object> response(int status, String errorMessage) {
 Map<String, Object> map = new HashMap<>();
 map.put("code", status);
 map.put("message", errorMessage);
 map.put("data", null);
 return map;
 }

}

覆蓋默認(rèn)的配置:

package com.cxytiandi.gateway.exception;

import java.util.Collections;
import java.util.List;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;

/**
 * 覆蓋默認(rèn)的異常處理
 * 
 * @author yinjihuan
 *
 */
@Configuration
@EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
public class ErrorHandlerConfiguration {

 private final ServerProperties serverProperties;

 private final ApplicationContext applicationContext;

 private final ResourceProperties resourceProperties;

 private final List<ViewResolver> viewResolvers;

 private final ServerCodecConfigurer serverCodecConfigurer;

 public ErrorHandlerConfiguration(ServerProperties serverProperties,
          ResourceProperties resourceProperties,
          ObjectProvider<List<ViewResolver>> viewResolversProvider,
          ServerCodecConfigurer serverCodecConfigurer,
          ApplicationContext applicationContext) {
  this.serverProperties = serverProperties;
  this.applicationContext = applicationContext;
  this.resourceProperties = resourceProperties;
  this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
  this.serverCodecConfigurer = serverCodecConfigurer;
 }

 @Bean
 @Order(Ordered.HIGHEST_PRECEDENCE)
 public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
  JsonExceptionHandler exceptionHandler = new JsonExceptionHandler(
    errorAttributes, 
    this.resourceProperties,
    this.serverProperties.getError(), 
    this.applicationContext);
  exceptionHandler.setViewResolvers(this.viewResolvers);
  exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
  exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
  return exceptionHandler;
 } 
}

注意點(diǎn)

異常時如何返回JSON而不是HTML?

在org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler中的getRoutingFunction()方法就是控制返回格式的,原代碼如下:

@Override
protected RouterFunction<ServerResponse> getRoutingFunction(
 ErrorAttributes errorAttributes) {
  return RouterFunctions.route(acceptsTextHtml(), this::renderErrorView)
 .andRoute(RequestPredicates.all(), this::renderErrorResponse);
}

這邊優(yōu)先是用HTML來顯示的,想用JSON的改下就可以了,如下:

protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
 return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
}

getHttpStatus需要重寫

原始的方法是通過status來獲取對應(yīng)的HttpStatus的,代碼如下:

protected HttpStatus getHttpStatus(Map<String, Object> errorAttributes) {
 int statusCode = (int) errorAttributes.get("status");
 return HttpStatus.valueOf(statusCode);
}

如果我們定義的格式中沒有status字段的話,這么就會報(bào)錯,找不到對應(yīng)的響應(yīng)碼,要么返回?cái)?shù)據(jù)格式中增加status子段,要么重寫,我這邊返回的是code,所以要重寫,代碼如下:

@Override
protected HttpStatus getHttpStatus(Map<String, Object> errorAttributes) {
 int statusCode = (int) errorAttributes.get("code");
 return HttpStatus.valueOf(statusCode);
}

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • java 數(shù)據(jù)結(jié)構(gòu)與算法 (快速排序法)

    java 數(shù)據(jù)結(jié)構(gòu)與算法 (快速排序法)

    這篇文章主要介紹了java 數(shù)據(jù)結(jié)構(gòu)與算法(快速排序法),,快速排序法是實(shí)踐中的一種快速的排序算法,在c++或?qū)ava基本類型的排序中特別有用,下面我們一起進(jìn)入文章學(xué)習(xí)更詳細(xì)的內(nèi)容吧,需要的朋友可以參考下
    2022-02-02
  • SpringBoot整合Redis管道的示例代碼

    SpringBoot整合Redis管道的示例代碼

    本文將結(jié)合實(shí)例代碼,介紹SpringBoot整合Redis管道,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • java利用oss實(shí)現(xiàn)下載功能

    java利用oss實(shí)現(xiàn)下載功能

    這篇文章主要為大家詳細(xì)介紹了java利用oss實(shí)現(xiàn)下載功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • java實(shí)現(xiàn)客戶信息管理系統(tǒng)

    java實(shí)現(xiàn)客戶信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)客戶信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-02-02
  • springboot 配置DRUID數(shù)據(jù)源的方法實(shí)例分析

    springboot 配置DRUID數(shù)據(jù)源的方法實(shí)例分析

    這篇文章主要介紹了springboot 配置DRUID數(shù)據(jù)源的方法,結(jié)合實(shí)例形式分析了springboot 配置阿里DRUID數(shù)據(jù)源的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2019-12-12
  • Spring中常見的7種BeanDefinition詳解

    Spring中常見的7種BeanDefinition詳解

    在?Spring?容器中,我們廣泛使用的是一個一個的?Bean,BeanDefinition?從名字上就可以看出是關(guān)于?Bean?的定義,下面就跟隨小編一起深入了解一下常見的7中BeanDefinition吧
    2023-09-09
  • java代碼之謎運(yùn)算符篇

    java代碼之謎運(yùn)算符篇

    從最簡單的運(yùn)算符加號(+)說起,加號(+)是個二元運(yùn)算符——也就是說,加號只把兩個數(shù)聯(lián)接起來,從來不把第三個或者更多的聯(lián)接起來
    2012-11-11
  • Java+opencv3.2.0之scharr濾波器

    Java+opencv3.2.0之scharr濾波器

    這篇文章主要為大家詳細(xì)介紹了Java+opencv3.2.0之scharr濾波器的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • Java全面細(xì)致講解final的使用

    Java全面細(xì)致講解final的使用

    關(guān)于final關(guān)鍵字,它也是我們一個經(jīng)常用的關(guān)鍵字,可以修飾在類上、或者修飾在變量、方法上,以此看來定義它的一些不可變性!像我們經(jīng)常使用的String類中,它便是final來修飾的類,并且它的字符數(shù)組也是被final所修飾的。但是一些final的一些細(xì)節(jié)你真的了解過嗎
    2022-05-05
  • springboot項(xiàng)目中jackson-序列化-處理 NULL教程

    springboot項(xiàng)目中jackson-序列化-處理 NULL教程

    這篇文章主要介紹了springboot項(xiàng)目中jackson-序列化-處理 NULL教程,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10

最新評論

沙雅县| 南皮县| 阳泉市| 五原县| 马鞍山市| 株洲市| 肥西县| 台南县| 镇坪县| 泸溪县| 辽阳市| 鄂托克前旗| 山西省| 西乡县| 富顺县| 车致| 门源| 海兴县| 金湖县| 邵阳县| 故城县| 开阳县| 启东市| 洪泽县| 彭水| 信阳市| 雷山县| 苍溪县| 繁昌县| 甘肃省| 温州市| 甘泉县| 宝清县| 交城县| 渑池县| 兴宁市| 湘乡市| 长丰县| 昌都县| 瑞丽市| 墨竹工卡县|