SpringCloudAlibaba项目搭建nacos+gateway

前言

记录一下SpringCloudAlibaba搭建过程,避免经常忘记!因为懒,记录下来以后自己抄自己 为了此结构长期可扩展性这里就集成nacos+gateway的基本结构就算完工,其余组件用的时候再说吧~nacos可以动态配置,负载均衡!gateway可以路由,过滤,拦截,限流,降级,溶断等各种功能,其实也不算半成品了。很多公司就是这么用的,如果集成一大堆组件,反而把人弄得晕呼呼的!

关于nacos

我这里直接使用docker部署了一个nacos-server!当然也可以直接clone项目直接启动nacos,或者直接把代码集成到自己项目,想怎么玩都行
关于nacos在docker下的部署请看:docker安装nacos并配置mysql数据库(docker系列六)

SpringCloudAlibaba项目搭建

创建父工程配置pom

创建一个maven项目作为父工程
大概就是下图的样子,删除src目录(因为父工程不需要启动,只是作为maven全局版本控制器使用)
在这里插入图片描述

父工程pom文件配置如下
注释都写在pom文件里面了,自己看吧

<?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>
    <!-- 描述此pom打包方式为父类型,如果不配置默认jar(所以其他子工程不需要设置,默认即可),如果需要外部部署子工程可设置war-->
    <packaging>pom</packaging>
    <!--  全局Springboot版本(包括test,web,starter等)与SpringCloud Greenwich兼容(SpringCloud版本在2020.0.X之前使用姓名作为版本,从A,B,C这样的顺序排列),Greenwich版本以上集成gateway有问题,目前没解决,所有退回来了哈哈 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.9.RELEASE</version>
        <relativePath/>
    </parent>

    <!--   maven坐标配置及此项目版本号 -->
    <groupId>com.zbdemo</groupId>
    <artifactId>spring-cloud-alibaba-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <!--   项目名称(使用坐标id或者自定义),描述,地址 -->
    <name>${project.artifactId}</name>
    <description>这是一个简单的项目描述</description>
    <url>http://www.zbdemo.com</url>
    <!--  引入jar包版本控制  -->
    <properties>
        <java.version>1.8</java.version>
        <!-- 与Springboot2.1.x兼容(这个版本以上集成gateway有问题,目前没解决,所有退回来了哈哈) -->
        <spring-cloud.version>Greenwich.SR6</spring-cloud.version>
        <lombok.version>1.18.22</lombok.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <!--SpringCloud版本全局控制(即使使用SpringCloudAlibaba也要加这个)-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--SpringCloudAlibaba版本全局控制-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>0.9.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <!-- 受管理的子依赖(下面三个是后续要增加的子项目) -->
    <modules>
        <module>commons</module>
        <module>user</module>
        <module>gateway</module>
    </modules>
    <!-- 描述打包方式 必须加在父工程而不是commons,否则其他工程引用不到,当然你也可以每个需要打包的项目都引一次-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

创建公共工程commons

创建一个maven新的
在父工程右键->new->modul创建一个子maven工程,命名为commons(意为公共工程)
在这里插入图片描述
**

创建好之后结构修改成如下格式:如果要在commons包配置相关公共bean,那么所有引用commons的的子项目包名请跟commons保持一致!如:com.zbdemo.commons的包名那么引用他的子模块包名也得是这,否则bean引用会报错!我这里演示没有配置公共bean,所以就用项目名来命名包名了!!!!!!!别跟我学,包名最好一样

**
在这里插入图片描述
commons工程pom配置如下
注释都写在pom文件里面了,自己看吧?

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-alibaba-demo</artifactId>
        <groupId>com.zbdemo</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>commons</artifactId>
    <name>${project.artifactId}</name>
    <url>http://www.zbdemo.com</url>

    <!-- 在公用项目引入依赖,在父工程全局控制版本 -->
    <dependencies>
        <!-- springboot版本父工程已控制不用写版本号 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- SpringCloudAlibaba版本父工程已控制不用写版本号 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- lombook 插件(为了演示父工程与公共子工程之间的版本控制关系,引入一个lombok作为示例)-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
        <!-- swagger2依赖(为了演示公共工程如何做公共配置引入swagger2做演示) -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
            <!-- 使用bootstrap-ui -->
<!--        <dependency>-->
<!--            <groupId>io.springfox</groupId>-->
<!--            <artifactId>springfox-swagger-ui</artifactId>-->
<!--            <version>2.9.2</version>-->
<!--        </dependency>-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.5</version>
        </dependency>
    </dependencies>
</project>

修改commons工程的pom文件后继续配置公共的swagger2
在这里插入图片描述
Swagger2Config文件内容如下:

import io.swagger.annotations.Api;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;


@Configuration
@EnableSwagger2
public class Swagger2Config {
    /**
     * 通过 createRestApi函数来构建一个DocketBean
     * 函数名,可以随意命名,喜欢什么命名就什么命名
     */
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())//调用apiInfo方法,创建一个ApiInfo实例,里面是展示在文档页面信息内容
                .select()
                //控制暴露出去的路径下的实例
                //如果某个接口不想暴露,可以使用以下注解
                //@ApiIgnore 这样,该接口就不会暴露在 swagger2 的页面下
//                .apis(RequestHandlerSelectors.basePackage("com.zbdemo"))
                // 这里不配置具体路径,扫描所有带有swagger注解的controller
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
                .paths(PathSelectors.any())
                .build();
    }

    //构建 api文档的详细信息函数
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                //页面标题
                .title(" Swagger2 构建RESTful API")
                //条款地址
                .termsOfServiceUrl("http://www.zbdemo.com")
                .version("1.0")
                //描述
                .description("spring-cloud-alibaba-demo")
                .build();
    }
}

创建普通服务工程user

按照commons工程创建的方式再创建一个user子工程作为普通的client服务测试一下效果
创建完成后结构修改成如下:
在这里插入图片描述
user工程pom配置如下
注释都写在pom文件里面了,自己看吧?
user工程依赖commons之后就会继承commons的依赖:如lombook,swagger2,springboot,springcloud等依赖

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-alibaba-demo</artifactId>
        <groupId>com.zbdemo</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>user</artifactId>
    <name>${project.artifactId}</name>
    <url>http://www.zbdemo.com</url>

    <dependencies>
        <!--依赖commons-->
        <dependency>
            <groupId>com.zbdemo</groupId>
            <artifactId>commons</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

接下来创建一个resources文件夹,在里面创建yml配置文件
在这里插入图片描述
application.yml配置文件内容如下:

# 指定user工程端口号
server:
  port: 8001
# 配置挂载的子配置文件,比如我这里创建两,一个是dev开发使用,一个是pro生产环境使用
spring:
  profiles:
    active: dev

application-dev.yml配置文件内容如下:

Spring:
  cloud:
    nacos:
      discovery:
      	# 指定你的nacos服务注册中心地址和端口,更多配置自行查询文档
        server-addr: 192.168.101.1:8848
  # 指定服务名称
  application:
    name: user

关于配置文件可以把其他配置内容放在nacos,然后通过这里引入配置,为了演示方便我就不做了
UserApplication启动类如下:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

// SpringBoot启动类注解
@SpringBootApplication
// SpringCloud客户端注解
@EnableDiscoveryClient
// 这个注解开启swagger2,swagger2配置已在commons工程做好,这里直接开启就行
@EnableSwagger2
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }
}

接下来在user工程写个controller测试一下效果:
在这里插入图片描述
UserController内容如下:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class UserController {

    @GetMapping(value = "/hello")
    public String hello() {
        return "hello word";
    }
}

最后启动user工程,测试效果
启动成功效果图:
在这里插入图片描述
查看注册中心,user已经成功注册到nacos:
在这里插入图片描述
调用我们刚刚写的接口测试效果:localhost:8001/hello/hello 调用成功
在这里插入图片描述
然后调用swagger-ui测试集成效果:localhost:8001/doc.html 效果完美
在这里插入图片描述

创建路由网关工程gateway

创建过程与前面相似,这里不重复了,创建完成后结构修改如下:
在这里插入图片描述
修改gateway工程pom文件

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-alibaba-demo</artifactId>
        <groupId>com.zbdemo</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gateway</artifactId>
    <name>gateway</name>
    <url>http://www.zbdemo.com</url>

    <!--这里不要引用commons模块,否则spring-boot-starter-web包和gateway中引用的spring-boot-starter-web会冲突报错-->
    <dependencies>
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- SpringCloudAlibaba版本父工程已控制不用写版本号 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- swagger2依赖 (网关不写业务,但是需要聚合所有服务的接口方便查看)-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.5</version>
        </dependency>
    </dependencies>
</project>

老规矩,创建resources文件夹,配置yml
application.yml配置文件内容如下:

server:
  port: 8000

spring:
  profiles:
    active: dev

端口定为8000
application-dev.yml配置文件内容如下:

Spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.101.1:8848
    gateway:
      discovery:
        locator:
          enabled: true  #表明gateway开启服务注册和发现的功能,并且spring cloud gateway自动根据服务发现为每一个服务创建了一个router,这个router将以服务名开头的请求路径转发到对应的服务
          lower-case-service-id: true  #是将请求路径上的服务名配置为小写(因为服务注册的时候,向注册中心注册时将服务名转成大写的了
      routes:
        -id: user  #自定义id,无意义但不能重复,最好跟服务名保持一致
        uri: lb://user  # 注册中心中的服务吗
        predicates:
          - Path=/user/** # 转发该路径
        filters:
          - StripPrefix=1 #必须加上StripPrefix=1,否则访问服务时会带上user
      # 经过gateWay网关时,需要在网关统一配置跨域请求,全部通过
      globalcors:
        cors-configurations:
          '[/**]':
            allowed-origins: "*"
            allowed-headers: "*"
            allow-credentials: true
            allowed-methods:
              - GET
              - POST
              - DELETE
              - PUT
              - OPTION

GatewayApplication启动类如下:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

启动Gateway服务测试路由效果
成功注册到nacos
在这里插入图片描述
访问:localhost:8000/user/hello/hello 测试路由转发效果
在这里插入图片描述

gateway聚合swagger2接口文档

在gateway项目中创建文件如下:
在这里插入图片描述
SwaggerProvider内容:

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator;
import org.springframework.context.annotation.Primary;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

@Component
@Primary
public class SwaggerProvider implements SwaggerResourcesProvider {
    /**
     * swagger的api json文档路径
     */
    public static final String API_URI = "/v2/api-docs";
    /**
     * Eureka发现功能的方法的名字,注册的服务会加入这个前缀
     */
    public static final String EUREKA_SUB_PFIX = "CompositeDiscoveryClient_";
    /**
     * 服务发现的路由处理器
     */
    private final DiscoveryClientRouteDefinitionLocator routeLocator;

    public SwaggerProvider(DiscoveryClientRouteDefinitionLocator routeLocator) {
        this.routeLocator = routeLocator;
    }

    @Override
    public List<SwaggerResource> get() {

        List<SwaggerResource> resources = new ArrayList<>();

        List<String> routes = new ArrayList<>();
        //从DiscoveryClientRouteDefinitionLocator 中取出routes,构造成swaggerResource
        routeLocator.getRouteDefinitions().subscribe(routeDefinition -> {
            resources.add(swaggerResource(
                    //获取id(服务注册的id)
                    routeDefinition.getId()
                            //去除CompositeDiscoveryClient_前缀
                            .substring(EUREKA_SUB_PFIX.length()),
                    //获取路由定义信息列表
                    routeDefinition.getPredicates()
                            //获取路径信息PredicateDefinition{name='Path', args={pattern=/byb-provider2/**}}
                            .get(0)
                            .getArgs()
                            //将pattern中的/**替换为服务swagger文档路径
                            .get("pattern")
                            .replace("/**", API_URI)));
        });
        return resources;
    }

    private SwaggerResource swaggerResource(String name, String location) {

        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }
}

SwaggerHandler内容:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.*;

import java.util.Optional;

@RestController
@RequestMapping("/swagger-resources")
public class SwaggerHandler {
    @Autowired(required = false)
    private SecurityConfiguration securityConfiguration;

    @Autowired(required = false)
    private UiConfiguration uiConfiguration;
    private final SwaggerResourcesProvider swaggerResources;

    @Autowired
    public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {
        this.swaggerResources = swaggerResources;
    }

    @GetMapping("/configuration/security")
    public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
    }

    @GetMapping("/configuration/ui")
    public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));

    }

	// 请使用更新后的的方法
    @GetMapping("")
    public Mono<ResponseEntity> swaggerResources() {
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    }
}

2023-10-22更新:原来的的方式在刷新页面后第二次无法正常获取接口资源目录,所以这里人工保存一下资源目录

 private Mono<ResponseEntity> mono;
 @GetMapping("")
 public Mono<ResponseEntity> swaggerResources() {
      // 存储返回的资源目录,因为下一次进入资源目录获取不到
      if (mono == null){
          mono = Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
      }
      return mono;
  }

重启gateway测试接口聚合效果
访问:http://localhost:8000/doc.html
在这里插入图片描述
可以看到已经成功检索到user服务接口内容,后续添加其他服务也会检索进gateway的swagger文档
其他内容后续可能会另起一篇作为增量,目前这篇就到此为止,太多太杂容易让人迷失
演示代码拉取地址:我知道你想要

  • 6
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
您好!要搭建Spring Cloud Alibaba Nacos项目,您可以按照以下步骤进行操作: 1. 创建Spring Boot项目:首先,在您的IDE中创建一个新的Spring Boot项目。 2. 添加依赖:在项目的pom.xml文件中添加相应的依赖。您需要添加以下四个核心依赖: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> ``` 3. 配置Nacos Server地址:在application.properties(或application.yml)文件中配置Nacos Server的地址。例如: ```yaml spring.cloud.nacos.discovery.server-addr=${NACOS_SERVER_ADDR:localhost:8848} ``` 4. 创建服务提供者和消费者:根据您的需求,创建相应的服务提供者和消费者。您可以使用`@RestController`注解创建简单的RESTful接口。 5. 注册服务:在服务提供者的主类上添加`@EnableDiscoveryClient`注解,以将服务注册到Nacos Server上。 6. 调用服务:在服务消费者中使用`@RestTemplate`或Feign等方式调用服务。您可以通过在方法上添加`@LoadBalanced`注解来实现负载均衡。 7. 启动应用程序:最后,启动应用程序并验证各个微服务之间的通信是否正常。 这些是搭建Spring Cloud Alibaba Nacos项目的基本步骤。根据您的具体需求,您可能还需要配置其他功能,如动态配置等。希望对您有帮助!如有更多问题,请随时提问。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值