天天看點

Spring Boot整合Nacos與Gateway實作前後端分離微服務

作者:Java功夫

Spring Boot整合Nacos與Gateway實作前後端分離微服務

架構選擇nacos作為服務注冊,GateWay作為網關兩者都是ali。那nacos咱們都知道可作為配置中心來使用且可動态,那做一個動态路由我覺得還是有些必要性的,不至于每次增加路由都要重新部署服務。

Spring Boot整合Gateway與阿裡系微服務內建Maven配置如下:

<?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>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.3.4.RELEASE</version>

<relativePath/> <!-- lookup parent from repository -->

</parent>

<groupId>com.bins.springboot.java</groupId>

<artifactId>gongfu</artifactId>

<version>0.0.1</version>

<name>gongfu</name>

<description>Demo project for Spring Boot</description>

<properties>

<java.version>1.8</java.version>

<spring-cloud.version>Greenwich.SR3</spring-cloud.version>

</properties>

<dependencies>

<dependency>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

<!--gateway-->

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-gateway</artifactId>

<!--nacos dicovery-->

<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>

</dependencies>

<dependencyManagement>

<artifactId>spring-cloud-dependencies</artifactId>

<version>${spring-cloud.version}</version>

<type>pom</type>

<scope>import</scope>

<artifactId>spring-cloud-alibaba-dependencies</artifactId>

<version>0.2.2.RELEASE</version>

</dependencyManagement>

<build>

<plugins>

<plugin>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

Spring Boot整合Nacos與Gateway實作前後端分離微服務

一、代碼整合

@Data

@Component

@ConfigurationProperties(prefix = "broad.dynamic.route")//yml配置資訊,下文給出

@ConditionalOnBean(DynamicRouteConfiguration.class)

public class DynamicRouteProperties {

/**

* nacos 配置管理 dataId

*/

private String dataId;

* nacos 配置管理 group

private String group;

* nacos 服務位址

private String ipAddr;

* 啟動動态路由的标志,預設關閉

private boolean enabled = false;

}

DynamicRouteConfiguration:

@Configuration

@ConditionalOnProperty(name = "broad.dynamic.route.enabled", matchIfMissing = true)

public class DynamicRouteConfiguration implements ApplicationEventPublisherAware {

Logger log= LoggerFactory.getLogger(DynamicRouteConfiguration.class);

//namespace名稱

private final static String NAMESPACE="8359a8d9-03ab-4574-9627-9456351c0c01";

//nacos賬号密碼

private final static String USERNAME_PASSWORD="nacos";

//截取字元

private final static String REPLACE="routes:";

private DynamicRouteProperties bean;

private RouteDefinitionWriter writer;

private ApplicationEventPublisher publisher;

public DynamicRouteConfiguration(DynamicRouteProperties bean, RouteDefinitionWriter writer, ApplicationEventPublisher publisher) {

this.bean = bean;

this.writer = writer;

this.publisher = publisher;

}

@PostConstruct

private void init() {

Assert.notNull(bean.getDataId(), "broad.dynamic.route.dataId null異常");

Assert.notNull(bean.getGroup(), "broad.dynamic.route.group is null異常");

Assert.notNull(bean.getIpAddr(), "broad.dynamic.route.ipAddr is null異常");

dynamicRouteByNacosListener();

private void dynamicRouteByNacosListener() {

try {

Properties properties = new Properties();

properties.put(PropertyKeyConst.NAMESPACE, NAMESPACE);

properties.put(PropertyKeyConst.SERVER_ADDR, bean.getIpAddr());

properties.put("username",USERNAME_PASSWORD);

properties.put("password",USERNAME_PASSWORD);

ConfigService configService = NacosFactory.createConfigService(properties);

String content = configService.getConfigAndSignListener(

bean.getDataId(),

bean.getGroup(),

5000,

new AbstractListener() {

@Override

public void receiveConfigInfo(String configInfo) {

updateConfig(configInfo);

});

updateConfig(content);

} catch (NacosException e) {

log.error("nacos 擷取動态路由配置和監聽異常", e);

private void updateConfig(String content) {

String contentReally=replaceContext(content);

log.info("nacos 動态路由更新: {}", contentReally);

getRouteDefinitions(contentReally).forEach(routeDefinition -> {

log.info("動态路由配置: {}", routeDefinition);

writer.delete(Mono.just(routeDefinition.getId()));

writer.save(Mono.just(routeDefinition)).subscribe();

publisher.publishEvent(new RefreshRoutesEvent(this));

} catch (Exception e) {

log.error("更新動态路由配置異常: ", e);

* 因在nacos配置路由攜帶 spring字首,會導緻yaml解析失敗,是以需截取

* @return

private String replaceContext(String content){

String contentDelete=content.replaceAll("\r|\n", "").substring(0, content.indexOf(REPLACE)+1);

String contentReally=content.substring(contentDelete.length()+7, content.length());

return contentReally;

* yaml轉換

* @param content

private List<RouteDefinition> getRouteDefinitions(String content) {

return JSON.parseArray(JSON.toJSONString(

YamlHelper.getInstance().load(content)

), RouteDefinition.class);

public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {

this.publisher = applicationEventPublisher;

Spring Boot整合Nacos與Gateway實作前後端分離微服務

二、配置檔案參數

server:

port: 8085

spring:

application:

name:gongfu

cloud:

nacos:

discovery:

server-addr: localhost:8848

gateway:

routes:

- id: apiconsumer ##路由 ID(不是網關ID),保持唯一

#目标服務位址 (加 lb 根據注冊中心服務名比對)

uri: lb://provider1

predicates:

# #路由條件,Predicate 接受一個輸入參數,傳回一個布爾值結果。該接口包含多種預設方法來将 Predicate 組合成其他複雜的邏輯(比如:與,或,非)

- Path=/provider/**

#必須加上StripPrefix=1,否則通路服務時會帶上provider

filters:

- StripPrefix=1

locator:

enabled: true #表明gateway開啟服務注冊和發現的功能,并且spring cloud gateway自動根據服務發現為每一個服務建立了一個router,這個router将以服務名開頭的請求路徑轉發到對應的服務

lower-case-service-id: true #是将請求路徑上的服務名配置為小寫(因為服務注冊的時候,向注冊中心注冊時将服務名轉成大寫的了

Spring Boot整合Nacos與Gateway實作前後端分離微服務

三、啟動類

啟動類增加@EnableDiscoverClient

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient

@SpringBootApplication

public class GongfuApplication {

public static void main(String[] args) {

SpringApplication.run(GongfuApplication.class, args);

Spring Boot整合Nacos與Gateway實作前後端分離微服務

四、前後端分離解決跨域問題

(1)利用nginx反向代理,解決跨域問題

Spring Boot整合Nacos與Gateway實作前後端分離微服務

所有的請求都通過nginx,讓 nginx 來差別請求是發送到前端還是網關。發送到網關的請求,讓網關轉發到相應的微服務。

(2)添加響應頭

因為所有的請求都會經過 gateway 網關,在請求響應的過程中,經 gateway 網關給請求添加響應頭,解決跨域問題。

public class GongfuCorsConfiguration {

@Bean

public CorsWebFilter corsWebFilter() {

UrlBasedCorsConfigurationSource ubcs = new UrlBasedCorsConfigurationSource();

// 對于任意路徑(/**)都要配置跨域

CorsConfiguration corsConfiguration = new CorsConfiguration();

// 配置跨域

corsConfiguration.addAllowedHeader("*"); // Access-Control-Expose-Headers

corsConfiguration.addAllowedMethod("*"); // Access-Control-Allow-Methods

corsConfiguration.addAllowedOriginPattern("*"); // Access-Control-Allow-origin

corsConfiguration.setAllowCredentials(true); // Access-Control-Allow-Credentials

ubcs.registerCorsConfiguration("/**", corsConfiguration);

return new CorsWebFilter(ubcs);

這樣就解決了Gateway+Nacos前後端分離中的問題了。

繼續閱讀