laitimes

Spring Boot integrates Nacos with Gateway to implement front-end and back-end decoupled microservices

author:Java Kung Fu

Spring Boot integrates Nacos with Gateway to implement front-end and back-end decoupled microservices

The architecture chooses nacos as the service registration and GateWay as the gateway, both of which are ali. That nacos we all know can be used as a configuration center and can be dynamic, then to do a dynamic route I think there is still some necessity, not to add routes every time to redeploy the service.

Spring Boot Integration Gateway and Alibaba Microservices Integration Maven are configured as follows:

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

<!--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 integrates Nacos with Gateway to implement front-end and back-end decoupled microservices

1. Code integration

@Data

@Component

@ConfigurationProperties (prefix = "broad.dynamic.route") //yml configuration information, given below

@ConditionalOnBean(DynamicRouteConfiguration.class)

public class DynamicRouteProperties {

/**

* nacos configuration management dataId

*/

private String dataId;

* Nacos configuration management group

private String group;

* Nacos service address

private String ipAddr;

* Flags that enable dynamic routing, off by default

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 name

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

Nacos account password

private final static String USERNAME_PASSWORD="nacos";

Intercept characters

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 get dynamic routing configuration and listening exceptions", e);

private void updateConfig(String content) {

String contentReally=replaceContext(content);

log.info ("nacos dynamic route update: {}", contentReally);

getRouteDefinitions(contentReally).forEach(routeDefinition -> {

log.info ("Dynamic Routing Configuration: {}", routeDefinition);

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

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

publisher.publishEvent(new RefreshRoutesEvent(this));

} catch (Exception e) {

log.error("Update dynamic routing configuration exception: ", e);

* Because the route configured in nacos carries a spring prefix, yaml parsing fails, so interception is required

* @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 conversion

* @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 integrates Nacos with Gateway to implement front-end and back-end decoupled microservices

Second, the configuration file parameters

server:

port: 8085

spring:

application:

name:gongfu

cloud:

nacos:

discovery:

server-addr: localhost:8848

gateway:

routes:

- id: apiconsumer ##路由 ID (not gateway ID) and remains unique

#目标服务地址 (plus lb matches based on registry service name)

uri:lb://provider1

predicates:

# #路由条件, Predicate accepts an input parameter and returns a Boolean result. The interface contains several default methods to combine Predicate into other complex logic (e.g., and, or, non)

- Path=/provider/**

#必须加上StripPrefix = 1, otherwise you will bring a provideder when you access the service

filters:

- StripPrefix=1

locator:

Enabled:true #表明gateway开启服务注册和发现的功能, and spring cloud gateway automatically creates a router for each service based on service discovery, which will forward the request path that begins with the service name to the corresponding service

lower-case-service-id: true #是将请求路径上的服务名配置为小写 (because when the service is registered, the service name is changed to uppercase when it registers with the registry.)

Spring Boot integrates Nacos with Gateway to implement front-end and back-end decoupled microservices

Third, the start-up class

The startup class increases the @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 integrates Nacos with Gateway to implement front-end and back-end decoupled microservices

Fourth, the separation of front and back end solves cross-domain problems

(1) Use nginx reverse proxy to solve cross-domain problems

Spring Boot integrates Nacos with Gateway to implement front-end and back-end decoupled microservices

All requests go through nginx, leaving nginx to distinguish whether the request is sent to the frontend or the gateway. Requests sent to the gateway that are forwarded by the gateway to the appropriate microservice.

(2) Add response headers

Because all requests will go through the gateway gateway, during the request response process, the gateway gateway adds response headers to the request to solve the cross-domain problem.

public class GongfuCorsConfiguration {

@Bean

public CorsWebFilter corsWebFilter() {

UrlBasedCorsConfigurationSource ubcs = new UrlBasedCorsConfigurationSource();

Cross-domains are configured for any path (/**).

CorsConfiguration corsConfiguration = new CorsConfiguration();

Configure cross-domain

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);

This solves the problem in the separation of the front and back ends of Gateway+Nacos.

Read on