欢迎来到信息岛!
adminAdmin  2024-11-04 16:51 信息岛 显示边栏 |   抢沙发  7 
文章评分 0 次,平均分 0.0

SpringBoot生成文档

先聊Swagger

图标

传说

  • 据说程序员最恨的两件事:一件是别人不写文档,另一件是自己写文档。
  • 可见文档真的是程序员生活中相爱相杀的存在。一方面对于使用者来说,一份全面、准确的文档简直就是旅行时的地图,烹饪时的菜谱,通关时的攻略。可以极大的提高对接的效率与尽可能的减少踩坑的概率。然而,一份全面而又准确的文档谈何容易。
  • 以接口文档来说,程序员不想写的原因跟写单元测试一样,很大程序上在于它完完全全是一个体力活,毫无创造性可言,枯燥并且乏味。更要紧的它不是一次性写完就可以了,还需要不停的维护,当你的业务变更进而导致代码变动,使得请求值、响应值、接口名称、字段注释、校验信息...都可能会修改。这个时候接口文档就要同步更新。否则它就会变的不准确了。如果经常对接接口的同学可能深有体会,这不光出现于公司内部,对接外部接口,或提供外部接口不时有这样的问题。
  • 天下苦接口文档久矣!突然有一天,一个头戴丝袜,气宇轩昂的大侠出现,改变了这个局面。他通过一套自创的注解,就可以自动生成一个在线的接口文档,而且随着代码的变更,它也会跟着变化。极大的减少了人们的工作量。为表达对于这位英雄的敬意,江湖人称--丝袜哥(Swagger音译)。

界面

一个典型的生成后 swagger 的接口文档页面如下图所示

img

不足

通过图片其实可以看出原生的界面、功能还是比较有限的

  • 首先没有一个登录界面,基本上在使用时没几个人改 swagger 的默认地址。所以别人发现你的接口地址很容易访问到你的 swagger 页面,这就带来了安全风险。
  • 另一点就是这个界面,怎么说呢,反正有人不喜欢。

术语过渡

官网

  • Swagger 官网 https://swagger.io/
  • OpenAPI 3 https://springdoc.org/

发展史

  • Swagger 1.x 阶段(2011-2014年)
  • Swagger 2.x 阶段(2014-2017年)
  • OpenAPI 阶段(2017-至今)(即 Swagger 3.x)

工具

  • SpringFox工具是基于 Swagger 2.x 基础上开发的
  • SpringDoc工具是基于OpenAPI 3.0 规范构建的

依赖

在Spring Boot框架中,Knife4j对于服务端将Spring的开放接口解析成Swagger2或者OpenAPI3规范的框架,也是依赖的第三方框架组件。说明如下:

  • Swagger2规范:依赖Springfox项目,该项目目前几乎处于停更状态,但很多老项目依然使用的是该规范,所以Knife4j在更新前端Ui的同时也继续保持了兼容
  • OpenAPI3规范:依赖Springdoc项目,更新发版频率非常快,建议开发者尽快迁移过来使用OpenAPI3规范,Knife4j后面的重心也会在这里。

再聊Knife4j

简介

  • Knife4j的前身是swagger-bootstrap-ui,前身swagger-bootstrap-ui是一个纯swagger-ui的ui皮肤项目
    一开始项目初衷是为了写一个增强版本的swagger的前端ui,但是随着项目的发展,面对越来越多的个性化需求,不得不编写后端Java代码以满足新的需求

  • 后期项目正式更名为Knife4j,取名Knife4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍,更名也是希望把她做成一个为Swagger接口文档服务的通用性解决方案

  • 现在的knife4j,是一个集Swagger2 和 OpenAPI3 为一体的增强解决方案。能够帮助开发者快速聚合使用OpenAPI规范.

官网

官方文档:https://doc.xiaominfo.com/

前置要求

提示

  • Spring Boot 3 只支持OpenAPI3规范,即支持SpringDoc工具
  • Knife4j提供的starter已经引用springdoc-openapi的jar,开发者需注意避免jar包冲突
  • JDK版本必须 >= 17
  • 详细Demo请参考knife4j-spring-boot3-demo

示例

首先,引用Knife4j的starter,Maven坐标如下:

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
    <version>4.5.0</version>
</dependency>

application.yml

# springdoc-openapi项目配置
springdoc:
  # swagger访问
  swagger-ui:
    path: /swagger-ui.html
    # alpha:按拼音升序
    tags-sorter: alpha
    operations-sorter: alpha
  # api-docs访问  
  api-docs:
      path: /v3/api-docs
  # 分组设置[也可以在Knife4j中设置,效果一样]
  group-configs:
    - group: 学生接口
      paths-to-match:
        - /stu2/**
      packages-to-scan:
        - net.wanho.controller
# knife4j的增强配置,不需要增强可以不配
knife4j:
  # 启用knife4j
  enable: true
  # basic认证
  basic:
    # 启用认证
    enable: true
    # 基本认证的用户名和密码
    username: admin
    password: admin

Knife4j更多增强配置明细,请移步文档进行查看

配置类

Kinfe4jConfig.java

@Configuration
public class Knife4jConfig {

    private String termsOfService = "1.服务提供方:本条款中的“服务提供方”指指定的公司或组织,提供API服务。<br>" +
            "2.用户:本条款中的“用户”指使用服务提供方提供的API服务的个人、公司或组织。<br>" +
            "3.授权:用户在遵守本条款的前提下,服务提供方授予用户使用其API服务的权利。<br>" +
            "4.使用限制:用户在使用API服务时,必须遵守以下限制:<br>" +
            "&nbsp;&nbsp;&nbsp;&nbsp;a.用户不得使用API服务进行非法活动或违反法律法规的行为;<br>" +
            "&nbsp;&nbsp;&nbsp;&nbsp;b.用户不得以任何方式干扰、破坏或损害API服务的正常运行;<br>" +
            "&nbsp;&nbsp;&nbsp;&nbsp;c.用户不得滥用API服务,包括但不限于超出使用限制、恶意攻击等行为;<br>" +
            "&nbsp;&nbsp;&nbsp;&nbsp;d.用户不得将API服务用于未经授权的商业用途。<br>" +
            "5.账户安全:用户在使用API服务时,必须保护其账户的安全性,包括但不限于保护密码和API密钥的安全。<br>" +
            "6.责任限制:服务提供方对于用户使用API服务所导致的任何直接或间接损失不承担责任,包括但不限于利润损失、数据损失等。<br>" +
            "7.服务变更和终止:服务提供方有权根据需要随时变更或终止API服务,用户在此不得要求服务提供方承担任何责任。<br>" +
            "8.知识产权:服务提供方保留所有API服务相关的知识产权。<br>9.隐私保护:服务提供方将根据相关法律法规保护用户的个人信息和数据隐私。<br>" +
            "10.争议解决:本条款的解释和适用以及由此产生的争议应适用服务提供方所在地的法律。<br>" +
            "11.其他条款:本条款中的任何条款无效或不可执行时,不影响其他条款的效力。<br>" +
            "12.条款变更:服务提供方有权随时修改本条款,并通过适当的方式向用户通知。<br>" +
            "📢请用户在使用API服务之前仔细阅读并理解本条款,如用户不同意本条款的任何内容,请勿使用API服务。<br>" +
            "⚠️用户一旦使用API服务,即视为用户已接受本条款的全部内容。";

    // 分组信息,与application.yml中的springdoc.group-configs的配置一样 
    @Bean
    public GroupedOpenApi sysApi() {
        return GroupedOpenApi.builder()
                .group("系统模块")
                .packagesToScan("net.wanho.controller")
                .addOpenApiMethodFilter(method -> method.isAnnotationPresent(io.swagger.v3.oas.annotations.Operation.class))
                .build();
    }

    // OpenAPI的基本信息
    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                .info(new Info()
                        .title("万里商城服务接口文档")
                        .description("万里商城服务接口文档描述")
                        .version("1.0.0")
                        .termsOfService(termsOfService)
                        .contact(new Contact().name("zj").email("zj@wanho.net"))
                        .license(new License().name("2024年度内部绝密文档,请勿外传").url("https://www.wanho.net/")
                        ));
    }
}

访问

knife4j文档访问地址 : http://localhost:8080/swagger-ui

image-20241104164343566

swagger文档访问地址 : http://localhost:8080/swagger-ui

image-20241104164422980

api-docs文档访问地址 : http://localhost:8080/v3/api-docs

image-20241104164606945

常用注解:

@Tag: 添加在controller类上,可以指定该 controller 模块的名称。

@Operation: 该注解放在 controller 类下的请求方法上,可以指定该请求/方法的作用。

@Parameters和@Parameter:用于对请求方法的参数列表中那些未封装的参数进行说明。如果有多个参数时需要使用@Parameters包起来。

@Schema:作用在实体类及其属性上,用于描述实体及其属性。

StudentController.java

@RestController
@RequestMapping("/stu")
@RequiredArgsConstructor
@Tag(name = "学生接口")
public class StudentController {

    private final  StudentServiceI studentService;

    /**
     * 分页按条件查询学生
     * @return
     */
    @GetMapping("/findByPage")
    @Operation(summary = "分页按条件查询学生")
    public AjaxResult findByPage(@Parameter(description = "当前页码") int pageNum,@Parameter(description = "每页记录数") int pageSize, Student stu) {
        return AjaxResult.success(studentService.findByPage(pageNum, pageSize, stu)) ;
    }

    @GetMapping("/{id}")
    @Operation(summary = "根据ID查询学生")
    public AjaxResult getById(@Parameter(description = "学生ID") @PathVariable int id) {
        return AjaxResult.success(studentService.getById(id)) ;
    }
}

Student.java

@Data
@AllArgsConstructor
@RequiredArgsConstructor
@Schema(description = "学生信息")
public class Student {
    @Schema(description = "学生ID")
    private  Long id;
    @Schema(description = "学生姓名")
    private  String name;
    @Schema(description = "学生年龄")
    private Integer age;
    @Schema(description = "学生性别")
    private String gender;
    @Schema(description = "学生地址")
    private String address;
    @Schema(description = "学生生日")
    private Date birth;
}

@Tag

添加在controller类上,可以指定该 controller 模块的名称。knife4j默认根据字母排序,加上序号后会根据序号排序。

@RestController
@RequestMapping("/stu")
@RequiredArgsConstructor
@Tag(name = "学生接口")
public class StudentController {

}

image-20241104163750884

@Operation

该注解放在 controller 类下的请求方法上,可以指定该请求/方法的作用。添加后可以在对应的 控制层模块下查看该请求。

@GetMapping("/findByPage")
@Operation(summary = "分页按条件查询学生")
public AjaxResult findByPage(@Parameter(description = "当前页码") int pageNum,@Parameter(description = "每页记录数") int pageSize, Student stu) {
    return AjaxResult.success(studentService.findByPage(pageNum, pageSize, stu)) ;
}

image-20241104163855591

@Parameters和@Parameter

用于对请求方法的参数列表中那些未封装的参数进行说明。如果有多个参数时需要使用@Parameters包起来。

@GetMapping("/findByPage")
@Operation(summary = "分页按条件查询学生")
@Parameters({
    @Parameter(name = "pageNum", description = "当前页码", required = true),
    @Parameter(name = "pageSize", description = "每页记录数", required = true)
})
public AjaxResult findByPage(int pageNum, int pageSize, Student stu) {
    return AjaxResult.success(studentService.findByPage(pageNum, pageSize, stu));
}

@GetMapping("/findByPage")
@Operation(summary = "分页按条件查询学生")
public AjaxResult findByPage(@Parameter(description = "当前页码") int pageNum,@Parameter(description = "每页记录数") int pageSize, Student stu) {
    return AjaxResult.success(studentService.findByPage(pageNum, pageSize, stu)) ;
}

image-20241104164131832

@Schema

作用在实体类及其属性上,用于描述实体及其属性。

requiredMode = Schema.RequiredMode.REQUIRED:表示该参数是必须的。

@Data
@AllArgsConstructor
@RequiredArgsConstructor
@Schema(description = "学生信息")
public class Student {
    @Schema(description = "学生ID")
    private  Long id;
    @Schema(description = "学生姓名")
    private  String name;
    @Schema(description = "学生年龄")
    private Integer age;
    @Schema(description = "学生性别")
    private String gender;
    @Schema(description = "学生地址")
    private String address;
    @Schema(description = "学生生日")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date birth;
}

默认值是类名,但可以使用@Schema注解的name属性修改默认值

image-20241104164209001

「点点赞赏,手留余香」

还没有人赞赏,快来当第一个赞赏的人吧!

admin给Admin打赏
×
予人玫瑰,手有余香
  • 2
  • 5
  • 10
  • 20
  • 50
2
支付

声明:本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

admin
Admin 关注:0    粉丝:0
这个人很懒,什么都没写

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享