基于SpringCloudGateway實(shí)現(xiàn)微服務(wù)網(wǎng)關(guān)的方式
(一)什么是微服務(wù)網(wǎng)關(guān)
后端寫完所有的微服務(wù)之后,最終是要交給前端去調(diào)用。我們都知道每個(gè)微服務(wù)都有各自的端口號,如果前端直接通過IP加端口的方式去調(diào)用微服務(wù)會很麻煩。如果想對請求增加限制也會變得十分困難。這個(gè)時(shí)候微服務(wù)網(wǎng)關(guān)就出現(xiàn)了。
微服務(wù)網(wǎng)關(guān)又成為API網(wǎng)關(guān),它是系統(tǒng)對外的唯一入口。APl網(wǎng)關(guān)封裝了系統(tǒng)內(nèi)部架構(gòu),為每個(gè)客戶端提供一個(gè)定制的APl。API網(wǎng)關(guān)方式的核心要點(diǎn)是,所有的客戶端和消費(fèi)端都通過統(tǒng)一的網(wǎng)關(guān)接入微服務(wù),在網(wǎng)關(guān)層處理所有的非業(yè)務(wù)功能。通常,網(wǎng)關(guān)也是提供REST/HTTP的訪問API。服務(wù)端通過API-GW注冊和管理服務(wù)。
聽起來有些抽象,下面就做一張圖給大家展示一下:前端的請求統(tǒng)一由微服務(wù)網(wǎng)關(guān)進(jìn)行管理,微服務(wù)網(wǎng)關(guān)可以調(diào)用各個(gè)微服務(wù),同時(shí)自身還有多種功能。
API網(wǎng)關(guān)的職責(zé)有身份驗(yàn)證、監(jiān)控、負(fù)載均衡、緩存、請求分片與管理、靜態(tài)響應(yīng)處理,最重要的功能是和外界聯(lián)系。
常見的API網(wǎng)關(guān)實(shí)現(xiàn)方式有Zuul,traefix,Spring Cloud Gateway等等。目前主流的微服務(wù)網(wǎng)關(guān)是Spring Cloud Gateway。
(二)Spring Cloud Gateway網(wǎng)關(guān)
Spring Cloud Gateway是Spring 官方基于Spring 5.0,Spring Boot 2.0和Project Reactor 等技術(shù)開發(fā)的網(wǎng)關(guān),旨在為微服務(wù)架構(gòu)提供一種簡單而有效的統(tǒng)一的API路由管理方式,統(tǒng)一訪問接口。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),和限流等。
2.1 核心概念:
路由(route):路由是網(wǎng)關(guān)最基礎(chǔ)的部分,路由信息由一個(gè)ID,一個(gè)目的URL,一組斷言工廠和一組Filter組成。
斷言(predicates):java8中的斷言函數(shù),Spring Cloud Gateway中的斷言函數(shù)允許開發(fā)者去定義匹配來自Http Request中的任何信息。當(dāng)斷言為真時(shí),則匹配路由。
過濾器(filter):對請求和響應(yīng)進(jìn)行過濾
下面通過實(shí)踐來操作微服務(wù)網(wǎng)關(guān),本項(xiàng)目有依賴于Nacos與Sentinel,如果不需要這部分的內(nèi)容可以在配置文件中去除。
2.2 搭建環(huán)境:
1、引入工程導(dǎo)入依賴
創(chuàng)建api_gateway_server工程,在工程中的pom.xml中導(dǎo)入依賴,項(xiàng)目全局依賴如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javayz</groupId> <artifactId>nacos-discovery-spring-cloud-gateway</artifactId> <version>0.0.1-SNAPSHOT</version> <name>nacos-discovery-spring-cloud-gateway</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <projec.build.sourceEncoding>UTF-8</projec.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.3.0.RELEASE</spring-boot.version> <spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <!--springcloudgateway--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId> <version>1.7.2</version> </dependency> </dependencies> <!--當(dāng)前項(xiàng)目繼承的依賴--> <dependencyManagement> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2、配置啟動類
創(chuàng)建GatewayApplication類
@EnableDiscoveryClient @SpringBootApplication public class NacosDiscoverySpringCloudGatewayApplication { public static void main(String[] args) { SpringApplication.run(NacosDiscoverySpringCloudGatewayApplication.class, args); } }
3、編寫配置文件
這里對配置文件的編寫使用.yml格式的配置文件,在resource文件夾下創(chuàng)建applicaiion.yml。這里需要注意的是gateway下routes的配置,首先用id自定義網(wǎng)關(guān);接著定義uri,意思是當(dāng)訪問的是9090端口(即訪問的是網(wǎng)關(guān)時(shí)),就自動把ip和端口號變成該uri;最后寫斷言predicates,這里的Path=/index/**
指得是自動匹配 /index/**
的路徑。當(dāng)請求地址為http://localhost:9090/index/1
時(shí),微服務(wù)網(wǎng)關(guān)會去訪問http://nacos-discovery-consumer/index/1
,這就是微服務(wù)網(wǎng)關(guān)調(diào)用微服務(wù)的功能。
server: port: 9090 spring: application: name: nacos-discovery-spring-cloud-gateway cloud: gateway: discovery: locator: enabled: true #啟用discoveryClient網(wǎng)關(guān)集成,實(shí)現(xiàn)服務(wù)發(fā)現(xiàn) routes: - id: route1 uri: lb://nacos-discovery-consumer #lb://表示負(fù)載均衡 predicates: #判斷條件 - Path=/test,/index/**
(三) 路由配置詳解
路由斷言中有許多匹配規(guī)則,之前只介紹了Path,其實(shí)還有許多匹配規(guī)則
predicates: #匹配一個(gè)時(shí)間,在這個(gè)時(shí)間之后發(fā)生的請求才能訪問(格式是ZonedDateTime) - After=2021-03-14T11:31:08.377+08:00[Asia/Shanghai] #匹配一個(gè)時(shí)間,在這個(gè)時(shí)間之前發(fā)生的請求才能訪問(ZonedDateTime) - Before=2021-03-14T11:31:08.377+08:00[Asia/Shanghai] #匹配兩個(gè)時(shí)間,在這個(gè)時(shí)間之間才能訪問 - Between=2021-03-14T11:31:08.377+08:00[Asia/Shanghai],2021-03-14T12:31:08.377+08:00[Asia/Shanghai] #路由斷言之間 #路由斷言Cookie匹配,匹配給定名稱(如master)或者正則表達(dá)式,如下面配置,請求的cookie中必須有token=master才能訪問 - Cookie=token,master #根據(jù)請求頭信息匹配,使用方式和cookie類似 - Header=XXX,XXX #根據(jù)host地址匹配 - Host=**.somehost.org #根據(jù)請求方法匹配 - Method=GET #根據(jù)請求路徑進(jìn)行匹配 - Path=*** #根據(jù)參數(shù)匹配,如果配置為token,則所有的請求必須要帶上token=XXX - Query=token #根據(jù)遠(yuǎn)程IP匹配 - RemoteAddr=192.168.1.1/24 #權(quán)重,第一個(gè)參數(shù)是組名,第二個(gè)參數(shù)是權(quán)重,兩個(gè)route下配置不同權(quán)重,會根據(jù)權(quán)重負(fù)載訪問 - Weight=group1,8
定義請求路徑時(shí),我們還可以據(jù)微服務(wù)名稱拉取請求路徑,下面是兩種不同方法定義uri,實(shí)現(xiàn)同樣的功能。
uri: http://127.0.0.1:9001 #當(dāng)訪問9090端口時(shí),自動把ip和端口替換為此uri uri: lb://userservice #根據(jù)微服務(wù)名稱拉取請求路徑
總體的配置:
server: port: 9090 spring: application: name: nacos-discovery-spring-cloud-gateway cloud: gateway: discovery: locator: enabled: true #啟用discoveryClient網(wǎng)關(guān)集成,實(shí)現(xiàn)服務(wù)發(fā)現(xiàn) routes: - id: route1 uri: lb://nacos-discovery-consumer #lb://表示負(fù)載均衡 predicates: #判斷條件 - Path=/test,/index/**,/** nacos: discovery: server-addr: 192.168.78.128:8848 username: nacos password: nacos sentinel: eager: true transport: dashboard: localhost:8080
3.1 自定義斷言配置
自定義斷言的實(shí)現(xiàn)分為兩步,假設(shè)我們現(xiàn)在要實(shí)現(xiàn)一個(gè)自定義的過濾器,規(guī)則是必須攜帶一個(gè)token,并且token要等于指定的值。
1、定義配置類:這里包含在配置文件要傳入的對象值
@Data public class TokenConfig { private String token; }
2、定義路由斷言工廠:首先是命名必須是XXXRoutePredicateFactory,繼承 AbstractRoutePredicateFactory
@Slf4j @Component public class TokenRoutePredicateFactory extends AbstractRoutePredicateFactory<TokenConfig> { public TokenRoutePredicateFactory(){ super(TokenConfig.class); } //用來把配置中的值變成一個(gè)集合 @Override public List<String> shortcutFieldOrder() { return Collections.singletonList("token"); } //通過jdk1.8的斷言接口來返回true或者false,如果是true表示過濾器不攔截 @Override public Predicate<ServerWebExchange> apply(TokenConfig config) { return exchange ->{ //獲取request請求參數(shù) MultiValueMap<String,String> valueMap=exchange.getRequest().getQueryParams(); boolean flag=false; List<String> list=new ArrayList<>(); //將request請求的value保存到集合里 valueMap.forEach((k,v)->{ list.addAll(v); }); //判斷有沒有和配置文件中相同的值 for (String s:list){ log.info("Token"+s); if (StringUtils.equalsIgnoreCase(s,config.getToken())){ flag=true; break; } } return flag; }; } }
最后在斷言處寫上我們自定義的內(nèi)容:
predicates: #判斷條件 - Path=/test,/index/**,/** - Token=javayz
只有鏈接是http://localhost:9090/sentinel/test1?token=javayz
帶上token=javayz
的請求才能訪問。
3.2 斷言不匹配404頁面自定義
SpringCloudGateway默認(rèn)給出的404頁面是
這樣的頁面實(shí)在不友好,我們可以通過自定義的方式讓他返回一個(gè)JSON字符串
public class MyErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler { public MyErrorWebExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) { super(errorAttributes, resourceProperties, errorProperties, applicationContext); } /** * 指定響應(yīng)處理方法為JSON處理 * @param errorAttributes * @return */ @Override protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) { return RouterFunctions.route(RequestPredicates.all(),this::renderErrorResponse); } /** * 根據(jù)code獲取對應(yīng)的HttpStatus * @param errorAttributes * @return */ @Override protected int getHttpStatus(Map<String, Object> errorAttributes) { return (int) errorAttributes.get("status"); } /** * 構(gòu)建異常信息 * @param request * @param ex * @return */ private String buildMessage(ServerRequest request,Throwable ex){ StringBuilder builder = new StringBuilder("Failed to handle request:"); builder.append(request.methodName()); builder.append(" "); builder.append(request.uri()); if (ex!=null){ builder.append(ex.getMessage()); } return builder.toString(); } /** * 返回的json數(shù)據(jù) * @param status * @param errorMsg * @param data * @return */ public static Map<String,Object> response(int status,String errorMsg,Object data){ Map<String,Object> map=new HashMap<>(); map.put("code",status); map.put("message",errorMsg); map.put("data",data); return map; } }
新建一個(gè)類叫做MyErrorWebExceptionHandler:
再編寫一個(gè)配置類,將自定義的異常頁面代碼注入到Bean容器中:
@Configuration public class GatewayConfiguration { private final ServerProperties serverProperties; private final ApplicationContext applicationContext; private final ResourceProperties resourceProperties; private final List<ViewResolver> viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; public GatewayConfiguration(ServerProperties serverProperties, ApplicationContext applicationContext, ResourceProperties resourceProperties, ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) { this.serverProperties = serverProperties; this.applicationContext = applicationContext; this.resourceProperties = resourceProperties; this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); this.serverCodecConfigurer = serverCodecConfigurer; } @Bean("myErrorWebExceptionHandler") @Order(Ordered.HIGHEST_PRECEDENCE) public ErrorWebExceptionHandler myErrorWebExceptionHandler(ErrorAttributes errorAttributes){ MyErrorWebExceptionHandler exceptionHandler=new MyErrorWebExceptionHandler( errorAttributes, this.resourceProperties, this.serverProperties.getError(), this.applicationContext ); exceptionHandler.setViewResolvers(this.viewResolvers); exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters()); exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders()); return exceptionHandler; } }
最后訪問到404就會以JSON的格式返回,方便調(diào)用方做處理。
(四)Spring Cloud Gateway過濾器
Spring Cloud Gateway除了具有請求路由功能之外,也支持對請求的過濾。
生命周期:
過濾器有兩種生命周期,PRE和POST:
PRE:這種過濾器在請求被路由之前調(diào)用。我們可利用這種過濾器實(shí)現(xiàn)身份驗(yàn)證、在集群中選擇請求的微服務(wù)、記錄調(diào)試信息等。
POST:這種過濾器在路由到微服務(wù)以后執(zhí)行。這種過濾器可用來為響應(yīng)添加標(biāo)準(zhǔn)的HTTP Header、收集統(tǒng)計(jì)信息和指標(biāo)、將響應(yīng)從微服務(wù)發(fā)送給客戶端等。
過濾器類型:
GatewayFilter:應(yīng)用到單個(gè)路由或者一個(gè)分組的路由上
GlobalFilter:應(yīng)用到所有的路由上
局部過濾器可以使用Spring Cloud Gateway內(nèi)置的方法,在官網(wǎng)中(docs.spring.io/spring-clou…
官方過濾器:
這里簡單介紹幾個(gè):
spring: cloud: gateway: routes: - id: add_request_header_route uri: https://example.org filters: - AddRequestHeader=X-Request-red, blue
添加AddRequestHeader過濾器后,每次請求轉(zhuǎn)發(fā)給微服務(wù)后都會在header種增加一個(gè)X-Request-red。
- AddRequestParameter=red, blue
添加Request參數(shù),每次請求轉(zhuǎn)發(fā)給微服務(wù)后都會增加一個(gè)請求參數(shù)。
自定義全局過濾器: 創(chuàng)建一個(gè)Filter包,在包下新建GatewayFilter類,自定義全局過濾器需要繼承GlobalFilter, Ordered接口,并重寫接口的兩個(gè)方法
@Component public class GatewayFilter implements GlobalFilter, Ordered { //在里面寫過濾器的邏輯 @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { System.out.println("進(jìn)入了過濾器"); //表示繼續(xù)向下執(zhí)行 return chain.filter(exchange); } //過濾器的優(yōu)先級,數(shù)值越小,優(yōu)先級越高 @Override public int getOrder() { return 0; } }
通過訪問可以看到控制臺上出現(xiàn)了打印的信息。
模擬用戶認(rèn)證過程:
全局過濾器可以實(shí)現(xiàn)對全局的用戶驗(yàn)證。修改gatewayFilter,編寫失敗的邏輯,如果獲取到的request請求中第一個(gè)屬性不是access-token或?yàn)榭?,則返回HttpStatus.UNAUTHORIZED的報(bào)錯(cuò)
@Component public class GatewayFilter implements GlobalFilter, Ordered { //在里面寫過濾器的邏輯 @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { System.out.println("進(jìn)入了過濾器"); String token = exchange.getRequest().getQueryParams().getFirst("access-token"); if (token==null){ //如果不存在,認(rèn)證失敗 System.out.println("沒有登陸"); exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } //過濾器的優(yōu)先級,數(shù)值越小,優(yōu)先級越高 @Override public int getOrder() { return 0; } }
在瀏覽器中輸入:http://localhost:9090/sentinel/test1,出現(xiàn)報(bào)錯(cuò),因?yàn)闆]有access-token
在瀏覽器中輸入:http://localhost:9090/sentinel/test1?access-token=1,獲取正確結(jié)果。
(五) 網(wǎng)關(guān)限流
在實(shí)際環(huán)境中會遇到這樣的問題,同一時(shí)間會有許多請求去調(diào)用微服務(wù),大量請求的進(jìn)入很有可能導(dǎo)致微服務(wù)被破環(huán),因此限流就變得很重要。
5.1 常見的一些限流算法:
計(jì)數(shù)器算法:設(shè)定一個(gè)單位時(shí)間內(nèi)的計(jì)數(shù)值,如果單位時(shí)間內(nèi)訪問的請求大于這個(gè)設(shè)定的值,則之后的請求都拒絕。直到單位時(shí)間內(nèi)的值低于這個(gè)值才繼續(xù)接收。
漏桶算法:我們可以把漏桶算法想象成一個(gè)漏斗。請求進(jìn)來時(shí)先到漏斗中,然后按設(shè)定好的輸出速率分配到微服務(wù)上。當(dāng)一下子有很多請求進(jìn)來時(shí),只能在漏斗上等著。為了控制流量,需要設(shè)置兩個(gè)變量:一個(gè)是桶的大小,另一個(gè)是漏斗流出的速率。
令牌桶算法:令牌桶算法是對漏桶算法的一種改進(jìn),相比于漏桶算法,令牌桶算法能允許一定程度的突發(fā)調(diào)用。令牌桶算法的原理:在令牌桶算法中,存在一個(gè)桶,用來存放固定數(shù)量的令牌,令牌會以一定速率放到桶中,桶中的令牌滿了之后就不會再放令牌。當(dāng)一個(gè)請求來臨時(shí),要先在令牌桶中拿到一個(gè)令牌,才能去調(diào)用微服務(wù),當(dāng)令牌桶中沒有令牌的時(shí)候,后來到的請求就需要等待。令牌桶算法除了可以限流,還允許一定程度的突發(fā)調(diào)用:比如一個(gè)令牌桶的容量是100,在沒有請求的時(shí)候,令牌桶中的令牌數(shù)量是滿的。此時(shí)如果突然來了100個(gè)請求,那么這100個(gè)請求都能被立刻執(zhí)行。
5.2 集成Sentinel進(jìn)行限流
添加依賴
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId> <version>1.7.2</version> </dependency>
添加Sentinel配置:
spring: cloud: sentinel: eager: true transport: dashboard: localhost:8080
將Sentinel過濾器注入到Bean容器中
@Bean @Order(-1) public GlobalFilter sentinelGatewayFilter(){ return new SentinelGatewayFilter(); }
這樣就可以用Sentinel的方式對網(wǎng)關(guān)進(jìn)行限流了。
對于限流后的錯(cuò)誤提示,我們可以修改默認(rèn)錯(cuò)誤提示方式,改成自定義或者跳轉(zhuǎn)到錯(cuò)誤頁面:
@Configuration public class GatewayConfiguration { private final ServerProperties serverProperties; private final ApplicationContext applicationContext; private final ResourceProperties resourceProperties; private final List<ViewResolver> viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; public GatewayConfiguration(ServerProperties serverProperties, ApplicationContext applicationContext, ResourceProperties resourceProperties, ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) { this.serverProperties = serverProperties; this.applicationContext = applicationContext; this.resourceProperties = resourceProperties; this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); this.serverCodecConfigurer = serverCodecConfigurer; } //自定義一個(gè)錯(cuò)誤處理 @Bean(name = "myBlockRequestHandler") public BlockRequestHandler myBlockRequestHandler(){ BlockRequestHandler blockRequestHandler=new BlockRequestHandler() { @Override public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) { return ServerResponse.status(HttpStatus.BAD_GATEWAY) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue("服務(wù)被限流了")); } }; return blockRequestHandler; } //用自定義的handler替換掉默認(rèn)的,或者重定向 @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler(BlockRequestHandler myBlockRequestHandler){ //自定義Block處理 GatewayCallbackManager.setBlockHandler(myBlockRequestHandler); //重定向block處理 //GatewayCallbackManager.setBlockHandler(new RedirectBlockRequestHandler("http://www.baidu.com")); return new SentinelGatewayBlockExceptionHandler(viewResolvers,serverCodecConfigurer); } @Bean @Order(-1) public GlobalFilter sentinelGatewayFilter(){ return new SentinelGatewayFilter(); } }
5.3 網(wǎng)關(guān)實(shí)現(xiàn)跨域
這個(gè)和SpringBoot中解決跨域的思路類似,配置CorsConfig
@Configuration public class CorsConfig { @Bean public CorsWebFilter corsWebFilter(){ CorsConfiguration configuration=new CorsConfiguration(); configuration.addAllowedHeader("*"); configuration.addAllowedMethod("*"); configuration.addAllowedOrigin("*"); UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource(new PathPatternParser()); source.registerCorsConfiguration("/*",configuration); return new CorsWebFilter(source); } }
(六)總結(jié)
本章內(nèi)容比較多,但是把SpringCloudGateway基本會遇到的內(nèi)容都講解了一遍,希望對你有幫助。
到此這篇關(guān)于基于SpringCloudGateway實(shí)現(xiàn)微服務(wù)網(wǎng)關(guān)的文章就介紹到這了,更多相關(guān)SpringCloudGateway?微服務(wù)網(wǎng)關(guān)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中的NumberFormatException異常原因以及解決方案詳解
這篇文章主要介紹了Java中的NumberFormatException異常原因以及解決方案詳解,NumberFormatException 是 Java 中的一個(gè)異常類,通常在字符串轉(zhuǎn)換為數(shù)字的過程中發(fā)生,它表示一個(gè)無效的數(shù)字格式,即字符串無法被正確解析為數(shù)字,需要的朋友可以參考下2024-02-02使用迭代器模式來進(jìn)行Java的設(shè)計(jì)模式編程
這篇文章主要介紹了使用迭代器模式來進(jìn)行Java的設(shè)計(jì)模式編程,文中對迭代器模式中的容器封裝方面的知識進(jìn)行了講解,需要的朋友可以參考下2016-02-02mybatis的foreach標(biāo)簽語法報(bào)錯(cuò)的解決
這篇文章主要介紹了mybatis的foreach標(biāo)簽語法報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02Springboot之@Async不執(zhí)行原因及分析
這篇文章主要介紹了Springboot之@Async不執(zhí)行原因及分析,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09druid ParserException類錯(cuò)誤問題及解決
這篇文章主要介紹了druid ParserException類錯(cuò)誤問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12