SpringBoot3中swagger无法使用

前言

springboot 3开始javax包改成了jakarta,而swagger-oas等包中依然使用的是javax,所以报错。另外springfox已经停止更新有段时间了,并且不支持OpenAPI 3标准,升级Springboot 3.0以后会有更多问题暴露出来。而SpringBoot 3只支持OpenAPI 3规范,因此Spring官网推荐了Springdoc

OpenApi 3的规范,目前针对Java的Spring Boot项目,主要支持的有2个版本:

  • springfox 3.0.0: 同时兼容OpenAPI 2以及OpenAPI 3,但是停更很久了
  • springdoc-openapi:兼容OpenAPI 3规范,更新速度频繁
  • Knife4j:在只有的OpenAPI 3规范中,底层基础框架选择springdoc-openapi项目,针对Springfox 3.0.0版本会放弃

一、Spring Boot 3.0整合Knife4j

以下是一些常见的Spring Boot版本及其对应的Knife4j版本兼容推荐:

参考文档:Knife4j文档

二、OpenApi 3注解的使用规范

Swagger 3(OpenApi 3) 注解与Swagger 2注解的对比

Swagger 2 OpenAPI 3 注解位置 作用
@Api @Tag(name = "接口类名",description = "接口类描述") Controller类 描述此controller的信息
@ApiOperation(value = "接口方法描述") @Operation(summary ="接口方法描述") Api端口方法 描述此Api的信息
@ApiImplicitParams @Parameters Api端口方法 描述参数信息
@ApiImplicitParam @Parameter(description="参数描述") Api方法的参数 描述参数信息
@ApiParam @Parameter(description="参数描述") Api方法的参数 -
@ApiIgnore @Parameter(hidden = true) 或 @Operation(hidden = true) 或 @Hidden - 用在各种地方,用于隐藏其Api
@ApiModel @Schema DTO类 用于Entity,以及Entity的属性上
@ApiModelProperty @Schema DTO属性 用于Entity,以及Entity的属性上
@ApiResponse(code = 404, message = "foo") @ApiResponse(responseCode = "404", description = "foo") Api方法上 描述响应数据

参考链接

三、使用步骤

  1. Spring Boot 3.0中使用knife4j
    在pom.xml文件中导入knife4j的依赖(本文springboot的版本是3.3.1)
pom 复制代码
<!-- Swagger3-knife4j依赖 -->
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
    <version>4.5.0</version>
</dependency>

其实现在就可以使用Knife4j了,暂不做其他配置,启动项目,浏览器输入http://localhost:端口号/doc.html查看接口文档

由于我们没有进行任何的属性配置,所以看到的页面是knife4j的初始页面

  1. 在application.yml中添加knife4j相关配置
yaml 复制代码
# springdoc-openapi项目配置
springdoc:
  swagger-ui:
    #自定义swagger前端请求路径,输入http:localhost:8080/swagger-ui.html会自动重定向到swagger页面
    path: /swagger-ui.html
    tags-sorter: alpha
    operations-sorter: alpha
  api-docs:
    path: /v3/api-docs    #swagger后端请求地址
    enabled: true   #是否开启文档功能
  group-configs:
    - group: 'default'   #分组名称
      paths-to-match: '/**'   #配置需要匹配的路径,默认为/**
      packages-to-scan: com.shkj.test    #配置要扫描包的路径,一般配置到启动类所在的包名
#packages-to-scan一定要记得修改-------------------------------------------------------------------

# knife4j的增强配置,不需要增强可以不配(建议配置一下)
knife4j:
  enable: true    #开启knife4j,无需添加@EnableKnife4j注解
  setting:
    language: zh_cn   #中文
    swagger-model-name: 实体类列表   #重命名SwaggerModel名称,默认
  #开启Swagger的Basic认证功能,默认是false
  basic:
    enable: true
    # Basic认证用户名
    username: ***
    # Basic认证密码
    password: ***

swagger3: 
  name: 盛海团队
  email: ***
  title: xxx
  description: xxx
  version: 1.0
  termsOfServiceUrl: xxx
  1. 创建config包,在其中新建一个配置类
    定义配置类WebMvcConfig,实现静态资源映射,将knife4j相关资源放行,保证生成的接口文档能够正常进行展示
java 复制代码
package com.blog.patrick.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * <p>
 * 配置类,注册web层相关组件
 * </p>
 *
 * @author Patrick
 * @since 2024-07-02
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    /**
     * 设置静态资源映射
     * @param registry 
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 添加静态资源映射规则
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        //配置 knife4j 的静态资源请求映射地址
        registry.addResourceHandler("/doc.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}
  1. 在config包下新建SwaggerProperties.java文件
    该文件主要读取swagger的属性参数,如:作者、版本等
java 复制代码
package com.shkj.test.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Data
@ConfigurationProperties(prefix = "swagger3")
public class SwaggerProperties {

    /**
     * 联系人的名称
     */
    private String name;


    /**
     * 联系人的邮箱
     */
    private String email;

    /**
     * API的标题
     */
    private String title;

    /**
     * API的描述
     */
    private String description;

    /**
     * API的版本号
     */
    private String version;

    /**
     * API的服务团队
     */
    private String termsOfServiceUrl;
}
  1. 在config包下新建Knife4jConfig.java文件
    该文件主要进行Knife4j的属性配置,如:作者、版本、接口分组等
java 复制代码
package com.shkj.test.config;

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.info.License;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Knife4j整合Swagger3 Api接口文档
 */
@Configuration
@EnableConfigurationProperties(SwaggerProperties.class)
public class Knife4jConfig {
    private SwaggerProperties swaggerProperties;

    public Knife4jConfig(SwaggerProperties swaggerProperties) {
        this.swaggerProperties = swaggerProperties;
    }

    @Bean
    public GroupedOpenApi adminApi() { // 创建了一个api接口的分组
        return GroupedOpenApi.builder()
                .group("admin-api") // 分组名称
                .pathsToMatch("/**") // 接口请求路径规则
                .build();
    }

    @Bean
    public OpenAPI openAPI(){
        return new OpenAPI()
                .info(new Info() // 基本信息配置
                        .title(swaggerProperties.getTitle()) // 标题
                        .description(swaggerProperties.getDescription()) // 描述Api接口文档的基本信息
                        .version(swaggerProperties.getVersion()) // 版本
                        .termsOfService(swaggerProperties.getTermsOfServiceUrl())
                        // 设置OpenAPI文档的联系信息,包括联系人姓名为"patrick",邮箱为"patrick@gmail.com"。
                        .contact(new Contact().name(swaggerProperties.getName()).email(swaggerProperties.getEmail()))
                        // 设置OpenAPI文档的许可证信息,包括许可证名称为"Apache 2.0",许可证URL为"http://springdoc.org"。
                        .license(new License().name("Apache 2.0").url("\"http://springdoc.org\""))
                );
    }
}
  1. entity实体类
    @Schema(description = " "): 标记实体类属性
java 复制代码
@Data
@TableName("t_user")
@Schema(description = "用户实体")
public class User implements Serializable {

    @Schema(description = "用户id")
    private Integer id;
    
    @Schema(description = "用户昵称")
    private String nickname;
    
    @Schema(description = "用户名")
    private String username;

    @Schema(description = "用户密码")
    private String password;

}
  1. controller控制层
    @Tag(name = " "): 标记接口类别
    @Operation(summary =" "): 标记接口操作
java 复制代码
@RestController
@Tag(name = "用户列表")
@RequestMapping("/user")
public class UserController {

    @Autowired
    UserService userService;

    /**
     * 用户列表
     * @return
     */
    @Operation(summary = "用户列表")
    @GetMapping("/list")
    public JsonResult list() {
        List<User> userList = userService.findAll();
        return JsonResult.success().data("userList", userList);
    }

}
java 复制代码
@RestController
@RequestMapping("body")
@Tag(name = "body参数")
public class BodyController {

   @Operation(summary = "普通body请求")
   @PostMapping("/body")
   public ResponseEntity<FileResp> body(@RequestBody FileResp fileResp){
       return ResponseEntity.ok(fileResp);
   }

   @Operation(summary = "普通body请求+Param+Header+Path")
   @Parameters({
           @Parameter(name = "id",description = "文件id",in = ParameterIn.PATH),
           @Parameter(name = "token",description = "请求token",required = true,in = ParameterIn.HEADER),
           @Parameter(name = "name",description = "文件名称",required = true,in=ParameterIn.QUERY)
   })
   @PostMapping("/bodyParamHeaderPath/{id}")
   public ResponseEntity<FileResp> bodyParamHeaderPath(@PathVariable("id") String id,@RequestHeader("token") String token, @RequestParam("name")String name,@RequestBody FileResp fileResp){
       fileResp.setName(fileResp.getName()+",receiveName:"+name+",token:"+token+",pathID:"+id);
       return ResponseEntity.ok(fileResp);
   }
}

8.重启项目并访问接口文档

访问http://localhost:端口号/doc.html,可以看到我们配置的属性已经在页面中显示出来了

四、Springboot启动类优化

每次都需要打开浏览器输入地址访问,对开发者很不友好,因此采取以下优化

java 复制代码
@Slf4j
@SpringBootApplication
public class BlogApplication {

    public static void main(String[] args) {
        ConfigurableEnvironment env = SpringApplication.run(BlogApplication.class, args).getEnvironment();

        log.info("\n----------------------------------------------------------\n\t" +
                        "Application: '{}' is running Success! \n\t" +
                        "Local URL: \thttp://localhost:{}\n\t" +
                        "Document:\thttp://localhost:{}/doc.html\n" +
                        "----------------------------------------------------------",
                env.getProperty("spring.application.name"),
                env.getProperty("server.port"),
                env.getProperty("server.port"));
    }

}
相关推荐
西岭千秋雪_9 分钟前
Redis性能优化
数据库·redis·笔记·学习·缓存·性能优化
chuanauc13 分钟前
Kubernets K8s 学习
java·学习·kubernetes
持梦远方22 分钟前
C 语言基础入门:基本数据类型与运算符详解
c语言·开发语言·c++
极限实验室22 分钟前
INFINI Labs 产品更新 | INFINI Console 1.29.6 发布 – 优化监控图表异常毛刺等
数据库·产品
先睡25 分钟前
优化MySQL查询
数据库·sql
一头生产的驴29 分钟前
java整合itext pdf实现自定义PDF文件格式导出
java·spring boot·pdf·itextpdf
YuTaoShao36 分钟前
【LeetCode 热题 100】73. 矩阵置零——(解法二)空间复杂度 O(1)
java·算法·leetcode·矩阵
zzywxc78739 分钟前
AI 正在深度重构软件开发的底层逻辑和全生命周期,从技术演进、流程重构和未来趋势三个维度进行系统性分析
java·大数据·开发语言·人工智能·spring
小张是铁粉42 分钟前
oracle的内存架构学习
数据库·学习·oracle·架构
专注API从业者1 小时前
构建淘宝评论监控系统:API 接口开发与实时数据采集教程
大数据·前端·数据库·oracle