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"));
    }

}
相关推荐
azhou的代码园几秒前
基于JAVA+SpringBoot+Vue的制造装备物联及生产管理ERP系统
java·spring boot·制造
hanbarger1 分钟前
nosql,Redis,minio,elasticsearch
数据库·redis·nosql
波音彬要多做9 分钟前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法
Swift社区17 分钟前
Excel 列名称转换问题 Swift 解答
开发语言·excel·swift
一道微光21 分钟前
Mac的M2芯片运行lightgbm报错,其他python包可用,x86_x64架构运行
开发语言·python·macos
微服务 spring cloud23 分钟前
配置PostgreSQL用于集成测试的步骤
数据库·postgresql·集成测试
矛取矛求25 分钟前
QT的前景与互联网岗位发展
开发语言·qt
先睡25 分钟前
MySQL的架构设计和设计模式
数据库·mysql·设计模式
Leventure_轩先生25 分钟前
[WASAPI]从Qt MultipleMedia来看WASAPI
开发语言·qt