20、微服务构建:Spring Boot 与 Vert.x 的 API 文档及应用实践

微服务构建:Spring Boot 与 Vert.x 的 API 文档及应用实践

1. Swagger 文档与 OpenAPI

在微服务架构中,会构建大量的 API 用于数据暴露和服务间通信,因此对 API 进行文档记录十分必要。为规范 REST API 的描述,开放 API 倡议(OAI)应运而生,其目的是创建和发展一个与供应商无关的标准描述格式。SmartBear 公司将 Swagger 规范捐赠给 OAI,使其成为 API 文档的事实标准。

Spring 本身没有内置的 API 文档生成机制,但借助 SpringFox 等开源框架可以轻松实现。SpringFox 能为使用 Spring 框架编写的 JSON API 自动生成可读的规范。

1.1 集成 Swagger 和 SpringFox

要集成 Swagger 和 SpringFox,需在 Maven 的 pom.xml 文件中添加相关依赖:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

然后在 Spring Boot 配置中创建 Docket bean 以集成 Swagger 2:

@Configuration
@EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2).select()
           .apis(RequestHandlerSelectors.basePackage(
"com.packtpub.springboot.footballplayermicroservice.controller"))
           .paths(PathSelectors.any())
           .build();
    }
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
            .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
            .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

这里使用 @EnableSwagger2 注解启用 Swagger 支持, api 方法通过字符串谓词过滤要记录的控制器和方法。

运行应用程序:

$ mvn spring-boot:run

通过访问 http://localhost:8080/v2/api-docs 可获取 API 文档的 JSON 表示。以下是部分示例:

{
    "swagger":"2.0",
    "info":{
        "description":"Api Documentation",
        "version":"1.0",
        "title":"Api Documentation",
        "termsOfService":"urn:tos",
        "contact":{},
        "license":{
            "name":"Apache 2.0",
            "url":"http://www.apache.org/licenses/LICENSE-2.0"
        }
    },
    "host":"localhost:8080",
    "basePath":"/",
    "tags":[
        {
            "name":"football-player-rest-controller",
            "description":"Football Player REST Controller"
        }
    ],
    "paths":{
        "/footballplayer":{
            "get":{
                "tags":[
                    "football-player-rest-controller"
                ],
                "summary":"findAll",
                "operationId":"findAllUsingGET",
                "produces":[
                    "application/json"
                ],
                "responses":{
                    "200":{
                        "description":"OK",
                        "schema":{
                            "$ref":"#/definitions/Iterable«FootballPlayer»"
                        }
                    },
                    "401":{
                        "description":"Unauthorized"
                    },
                    "403":{
                        "description":"Forbidden"
                    },
                    "404":{
                        "description":"Not Found"
                    }
                },
                "deprecated":false
            }
        },
        "/footballplayer/delete/{id}":{
            "delete":{
                "tags":[
                    "football-player-rest-controller"
                ],
                "summary":"delete",
                "operationId":"deleteUsingDELETE",
                "produces":[
                    "application/json"
                ],
                "parameters":[
                    {
                        "name":"id",
                        "in":"path",
                        "description":"id",
                        "required":true,
                        "type":"integer",
                        "format":"int32"
                    }
                ],
                "responses":{
                    "200":{
                        "description":"OK"
                    },
                    "204":{
                        "description":"No Content"
                    },
                    "401":{
                        "description":"Unauthorized"
                    },
                    "403":{
                        "description":"Forbidden"
                    }
                },
                "deprecated":false
            }
        }
    }
}
1.2 使用 Swagger UI

为获取可读、结构化的文档,可使用 Swagger UI。访问 http://localhost:8080/swagger-ui.html 即可查看生成的文档。

在使用前,可自定义控制台的头部部分,向用户解释 UI 中描述的 API 文档类型。在 SwaggerConfig 类中添加元数据 API 信息:

private ApiInfo metaData() {
    return new ApiInfoBuilder()
       .title("Spring Boot REST API")
       .description("\"Spring Boot REST API for Football Player Microservice\"")
       .version("1.0.0")
       .license("Apache License Version 2.0")
       .licenseUrl("https://www.apache.org/licenses/LICENSE-2.0\"")
       .contact(new Contact("Mauro Vocale",
            "https://github.com/Hands-on-MSA-JakartaEE",
            "mauro.vocale@gmail.com"))
       .build();
}

并在 SwaggerConfig 类的 api 方法的管道构建器中添加对 metaData 方法的调用。重新运行应用程序:

$ mvn spring-boot:run

此时可看到与构建和暴露 API 的组织相关的更详细信息。

1.3 自定义控制器类

为描述操作端点的目的,可使用 @ApiOperation 注解描述端点及其响应类型,示例如下:

@ApiOperation(value = "View all available football players", response = Iterable.class)
@ApiResponses(value = {
    @ApiResponse(code = 200, message = "Successfully retrieved list"),
    @ApiResponse(code = 404, message = "The resource you were trying to reach is not found")
})
@RequestMapping(method = RequestMethod.GET, produces = "application/json")
public Iterable<FootballPlayer> findAll() {
    return service.findAll();
}

@ApiOperation(value = "Add a football player")
@RequestMapping(value = "/save", method = RequestMethod.POST, produces = "application/json")
public FootballPlayer save(@RequestBody FootballPlayer entity) {
    return service.save(entity);
}

@ApiOperation(value = "Update a football player")
@RequestMapping(value = "/update/{id}", method = RequestMethod.PUT, produces = "application/json")
public FootballPlayer edit(@PathVariable Integer id, @RequestBody FootballPlayer entity) {
    return service.save(entity);
}

@ApiOperation(value = "Delete a football player")
@RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE, produces = "application/json")
public void delete(@PathVariable Integer id) {
    service.deleteById(id);
}

@ApiOperation(value = "Search a football player with an ID", response = FootballPlayer.class)
@RequestMapping(value = "/show/{id}", method = RequestMethod.GET, produces = "application/json")
public Optional<FootballPlayer> findById(@PathVariable Integer id) {
    return service.findById(id);
}

这样用户就能清楚了解微服务应用暴露的 API 及其目标。

1.4 测试 API

以“Search a football player with an ID” API(路径为 /footballplayer/show/{id} )为例,Swagger 会显示以下信息:
- HTTP 动词:GET
- API 简要描述
- 调用 API 所需的参数(此处为 Id)
- 不同类型的响应:JSON 对象表示和 HTTP 错误代码

测试 API 的步骤如下:
1. 点击“Try it out”按钮。
2. 插入 ID 参数并点击“Execute”按钮。
3. 查看 API 调用的响应。

2. 使用 Vert.x 构建微服务

Vert.x 是一个用于构建分布式和响应式系统的开源 Eclipse 工具包,基于响应式流原则,提供了编写轻量级和响应式应用程序的灵活方式。它采用异步和非阻塞的开发模型,基于事件循环处理请求,避免客户端长时间等待。

2.1 Maven 设置

Vert.x 与 Apache Maven 3.2 或更高版本兼容,为方便管理所有 Vert.x 依赖,可让 Maven POM 文件继承 vertx-stack-depchain BOM。以下是一个示例 pom.xml

<?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">
    <modelVersion>4.0.0</modelVersion>
    ...
    <properties>
        <java.version>1.8</java.version>
        <maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version>
        <maven-shade-plugin.version>2.4.3</maven-shade-plugin.version>
        <maven-surefire-plugin.version>2.21.0</maven-surefire-plugin.version>
        <exec-maven-plugin.version>1.5.0</exec-maven-plugin.version>
        <vertx.version>3.5.4</vertx.version>
        ...
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.vertx</groupId>
                <artifactId>vertx-stack-depchain</artifactId>
                <version>${vertx.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        ...
    </dependencies>
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.5.1</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>${maven-shade-plugin.version}</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <manifestEntries>
                                        <Main-Class>io.vertx.core.Launcher</Main-Class>
                                        <Main-Verticle>${main.verticle}</Main-Verticle>
                                    </manifestEntries>
                                </transformer>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                    <resource>
                                        META-INF/services/io.vertx.core.spi.VerticleFactory
                                    </resource>
                                </transformer>
                            </transformers>
                            <outputFile>
                                ${project.build.directory}/${project.artifactId}-${project.version}-fat.jar
                            </outputFile>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            ...
        </plugins>
    </build>
</project>

使用以下命令构建和打包应用程序:

$ mvn clean package
2.2 Gradle 设置

Gradle 是一个开源的构建自动化工具,可使用 Groovy 或 Kotlin DSL 编写脚本。要在 Gradle 项目中使用 Vert.x,可创建如下 Gradle 文件:

plugins {
    id 'java'
    id 'application'
    id 'com.github.johnrengelman.shadow' version '2.0.4'
}

ext {
    vertxVersion = '3.5.4'
    junitJupiterEngineVersion = '5.2.0'
}

repositories {
    mavenLocal()
    jcenter()
}

group = 'com.packtpub.vertx'
version = '1.0.0-SNAPSHOT'
sourceCompatibility = '1.8'
mainClassName = 'io.vertx.core.Launcher'
def mainVerticleName = 'com.packtpub.vertx.football-player-microservice.MainVerticle'
def watchForChange = 'src/**/*'
def doOnChange = './gradlew classes'

dependencies {
    implementation "io.vertx:vertx-core:$vertxVersion"
    implementation "io.vertx:vertx-config:$vertxVersion"
    ...
}

shadowJar {
    classifier = 'fat'
    manifest {
        attributes 'Main-Verticle': mainVerticleName
    }
    mergeServiceFiles {
        include 'META-INF/services/io.vertx.core.spi.VerticleFactory'
    }
}

...

run {
    args = ['run', mainVerticleName, "--redeploy=$watchForChange", "--launcher-class=$mainClassName", "--on-redeploy=$doOnChange"]
}

构建可执行 JAR 的命令:

$ ./gradlew shadowJar

运行可执行 JAR 的命令:

$ java -jar build/libs/gradle-my-vertx-project.jar

或者使用以下 Gradle 命令运行:

$ ./gradlew run
2.3 构建足球运动员微服务

要构建一个简单的足球运动员微服务,该服务处理足球运动员领域,暴露 CRUD API,并使用 PostgreSQL 数据库存储和检索信息。所需工具及安装信息如下:
| 工具 | 安装链接 |
| ---- | ---- |
| Apache Maven 3.5.4 | https://maven.apache.org/install.html |
| JDK 1.8.0_171 | 推荐 OpenJDK:http://openjdk.java.net/install/ |
| Vert.x 版本 3.5.4 | 后续描述使用说明 |
| Docker Community Edition 18.06.1 | https://docs.docker.com/install/ |

2.4 数据库安装和配置

安装 Docker 后,在新终端窗口中运行以下命令启动 PostgreSQL 容器:

$ docker run --name postgres_vertx -e POSTGRES_PASSWORD=postgresPwd -e POSTGRES_DB=football_players_registry -d -p 5532:5432 postgres

该命令会从 Docker 公共注册表中拉取最新的 PostgreSQL 版本,并下载运行容器所需的所有层。

验证容器是否启动:

$ docker ps -a

查看容器日志:

$ docker logs -f <容器 ID>

连接到容器:

$ docker exec -it <容器 ID> bash

登录 PostgreSQL:

$ psql -U postgres

查看数据库列表:

$ \l

连接到 football_players_registry 数据库:

$ \connect football_players_registry

创建 FOOTBALL_PLAYER 表:

CREATE TABLE FOOTBALL_PLAYER(
    ID SERIAL PRIMARY KEY NOT NULL,
    NAME VARCHAR(50) NOT NULL,
    SURNAME VARCHAR(50) NOT NULL,
    AGE INT NOT NULL,
    TEAM VARCHAR(50) NOT NULL,
    POSITION VARCHAR(50) NOT NULL,
    PRICE NUMERIC
);

查看表结构:

$ \d+ football_player

通过以上步骤,我们完成了使用 Spring Boot 和 Vert.x 构建微服务及相关 API 文档配置和数据库设置的过程。这些技术为开发高效、灵活的微服务应用提供了强大的支持。

3. 微服务构建流程总结与对比
3.1 Spring Boot 与 Swagger 集成流程总结

以下是使用 Spring Boot 和 Swagger 集成实现 API 文档化的详细步骤:
1. 添加依赖 :在 Maven 的 pom.xml 文件中添加 springfox-swagger2 springfox-swagger-ui 依赖。

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>
  1. 配置 Swagger :创建 SwaggerConfig 类,使用 @EnableSwagger2 注解启用 Swagger 支持,并配置 Docket bean。
@Configuration
@EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2).select()
           .apis(RequestHandlerSelectors.basePackage(
"com.packtpub.springboot.footballplayermicroservice.controller"))
           .paths(PathSelectors.any())
           .build();
    }
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
            .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
            .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}
  1. 自定义 API 信息 :在 SwaggerConfig 类中添加 metaData 方法,设置 API 的元数据信息。
private ApiInfo metaData() {
    return new ApiInfoBuilder()
       .title("Spring Boot REST API")
       .description("\"Spring Boot REST API for Football Player Microservice\"")
       .version("1.0.0")
       .license("Apache License Version 2.0")
       .licenseUrl("https://www.apache.org/licenses/LICENSE-2.0\"")
       .contact(new Contact("Mauro Vocale",
            "https://github.com/Hands-on-MSA-JakartaEE",
            "mauro.vocale@gmail.com"))
       .build();
}
  1. 自定义控制器类 :使用 @ApiOperation @ApiResponses 注解描述控制器方法的操作和响应。
@ApiOperation(value = "View all available football players", response = Iterable.class)
@ApiResponses(value = {
    @ApiResponse(code = 200, message = "Successfully retrieved list"),
    @ApiResponse(code = 404, message = "The resource you were trying to reach is not found")
})
@RequestMapping(method = RequestMethod.GET, produces = "application/json")
public Iterable<FootballPlayer> findAll() {
    return service.findAll();
}
  1. 运行和测试 :使用 mvn spring-boot:run 命令启动应用程序,访问 http://localhost:8080/v2/api-docs 获取 JSON 格式的 API 文档,访问 http://localhost:8080/swagger-ui.html 获取可视化的 API 文档。
3.2 Vert.x 微服务构建流程总结

使用 Vert.x 构建微服务的步骤如下:
1. Maven 设置 :让 Maven POM 文件继承 vertx-stack-depchain BOM,管理 Vert.x 依赖。

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-stack-depchain</artifactId>
            <version>${vertx.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
  1. Gradle 设置 :在 Gradle 项目中添加 Vert.x 依赖和相关配置。
plugins {
    id 'java'
    id 'application'
    id 'com.github.johnrengelman.shadow' version '2.0.4'
}

ext {
    vertxVersion = '3.5.4'
    junitJupiterEngineVersion = '5.2.0'
}

repositories {
    mavenLocal()
    jcenter()
}

group = 'com.packtpub.vertx'
version = '1.0.0-SNAPSHOT'
sourceCompatibility = '1.8'
mainClassName = 'io.vertx.core.Launcher'
def mainVerticleName = 'com.packtpub.vertx.football-player-microservice.MainVerticle'
def watchForChange = 'src/**/*'
def doOnChange = './gradlew classes'

dependencies {
    implementation "io.vertx:vertx-core:$vertxVersion"
    implementation "io.vertx:vertx-config:$vertxVersion"
    ...
}

shadowJar {
    classifier = 'fat'
    manifest {
        attributes 'Main-Verticle': mainVerticleName
    }
    mergeServiceFiles {
        include 'META-INF/services/io.vertx.core.spi.VerticleFactory'
    }
}

run {
    args = ['run', mainVerticleName, "--redeploy=$watchForChange", "--launcher-class=$mainClassName", "--on-redeploy=$doOnChange"]
}
  1. 数据库安装和配置 :使用 Docker 启动 PostgreSQL 容器,创建数据库和表。
$ docker run --name postgres_vertx -e POSTGRES_PASSWORD=postgresPwd -e POSTGRES_DB=football_players_registry -d -p 5532:5432 postgres
$ docker ps -a
$ docker logs -f <容器 ID>
$ docker exec -it <容器 ID> bash
$ psql -U postgres
$ \l
$ \connect football_players_registry
$ CREATE TABLE FOOTBALL_PLAYER(
    ID SERIAL PRIMARY KEY NOT NULL,
    NAME VARCHAR(50) NOT NULL,
    SURNAME VARCHAR(50) NOT NULL,
    AGE INT NOT NULL,
    TEAM VARCHAR(50) NOT NULL,
    POSITION VARCHAR(50) NOT NULL,
    PRICE NUMERIC
);
$ \d+ football_player
3.3 Spring Boot 与 Vert.x 的对比
特性 Spring Boot Vert.x
开发模型 基于 Spring 框架,提供了丰富的注解和组件,开发相对简单,适合快速开发。 异步和非阻塞的开发模型,基于事件循环,更适合高并发场景。
文档生成 需要借助 SpringFox 等第三方框架生成 API 文档。 未提及内置的 API 文档生成机制,可根据需求集成第三方工具。
数据库集成 支持多种数据库,通过 Spring Data 等模块简化数据库操作。 可与多种数据库集成,需要手动编写数据库操作代码。
生态系统 拥有庞大的生态系统,有大量的第三方库和工具可供使用。 生态系统相对较小,但提供了灵活的开发方式。
4. 总结与展望

通过本文的介绍,我们了解了如何使用 Spring Boot 和 Swagger 集成实现 API 文档化,以及如何使用 Vert.x 构建微服务。Spring Boot 适合快速开发和构建简单的微服务,而 Vert.x 则更适合处理高并发和异步场景。

在实际开发中,可以根据项目的需求和场景选择合适的技术栈。如果项目对开发效率和生态系统有较高的要求,可以选择 Spring Boot;如果项目需要处理大量的并发请求和异步操作,可以选择 Vert.x。

未来,随着微服务架构的不断发展,我们可以期待更多的工具和框架的出现,为微服务的开发和管理提供更好的支持。同时,我们也需要不断学习和掌握新的技术,以适应不断变化的开发需求。

流程图:Spring Boot 与 Swagger 集成流程

graph LR
    A[添加依赖] --> B[配置 Swagger]
    B --> C[自定义 API 信息]
    C --> D[自定义控制器类]
    D --> E[运行和测试]

流程图:Vert.x 微服务构建流程

graph LR
    A[Maven 设置] --> B[Gradle 设置]
    B --> C[数据库安装和配置]
内容概要:本文为《科技类企业品牌传播白皮书》,系统阐述了新闻媒体发稿、自媒体博主种草短视频矩阵覆盖三大核心传播策略,并结合“传声港”平台的AI工具资源整合能力,提出适配科技企业的品牌传播解决方案。文章深入分析科技企业传播的特殊性,包括受众圈层化、技术复杂性传播通俗性的矛盾、产品生命周期影响及2024-2025年传播新趋势,强调从“技术输出”向“价值引领”的战略升级。针对三种传播方式,分别从适用场景、操作流程、效果评估、成本效益、风险防控等方面提供详尽指南,并通过平台AI能力实现资源智能匹配、内容精准投放全链路效果追踪,最终构建“信任—种草—曝光”三位一体的传播闭环。; 适合人群:科技类企业品牌市场负责人、公关传播从业者、数字营销管理者及初创科技公司创始人;具备一定品牌传播基础,关注效果可量化AI工具赋能的专业人士。; 使用场景及目标:①制定科技产品全生命周期的品牌传播策略;②优化媒体发稿、KOL合作短视频运营的资源配置ROI;③借助AI平台实现传播内容的精准触达、效果监测风险控制;④提升品牌在技术可信度、用户信任市场影响力方面的综合竞争力。; 阅读建议:建议结合传声港平台的实际工具模块(如AI选媒、达人匹配、数据驾驶舱)进行对照阅读,重点关注各阶段的标准化流程数据指标基准,将理论策略平台实操深度融合,推动品牌传播从经验驱动转向数据工具双驱动。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值