天天看点

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前后端分离中的问题了。

继续阅读