欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring Cloud Gateway組件的三種使用方式實(shí)例詳解

 更新時(shí)間:2024年01月11日 10:33:00   作者:Java方文山  
Spring Cloud Gateway是 Spring 官方基于 Spring5.0 、 SpringBoot2.0 和 Project Reactor 等技術(shù)開發(fā)的網(wǎng)關(guān)旨在為微服務(wù)框架提供一種簡(jiǎn)單而有效的統(tǒng)一的API 路由管理方式,統(tǒng)一訪問(wèn)接口,這篇文章主要介紹了Spring Cloud Gateway組件的三種使用方式,需要的朋友可以參考下

??前言         

Spring Cloud Gateway是 Spring 官方基于 Spring5.0 、 SpringBoot2.0 和 Project Reactor 等技術(shù)開發(fā)的網(wǎng)關(guān)旨在為微服務(wù)框架提供一種簡(jiǎn)單而有效的統(tǒng)一的API 路由管理方式,統(tǒng)一訪問(wèn)接口。      

   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)和限流等等,而且它是基于Netty 的響應(yīng)式開發(fā)模式。

?創(chuàng)建模塊

我們的Gatewa既然是負(fù)責(zé)網(wǎng)絡(luò)路由的,那么它首先肯定是個(gè)模塊,所以我們的第一步就是需要?jiǎng)?chuàng)建一個(gè)模塊。

修改該模塊的pom.xml文件,讓其繼承父模塊及導(dǎo)入相應(yīng)的依賴

  <parent>
        <groupId>org.example</groupId>
        <artifactId>Cloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.35</version>
    </dependency>
</dependencies>

因?yàn)樗械姆?wù)都要接入網(wǎng)關(guān),而服務(wù)都在注冊(cè)中心有記錄,所以我們網(wǎng)關(guān)要與Nacos關(guān)聯(lián),首先需要在配置文件中與Nacos做配置并且在啟動(dòng)類開啟Nacos

@EnableDiscoveryClient(啟動(dòng)類打上該注解)

server:
  port: 8083
spring:
  cloud:
    nacos:
      server-addr: localhost:8848
  application:
    name: geteway

將全部服務(wù)啟動(dòng)就可以看到我們的gateway也被注冊(cè)到Nacos中啦

?使用Gateway的三種方式

??方法一

gateway:
  discovery:
    locator:
#是否與服務(wù)發(fā)現(xiàn)組件進(jìn)行結(jié)合,通過(guò)service-id(必須設(shè)置成大寫)轉(zhuǎn)發(fā)到具體的服務(wù)實(shí)例。默認(rèn) false
#為true代表開啟基于服務(wù)發(fā)現(xiàn)的路由規(guī)則。
        enabled: true
#配置之后訪問(wèn)時(shí)service-id無(wú)需大寫
        lower-case-service-id: true

注意:我們的gateway是與spring下的nacos的標(biāo)簽同級(jí)別可不要將它寫在nacos下面

 

 前面是通過(guò)服務(wù)直接訪問(wèn)的,后面則是通過(guò)網(wǎng)關(guān)向服務(wù)發(fā)起的請(qǐng)求,此時(shí)我們的請(qǐng)求已經(jīng)被官網(wǎng)處理了。

??方法二

第二種方式是為了防止使用第一種方式的時(shí)候服務(wù)名字太長(zhǎng)而導(dǎo)致的麻煩,這種方式類似于為服務(wù)名又起了一個(gè)別名。

    gateway:
      routes:
      # 路由標(biāo)識(shí)(id:標(biāo)識(shí),具有唯一性)
      - id: user-consumer-api
      #目標(biāo)服務(wù)地址(uri:地址,請(qǐng)求轉(zhuǎn)發(fā)后的地址),會(huì)自動(dòng)從注冊(cè)中心獲得服務(wù)的IP,不需要手動(dòng)寫死
        uri: lb://consume
      #優(yōu)先級(jí),越小越優(yōu)先
        predicates:
        # 路徑匹配,
           - Path=/aa/**
        filters:
      #前綴過(guò)濾,請(qǐng)求地址:http://localhost:8084/usr/hello
      #此處配置去掉1個(gè)路徑前綴,再配置上面的 Path=/usr/**,就將**轉(zhuǎn)發(fā)到指定的微服務(wù)
            - StripPrefix=1

 這里如果使用的是http://localhost:8083/aa/test01就會(huì)映射到consume這個(gè)服務(wù),并且通過(guò)前綴過(guò)濾會(huì)過(guò)濾掉aa拿到test01就會(huì)映射到consume/test01上,得到如下結(jié)果????

??方法三

第三種方式是結(jié)合配置讀取類進(jìn)行的,我們將對(duì)服務(wù)的網(wǎng)關(guān)配置寫在Nacos,然后再用這個(gè)讀取類去進(jìn)行讀取,獲取我們想要的路由信息。

    gateway:
      nacos:
      server-addr: ${spring.cloud.nacos.server-addr}
      data-id: dynamic-routing.json
      group: DEFAULT_GROUP

首先需要新建一個(gè)POJO包將以下類進(jìn)行創(chuàng)建

package org.example.geteway.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.LinkedHashMap;
import java.util.Map;
/**
 * @author hgh
 */
@SuppressWarnings("all")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class FilterEntity {
    //過(guò)濾器對(duì)應(yīng)的Name
    private String name;
    //路由規(guī)則
    private Map<String, String> args = new LinkedHashMap<>();
}
package org.example.geteway.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@SuppressWarnings("all")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@ConfigurationProperties(prefix = "gateway.nacos")
@Component
public class GatewayNacosProperties {
    private String serverAddr;
    private String dataId;
    private String namespace;
    private String group;
}
package org.example.geteway.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.LinkedHashMap;
import java.util.Map;
/**
 * @author hgh
 */
@SuppressWarnings("all")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class PredicateEntity {
    //斷言對(duì)應(yīng)的Name
    private String name;
    //斷言規(guī)則
    private Map<String, String> args = new LinkedHashMap<>();
}
package org.example.geteway.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.ArrayList;
import java.util.List;
/**
 * @author hgh
 */
@SuppressWarnings("all")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class RouteEntity {
    //路由id
    private String id;
    //路由斷言集合
    private List<PredicateEntity> predicates = new ArrayList<>();
    //路由過(guò)濾器集合
    private List<FilterEntity> filters = new ArrayList<>();
    //路由轉(zhuǎn)發(fā)的目標(biāo)uri
    private String uri;
    //路由執(zhí)行的順序
    private int order = 0;
}

最后創(chuàng)建一個(gè)配置信息讀取類,這個(gè)類是一個(gè)基于 Spring Cloud Gateway 和 Nacos 的動(dòng)態(tài)路由配置類,它實(shí)現(xiàn)了一個(gè) Spring 提供的事件推送接口 ApplicationEventPublisherAware。它的功能主要包括監(jiān)聽 Nacos 的配置變化、解析從 Nacos 讀取的路由配置信息(json格式)、路由更新、以及組裝和定義路由信息等。通過(guò)這個(gè)類,可以實(shí)現(xiàn)路由信息的動(dòng)態(tài)管理和更新。

package org.example.geteway;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.example.geteway.pojo.FilterEntity;
import org.example.geteway.pojo.GatewayNacosProperties;
import org.example.geteway.pojo.PredicateEntity;
import org.example.geteway.pojo.RouteEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;
/**
 * 此類實(shí)現(xiàn)了Spring Cloud Gateway + nacos 的動(dòng)態(tài)路由,
 * 它實(shí)現(xiàn)一個(gè)Spring提供的事件推送接口ApplicationEventPublisherAware
 */
@SuppressWarnings("all")
@Slf4j
@Component
public class DynamicRoutingConfig implements ApplicationEventPublisherAware {
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    @Autowired
    private GatewayNacosProperties gatewayProperties;
    @Autowired
    private ObjectMapper mapper;
    private ApplicationEventPublisher applicationEventPublisher;
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }
    /**
     * 這個(gè)方法主要負(fù)責(zé)監(jiān)聽Nacos的配置變化,這里先使用參數(shù)構(gòu)建一個(gè)ConfigService,
     * 再使用ConfigService開啟一個(gè)監(jiān)聽,
     * 并且在監(jiān)聽的方法中刷新路由信息。
     */
    @Bean
    public void refreshRouting() throws NacosException {
        //創(chuàng)建Properties配置類
        Properties properties = new Properties();
        System.out.println(gatewayProperties);
        //設(shè)置nacos的服務(wù)器地址,從配置類GatewayProperties中獲取
        properties.put(PropertyKeyConst.SERVER_ADDR, gatewayProperties.getServerAddr());
        //設(shè)置nacos的命名空間,表示從具體的命名空間中獲取配置信息,不填代表默認(rèn)從public獲得
        if (gatewayProperties.getNamespace() != null) {
            properties.put(PropertyKeyConst.NAMESPACE, gatewayProperties.getNamespace());
        }
        //根據(jù)Properties配置創(chuàng)建ConfigService類
        ConfigService configService = NacosFactory.createConfigService(properties);
        //獲得nacos中已有的路由配置
        String json = configService.getConfig(gatewayProperties.getDataId(), gatewayProperties.getGroup(), 5000);
        this.parseJson(json);
        //添加監(jiān)聽器,監(jiān)聽nacos中的數(shù)據(jù)修改事件
        configService.addListener(gatewayProperties.getDataId(), gatewayProperties.getGroup(), new Listener() {
            @Override
            public Executor getExecutor() {
                return null;
            }
            /**
             * 用于接收遠(yuǎn)端nacos中數(shù)據(jù)修改后的回調(diào)方法
             */
            @Override
            public void receiveConfigInfo(String configInfo) {
                log.warn(configInfo);
                //獲取nacos中修改的數(shù)據(jù)并進(jìn)行轉(zhuǎn)換
                parseJson(configInfo);
            }
        });
    }
    /**
     * 解析從nacos讀取的路由配置信息(json格式)
     */
    public void parseJson(String json) {
        log.warn("從Nacos返回的路由配置(JSON格式):" + json);
        boolean refreshGatewayRoute = JSONObject.parseObject(json).getBoolean("refreshGatewayRoute");
        if (refreshGatewayRoute) {
            List<RouteEntity> list = JSON.parseArray(JSONObject.parseObject(json).getString("routeList")).toJavaList(RouteEntity.class);
            for (RouteEntity route : list) {
                update(assembleRouteDefinition(route));
            }
        } else {
            log.warn("路由未發(fā)生變更");
        }
    }
    /**
     * 路由更新
     */
    public void update(RouteDefinition routeDefinition) {
        try {
            this.routeDefinitionWriter.delete(Mono.just(routeDefinition.getId()));
            log.warn("路由刪除成功:" + routeDefinition.getId());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        try {
            routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
            this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
            log.warn("路由更新成功:" + routeDefinition.getId());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
    /**
     * 路由定義
     */
    public RouteDefinition assembleRouteDefinition(RouteEntity routeEntity) {
        RouteDefinition definition = new RouteDefinition();
        // ID
        definition.setId(routeEntity.getId());
        // Predicates
        List<PredicateDefinition> pdList = new ArrayList<>();
        for (PredicateEntity predicateEntity : routeEntity.getPredicates()) {
            PredicateDefinition predicateDefinition = new PredicateDefinition();
            predicateDefinition.setArgs(predicateEntity.getArgs());
            predicateDefinition.setName(predicateEntity.getName());
            pdList.add(predicateDefinition);
        }
        definition.setPredicates(pdList);
        // Filters
        List<FilterDefinition> fdList = new ArrayList<>();
        for (FilterEntity filterEntity : routeEntity.getFilters()) {
            FilterDefinition filterDefinition = new FilterDefinition();
            filterDefinition.setArgs(filterEntity.getArgs());
            filterDefinition.setName(filterEntity.getName());
            fdList.add(filterDefinition);
        }
        definition.setFilters(fdList);
        // URI
        URI uri = UriComponentsBuilder.fromUriString(routeEntity.getUri()).build().toUri();
        definition.setUri(uri);
        return definition;
    }
}

現(xiàn)在需要我們?nèi)acos創(chuàng)建對(duì)應(yīng)的配置 dynamic-routing.json

{
  "refreshGatewayRoute": true,
  "routeList": [
    {
      "id": "consumer-api",
      "predicates": [
        {
          "name": "Path",
          "args": {
            "_genkey_0": "/cum/**"
          }
        }
      ],
      "filters": [
        {
          "name": "StripPrefix",
          "args": {
            "_genkey_0": "1"
          }
        }
      ],
      "uri": "lb://consumer",
      "order": 0
    },
    {
      "id": "provider-api",
      "predicates": [
        {
          "name": "Path",
          "args": {
            "_genkey_0": "/pvr/**"
          }
        }
      ],
      "filters": [
        {
          "name": "StripPrefix",
          "args": {
            "_genkey_0": "1"
          }
        }
      ],
      "uri": "lb://provider",
      "order": 0
    }
  ]
}

現(xiàn)在我們就可以通過(guò)獲取Nacos所配置的路由進(jìn)行訪問(wèn)了

如果你更改了Nacos的信息也會(huì)實(shí)時(shí)發(fā)送改變不用重啟服務(wù)器

到此這篇關(guān)于Spring Cloud Gateway組件的三種使用方式的文章就介紹到這了,更多相關(guān)Spring Cloud Gateway組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論