SpringCloudAlibaba项目搭建nacos+gateway

SpringCloudAlibaba项目搭建nacos+gateway

  • 前言
  • 关于nacos
  • SpringCloudAlibaba项目搭建
    • 创建父工程配置pom
    • 创建公共工程commons
    • 创建好之后结构修改成如下格式:如果要在commons包配置相关公共bean,那么所有引用commons的的子项目包名请跟commons保持一致!如:com.zbdemo.commons的包名那么引用他的子模块包名也得是这,否则bean引用会报错!我这里演示没有配置公共bean,所以就用项目名来命名包名了!!!!!!!别跟我学,包名最好一样
    • 创建普通服务工程user
    • 创建路由网关工程gateway
    • gateway聚合swagger2接口文档

前言

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

关于nacos

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

SpringCloudAlibaba项目搭建

创建父工程配置pom

创建一个maven项目作为父工程
大概就是下图的样子,删除src目录(因为父工程不需要启动,只是作为maven全局版本控制器使用)
SpringCloudAlibaba项目搭建nacos+gateway_第1张图片

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


<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.0modelVersion>
    
    <packaging>pompackaging>
    
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.1.9.RELEASEversion>
        <relativePath/>
    parent>

    
    <groupId>com.zbdemogroupId>
    <artifactId>spring-cloud-alibaba-demoartifactId>
    <version>0.0.1-SNAPSHOTversion>
    
    <name>${project.artifactId}name>
    <description>这是一个简单的项目描述description>
    <url>http://www.zbdemo.comurl>
    
    <properties>
        <java.version>1.8java.version>
        
        <spring-cloud.version>Greenwich.SR6spring-cloud.version>
        <lombok.version>1.18.22lombok.version>
    properties>
    <dependencyManagement>
        <dependencies>
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                <version>0.9.0.RELEASEversion>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>
    
    <modules>
        <module>commonsmodule>
        <module>usermodule>
        <module>gatewaymodule>
    modules>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>
project>

创建公共工程commons

创建一个maven新的
在父工程右键->new->modul创建一个子maven工程,命名为commons(意为公共工程)
SpringCloudAlibaba项目搭建nacos+gateway_第2张图片
**

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

**
SpringCloudAlibaba项目搭建nacos+gateway_第3张图片
commons工程pom配置如下
注释都写在pom文件里面了,自己看吧?



<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-demoartifactId>
        <groupId>com.zbdemogroupId>
        <version>0.0.1-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>

    <artifactId>commonsartifactId>
    <name>${project.artifactId}name>
    <url>http://www.zbdemo.comurl>

    
    <dependencies>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
        dependency>
        
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>${lombok.version}version>
        dependency>
        
        <dependency>
            <groupId>io.springfoxgroupId>
            <artifactId>springfox-swagger2artifactId>
            <version>2.9.2version>
        dependency>
            





        <dependency>
            <groupId>com.github.xiaoymingroupId>
            <artifactId>swagger-bootstrap-uiartifactId>
            <version>1.9.5version>
        dependency>
    dependencies>
project>

修改commons工程的pom文件后继续配置公共的swagger2
SpringCloudAlibaba项目搭建nacos+gateway_第4张图片
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服务测试一下效果
创建完成后结构修改成如下:
SpringCloudAlibaba项目搭建nacos+gateway_第5张图片
user工程pom配置如下
注释都写在pom文件里面了,自己看吧?
user工程依赖commons之后就会继承commons的依赖:如lombook,swagger2,springboot,springcloud等依赖



<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-demoartifactId>
        <groupId>com.zbdemogroupId>
        <version>0.0.1-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>

    <artifactId>userartifactId>
    <name>${project.artifactId}name>
    <url>http://www.zbdemo.comurl>

    <dependencies>
        
        <dependency>
            <groupId>com.zbdemogroupId>
            <artifactId>commonsartifactId>
            <version>0.0.1-SNAPSHOTversion>
        dependency>
    dependencies>
project>

接下来创建一个resources文件夹,在里面创建yml配置文件
SpringCloudAlibaba项目搭建nacos+gateway_第6张图片
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测试一下效果:
SpringCloudAlibaba项目搭建nacos+gateway_第7张图片
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:
SpringCloudAlibaba项目搭建nacos+gateway_第8张图片
调用我们刚刚写的接口测试效果:localhost:8001/hello/hello 调用成功
在这里插入图片描述
然后调用swagger-ui测试集成效果:localhost:8001/doc.html 效果完美

创建路由网关工程gateway

创建过程与前面相似,这里不重复了,创建完成后结构修改如下:
SpringCloudAlibaba项目搭建nacos+gateway_第9张图片
修改gateway工程pom文件



<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-demoartifactId>
        <groupId>com.zbdemogroupId>
        <version>0.0.1-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>

    <artifactId>gatewayartifactId>
    <name>gatewayname>
    <url>http://www.zbdemo.comurl>

    
    <dependencies>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-gatewayartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
        dependency>
        
        <dependency>
            <groupId>io.springfoxgroupId>
            <artifactId>springfox-swagger2artifactId>
            <version>2.9.2version>
        dependency>
        <dependency>
            <groupId>com.github.xiaoymingroupId>
            <artifactId>swagger-bootstrap-uiartifactId>
            <version>1.9.5version>
        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
SpringCloudAlibaba项目搭建nacos+gateway_第10张图片
访问:localhost:8000/user/hello/hello 测试路由转发效果
在这里插入图片描述

gateway聚合swagger2接口文档

在gateway项目中创建文件如下:
SpringCloudAlibaba项目搭建nacos+gateway_第11张图片
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)));
    }
}

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

你可能感兴趣的:(java,gateway,java,微服务,spring,cloud,alibaba)