Spring Boot 集成 SpringDoc OpenAPI(Swagger)实战:从配置到接口文档落地

Swagger 是一套用于构建、描述和调用 RESTful API 的规范和工具集。核心优势包括:

  • 自动生成 API 文档,减少手动编写成本;
  • 支持在线调试接口,无需依赖 Postman 等工具;
  • 可配置性强,能根据需求定制文档信息;
  • 与 Spring 生态无缝集成,上手简单。
  • 页面展示:

一、环境准备

1. 核心依赖

本文使用 springdoc-openapi-ui(而非 Springfox),适配 Spring Boot 2.x 版本,直接引入用户提供的依赖:

XML 复制代码
<!-- SpringDoc OpenAPI 核心依赖(含 Swagger UI) -->
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.6.14</version>
</dependency>

<!-- Spring Security(用于 Swagger 页面认证,可选但推荐) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. 关键版本适配

  • Spring Boot 版本:2.x(本文基于 2.6.x 验证)
  • SpringDoc 版本:1.6.14(兼容 Spring Boot 2.x,支持 OpenAPI 3.0)
  • JDK 版本:1.8+

二、核心配置:从文件到代码

SpringDoc 的配置分为「配置文件(yaml/properties)」和「Java 配置类」两部分,需配合使用才能实现完整功能。

1. 配置文件:自定义 Swagger 行为

application.yml 中添加用户提供的 SpringDoc 配置,每一项都附带详细说明,可直接复制使用:

XML 复制代码
# SpringDoc OpenAPI 核心配置
springdoc:
  # Swagger UI 页面配置
  swagger-ui:
    path: /swagger-ui.html  # Swagger UI 访问路径(自定义,如:http://ip:port/上下文/swagger-ui.html)
    tags-sorter: alpha      # 接口标签(Tag)排序:alpha=字母序,method=定义顺序
    operations-sorter: alpha # 同标签下接口排序:alpha=路径字母序,method=HTTP方法序(GET→POST)
  # API 文档数据接口(Swagger UI 数据源,返回 JSON)
  api-docs:
    path: /v3/api-docs  # 文档数据路径(如:http://ip:port/上下文/v3/api-docs)
  # 接口分组配置(按包/路径筛选接口,避免无关接口混入文档)
  group-configs:
    - group: default          # 分组名称(Swagger UI 顶部可切换,默认一个分组)
      paths-to-match: /**     # 匹配所有路径的接口(可缩小范围,如:/personInfo/**)
      packages-to-scan: com.cetc.ydyl.controller # 扫描的控制器包(只解析该包下的接口)

2. Java 配置类一:OpenAPI 文档元信息(OpenApiConfig)

该类用于定义 Swagger 文档的「基础信息」和「安全方案声明」,告诉文档 "需要什么认证",代码如下:

java 复制代码
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.Components;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Configuration
@Profile("dev")  # 仅在 dev 环境生效(生产环境建议关闭 Swagger)
public class OpenApiConfig {

    /**
     * 配置 OpenAPI 文档元信息 + 安全方案
     */
    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
                // 1. 文档基础信息(显示在 Swagger UI 顶部)
                .info(new Info()
                        .title("API文档")  // 文档标题
                        .version("1.0")   // 文档版本
                        .description("项目API文档说明")  // 文档描述(可写接口规范、注意事项)
                        .contact(new Contact().name("ydyl")))  // 联系人(维护者信息)
                // 2. 全局安全需求:声明所有接口需通过 "basicAuth" 认证(可按需关闭)
                .addSecurityItem(new SecurityRequirement().addList("basicAuth"))
                // 3. 定义安全方案:此处为 HTTP Basic 认证(账号密码登录)
                .components(new Components()
                        .addSecuritySchemes("basicAuth",  // 安全方案名称(需与上方 SecurityRequirement 对应)
                                new SecurityScheme()
                                        .type(SecurityScheme.Type.HTTP)  // 认证类型:HTTP
                                        .scheme("basic")));  // 认证方式:basic(基础认证)
    }
}

3. Java 配置类二:Swagger 安全控制(OpenAPISecurityConfig)

该类基于 Spring Security 实现「实际的认证逻辑」,控制哪些路径需要登录、用什么账号登录,代码如下:

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityConfigurerAdapter;
import org.springframework.security.web.SecurityFilterChain;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.security.SecurityScheme;

@Configuration
@EnableWebSecurity  // 启用 Spring Security 安全控制
@Profile("dev")     // 仅 dev 环境生效
// 声明 JWT 安全方案(当前项目未使用,属于冗余配置,可删除)
@SecurityScheme(
        name = "bearerAuth",
        type = SecuritySchemeType.HTTP,
        scheme = "bearer",
        bearerFormat = "JWT"
)
public class OpenAPISecurityConfig {

    /**
     * 配置安全规则:控制路径访问权限
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                // 1. Swagger 相关路径必须认证(避免文档暴露)
                .antMatchers("/swagger-ui.html", "/v3/api-docs/**").authenticated()
                // 2. 其他业务接口允许匿名访问(可根据项目调整为 authenticated())
                .anyRequest().permitAll()
                .and()
                // 3. 启用 HTTP Basic 认证(浏览器弹出账号密码登录框)
                .httpBasic()
                .and()
                // 4. 关闭 CSRF(开发环境简化操作,生产环境需评估)
                .csrf().disable();

        return http.build();
    }

    /**
     * 配置认证用户:内存存储(生产环境建议用数据库存储)
     */
    @Bean
    public UserDetailsService userDetailsService() {
        // 密码编码器(自动适配 BCrypt 等加密方式)
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        // 定义用户:用户名=ydyl,密码=123456
        UserDetails user = User.withUsername("ydyl")
                .password(encoder.encode("123456"))
                .roles("API_DOCS")  // 角色(可用于细粒度权限控制)
                .build();

        // 内存用户管理器(仅开发环境测试用)
        return new InMemoryUserDetailsManager(user);
    }
}

注意 :类上的 @SecurityScheme(bearerAuth) 是冗余配置(当前用 Basic 认证,未用 JWT),可删除以精简代码。

三、接口与实体类:用注解完善文档

Swagger 文档的核心是「接口信息」和「参数 / 返回值说明」,需通过注解在控制器和实体类中添加描述,以用户提供的 PersonInfoControllerPersonInfo 为例。

1. 控制器注解:定义接口信息(PersonInfoController)

控制器类用 @Tag 分组,接口方法用 @Operation 描述功能,代码如下:

java 复制代码
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Validated;
import javax.servlet.http.HttpServletResponse;

@RestController
@RequestMapping("/personInfo")  // 接口基础路径
@Tag(name = "人员-系统人物库")  // 接口标签(Swagger UI 左侧分组名称)
public class PersonInfoController {

    private final IPersonInfoService onlyService;

    // 构造器注入服务(推荐方式,避免字段注入)
    public PersonInfoController(IPersonInfoService onlyService) {
        this.onlyService = onlyService;
    }

    /**
     * 新增或修改人员信息
     */
    @PostMapping("/addOrUpdate")
    @Operation(summary = "新增或修改", description = "根据传入的人员信息,不存在则新增,存在则更新")
    public BaseResponse<String> addOrUpdate(
            @Validated @RequestBody PersonInfo personInfo  // @Validated 开启参数校验
    ) {
        String result = onlyService.addOrUpdate(personInfo);
        return BaseResponse.success(result);
    }

    /**
     * 根据 ID 删除人员
     */
    @PostMapping("/deleteById")
    @Operation(summary = "根据ID删除", description = "传入人员ID,逻辑删除对应人员信息")
    public BaseResponse<String> deleteById(
            @Validated @RequestBody PersonUpdateVo paramVo
    ) {
        String result = onlyService.deleteById(paramVo.getId());
        return BaseResponse.success(result);
    }

    /**
     * 分页查询人员信息
     */
    @PostMapping("/searchPage")
    @Operation(summary = "分页查询", description = "传入查询条件(如手机号、邮箱),返回分页人员列表")
    public BaseResponse<Page<PersonInfo>> searchPage(
            @RequestBody PersonOnlyParamVo paramVo
    ) {
        Page<PersonInfo> result = onlyService.searchPage(paramVo);
        return BaseResponse.success(result);
    }

    /**
     * 导出人员数据
     */
    @PostMapping("/export")
    @Operation(summary = "导出数据", description = "每天最多导出10次,每次最多20条数据,返回Excel文件")
    public BaseResponse<?> exportPerson(
            @RequestBody ExportLimitDoc exportLimitDoc,
            HttpServletResponse response  // 用于输出Excel流
    ) {
        onlyService.exportPerson(exportLimitDoc, response);
        return BaseResponse.success();
    }
}

2. 实体类注解:定义参数 / 返回值说明(PersonInfo)

实体类用 @Schema 描述类和字段含义,Swagger UI 会自动显示这些说明,代码如下:

java 复制代码
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.annotations.MultiField;
import org.springframework.data.elasticsearch.annotations.InnerField;

@Data  // Lombok 注解,自动生成 getter/setter
@Schema(description = "人物信息实体类")  // 实体类描述(Swagger 中显示)
@Document(indexName = PersonInfo.INDEXNAME, replicas = 0, shards = 1)  // Elasticsearch 注解(非 Swagger 相关,无需修改)
public class PersonInfo extends ElasticsearchEntity {

    public static final String INDEXNAME = "person_info";
    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";

    @Schema(description = "指纹")  // 字段描述
    @MultiField(
            mainField = @Field(type = FieldType.Text),
            otherFields = {@InnerField(suffix = "keyword", type = FieldType.Keyword)}
    )
    private String fingerprint;

    @Schema(description = "虹膜")
    @MultiField(
            mainField = @Field(type = FieldType.Text),
            otherFields = {@InnerField(suffix = "keyword", type = FieldType.Keyword)}
    )
    private String iris;

    @Schema(description = "其他生物特征")
    @MultiField(
            mainField = @Field(type = FieldType.Text),
            otherFields = {@InnerField(suffix = "keyword", type = FieldType.Keyword)}
    )
    private String otherBiometricFeatures;

    @Schema(description = "手机号码")
    @MultiField(
            mainField = @Field(type = FieldType.Text),
            otherFields = {@InnerField(suffix = "keyword", type = FieldType.Keyword)}
    )
    private String phoneNumber;

    @Schema(description = "邮箱账号")
    @MultiField(
            mainField = @Field(type = FieldType.Text),
            otherFields = {@InnerField(suffix = "keyword", type = FieldType.Keyword)}
    )
    private String email;
}

四、访问与测试:验证文档效果

1. 确定访问路径

结合配置文件中的 server.portserver.servlet.context-pathspringdoc.swagger-ui.path,最终访问路径为:

java 复制代码
http://localhost:9005/ydyl/swagger-ui.html
  • localhost:项目部署地址(若部署在服务器,替换为服务器 IP)
  • 9005:用户指定端口
  • ydyl:应用上下文路径
  • swagger-ui.html:Swagger UI 自定义路径

2. 登录认证

访问上述路径后,浏览器会弹出「基础认证」对话框,输入配置的账号密码:

  • 用户名:ydyl
  • 密码:123456(原始密码,非加密后的字符串)

3. 文档使用

登录成功后,即可看到完整的 Swagger 文档界面:

  1. 左侧标签 :显示 人员-系统人物库(对应 @Tag 注解),点击可展开所有接口;
  2. 接口详情 :每个接口显示 summarydescription(对应 @Operation 注解),可查看请求参数(自动显示 PersonInfo 字段的 @Schema 说明);
  3. 在线调试:点击接口右侧的「Try it out」,输入参数后点击「Execute」,即可直接调用接口并查看返回结果。
相关推荐
不是株35 分钟前
JavaWeb(后端进阶)
java·开发语言·后端
IT_陈寒36 分钟前
5个Python 3.12新特性让你的代码效率提升50%,第3个太实用了!
前端·人工智能·后端
Victor3561 小时前
Redis(109)Redis的Pipeline如何使用?
后端
NPE~1 小时前
[手写系列]Go手写db — — 第七版(实现Disk存储引擎、Docker化支持)
数据库·后端·docker·golang·教程·手写数据库
Victor3561 小时前
Redis(108)Redis的事务机制如何实现?
后端
JaguarJack1 小时前
PHP 开发中 你可能不知道的非常好用 PhpStorm 插件
后端·php
9ilk1 小时前
【基于one-loop-per-thread的高并发服务器】--- 前置技术
运维·服务器·c++·笔记·后端·中间件
编程火箭车1 小时前
【Java SE 基础学习打卡】02 计算机硬件与软件
java·电脑选购·计算机基础·编程入门·计算机硬件·软件系统·编程学习路线
Felix_XXXXL2 小时前
IDEA + Spring Boot 的三种热加载方案
java·后端