Spring Boot 2.X(十五):集成 Swagger2 开发 API 文档(在线+离线)

简介: 前言 相信很多后端开发在项目中都会碰到要写 api 文档,不管是给前端、移动端等提供更好的对接,还是以后为了以后交接方便,都会要求写 api 文档。 而手写 api 文档的话有诸多痛点: 文档更新的时候,需要再次发送给对接人 接口太对,手写文档很难管理 接口返回的结果不明确 不能直接在线测试接口,通常需要使用工具,如 postman 等 Swagger 就很好的解决了这个问题。

前言

相信很多后端开发在项目中都会碰到要写 api 文档,不管是给前端、移动端等提供更好的对接,还是以后为了以后交接方便,都会要求写 api 文档。

而手写 api 文档的话有诸多痛点:

  • 文档更新的时候,需要再次发送给对接人
  • 接口太对,手写文档很难管理
  • 接口返回的结果不明确
  • 不能直接在线测试接口,通常需要使用工具,如 postman 等

Swagger 就很好的解决了这个问题。

Swagger 简介

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。

官网:https://swagger.io

Swagger 使用

1.相关依赖

<!--swagger2 -->
        <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>

2.Swagger 配置类

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket buildDocket() {
        return new Docket(DocumentationType.SWAGGER_2)
        .apiInfo(buildApiInf()) //将api的元信息设置为包含在json resourcelisting响应中
        //.host("127.0.0.1:8080") //设置ip和端口,或者域名
        .select()  //启动用于api选择的生成器
        //.apis(RequestHandlerSelectors.any())
        .apis(RequestHandlerSelectors.basePackage("cn.zwqh.springboot.controller"))//指定controller路径
        .paths(PathSelectors.any()).build();
    }

    private ApiInfo buildApiInf() {
        
        Contact contact=new Contact("朝雾轻寒","https://www.zwqh.top/","zwqh@clover1314.com");
        return new ApiInfoBuilder()
        .title("Swagger Demo Restful API Docs")//文档标题
        .description("Swagger 示例 Restful Api 文档")//文档描述
        .contact(contact)//联系人
        .version("1.0")//版本号
        //.license("")//更新此API的许可证信息
        //.licenseUrl("")//更新此API的许可证Url
        //.termsOfServiceUrl("")//更新服务条款URL
        .build();

    }
}

3.Spring MVC 相关配置

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
    /**
     * 静态资源配置(默认)
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");// 静态资源路径
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        super.addResourceHandlers(registry);
    }


}

如果不添加此静态资源配置会报错,找不到相关路径

4.Model 中使用 Swagger 注解

@ApiModel(value = "UserEntity", description = "用户对象")
public class UserEntity implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 5237730257103305078L;
    @ApiModelProperty(value ="用户id",name="id",dataType="Long",required = false,example = "1",hidden = false )
    private Long id;
    @ApiModelProperty(value ="用户名",name="userName",dataType="String",required = false,example = "关羽" )
    private String userName;
    @ApiModelProperty(value ="用户性别",name="userSex",dataType="String",required = false,example = "男" )
    private String userSex;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserSex() {
        return userSex;
    }

    public void setUserSex(String userSex) {
        this.userSex = userSex;
    }

}

5. Controller 中使用 Swagger 注解


@RestController
@RequestMapping("/api")
@Api(tags = { "接口分组1", "接口分组2" })
public class ApiController {

    @Autowired
    private UserDao userDao;

    @GetMapping("/getAllUser")
    @ApiOperation(value = "获取所有用户", notes = "", httpMethod = "GET", tags = "接口分组3")
    public List<UserEntity> getAll() {
        return userDao.getAll();
    }

    @GetMapping("/getUserById")
    @ApiOperation(value = "根据id获取用户", notes = "id必传", httpMethod = "GET")
    @ApiImplicitParam(name = "id", value = "用户id",example = "1", required = true, dataType = "long", paramType = "query")
    public UserEntity getOne(Long id) {
        return userDao.getOne(id);
    }

    @PostMapping("/getUserByNameAndSex")
    @ApiOperation(value = "根据name和sex获取用户", notes = "", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userName", value = "用户名", example = "关羽", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "userSex", value = "用户性别", example = "男", required = true, dataType = "string", paramType = "query") })
    public UserEntity getUserByNameAndSex(String userName, String userSex) {
        return userDao.getUserByNameAndSex(userName, userSex);
    }

    @PostMapping("/insertUser")
    @ApiOperation(value = "新增用户", notes = "传json,数据放body", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "body", value = "用户对象json", example = "{userName:'朝雾轻寒',userSex:'男'}", required = true) })
    public String insertUser(@RequestBody String body) {
        System.out.println(body);
        UserEntity user = JSON.parseObject(body, UserEntity.class);
        userDao.insertUser(user);
        return "{code:0,msg:'success'}";
    }

    @PostMapping("/updateUser")
    @ApiOperation(value = "修改用户", notes = "传json,数据放body", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "body", value = "用户对象json", example = "{id:23,userName:'朝雾轻寒',userSex:'女'}", required = true) })
    public String updateUser(@RequestBody String body) {
        System.out.println(body);
        UserEntity user = JSON.parseObject(body, UserEntity.class);
        userDao.updateUser(user);
        return "{code:0,msg:'success'}";
    }

    @PostMapping("/deleteUser")
    @ApiOperation(value = "删除用户", notes = "id必传", httpMethod = "POST")
    public String deleteUser(@ApiParam(name = "id", value = "用户id", required = true) Long id) {
        userDao.deleteUser(id);
        return "{code:0,msg:'success'}";
    }
}

5.测试

访问 http://127.0.0.1:8080/swagger-ui.html 进行接口在线测试

Swagger 常用注解

1.@Api

用于类,表示标识这个类是swagger的资源。属性如下:

  • tags 表示说明,tags如果有多个值,会生成多个列表
  • value 表示说明,可以使用tags替代

2.@ApiOperation

用于方法,表示一个http请求的操作。属性如下:

  • value 用于方法描述
  • notes 用于提示内容
  • tags 用于API文档控制的标记列表,视情况而用,可以进行独立分组

3.@ApiParam

用于方法、参数、字段说明;表示对参数的添加元数据。

  • name 参数名
  • value 参数说明
  • required 是否必填

4.@ApiModel

用于类,表示对类进行说明,用于参数用实体类接受。

  • value 对象名
  • description 描述

5.@ApiModelProperty

用于方法、字段,表示对model属性的说明或者数据操作更改。

  • value 字段说明
  • name 重写属性名
  • dataType 重写属性数据类型
  • required 是否必填
  • example 举例说明
  • hidden 隐藏

6.@ApiIgnore

用于类、方法、方法参数,表示这个方法或者类被忽略,不在swagger-ui.html上显示。

7.@ApiImplicitParam

用于方法,表示单独的请求参数。

  • name 参数名
  • value 参数说明
  • dataType 数据类型
  • paramType 参数类型
  • example 举例说明

8.@ApiImplicitParams

用于方法,包含多个 @ApiImplicitParam。

9.@ApiResponses @ApiResponse

用于类或者方法,描述操作的可能响应。

  • code 响应的HTTP状态代码
  • message 响应附带的可读消息

10.@ResponseHeader

用于方法,响应头设置。

  • name 响应头名称
  • description 头描述
  • response 默认响应类 void
  • responseContainer 参考ApiOperation中配置

Swagger 导出离线 api 文档

1.导出 AsciiDocs、Markdown、Confluence 格式文档

添加依赖

<!-- swagger2markup 相关依赖 -->
        <dependency>
            <groupId>io.github.swagger2markup</groupId>
            <artifactId>swagger2markup</artifactId>
            <version>1.3.3</version>
        </dependency>

转换工具类

public class SwaggerUtils {

    private static final String url = "http://127.0.0.1:8080/v2/api-docs";
    /**
     * 生成AsciiDocs格式文档
     * @throws MalformedURLException
     */
    public static void generateAsciiDocs() throws MalformedURLException {
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.ASCIIDOC)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema().build();

        Swagger2MarkupConverter.from(new URL(url))
                .withConfig(config)
                .build()
                .toFolder(Paths.get("./docs/asciidoc/generated"));
    }
    /**
     * 生成AsciiDocs格式文档,并汇总成一个文件
     * @throws MalformedURLException
     */
    public static void generateAsciiDocsToFile() throws MalformedURLException {
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.ASCIIDOC)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema()
                .build();

        Swagger2MarkupConverter.from(new URL(url))
                .withConfig(config)
                .build()
                .toFile(Paths.get("./docs/asciidoc/generated/all"));
    }
    
    /**
     * 生成Markdown格式文档
     * @throws MalformedURLException
     */
    public static void generateMarkdownDocs() throws MalformedURLException {
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.MARKDOWN)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema()
                .build();

        Swagger2MarkupConverter.from(new URL(url))
                .withConfig(config)
                .build()
                .toFolder(Paths.get("./docs/markdown/generated"));
    }
    /**
     * 生成Markdown格式文档,并汇总成一个文件
     * @throws MalformedURLException
     */
    public static void generateMarkdownDocsToFile() throws MalformedURLException {
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.MARKDOWN)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema()
                .build();

        Swagger2MarkupConverter.from(new URL(url))
                .withConfig(config)
                .build()
                .toFile(Paths.get("./docs/markdown/generated/all"));
    }
    
    /**
     * 生成Confluence格式文档
     * @throws MalformedURLException
     */
    public static void generateConfluenceDocs() throws MalformedURLException {
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.CONFLUENCE_MARKUP)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema()
                .build();

        Swagger2MarkupConverter.from(new URL(url))
                .withConfig(config)
                .build()
                .toFolder(Paths.get("./docs/confluence/generated"));
    }
    
    /**
     * 生成Confluence格式文档,并汇总成一个文件
     * @throws MalformedURLException
     */
    public static void generateConfluenceDocsToFile() throws MalformedURLException {
        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                .withMarkupLanguage(MarkupLanguage.CONFLUENCE_MARKUP)
                .withOutputLanguage(Language.ZH)
                .withPathsGroupedBy(GroupBy.TAGS)
                .withGeneratedExamples()
                .withoutInlineSchema()
                .build();

        Swagger2MarkupConverter.from(new URL(url))
                .withConfig(config)
                .build()
                .toFile(Paths.get("./docs/confluence/generated/all"));
    }
    
    
}

使用测试 Controller

@RestController
@RequestMapping("/export")
@ApiIgnore
public class ExportController {

    
    @RequestMapping("/ascii")
    public String exportAscii() throws MalformedURLException{
        SwaggerUtils.generateAsciiDocs();
        return "success";
    }
    
    @RequestMapping("/asciiToFile")
    public String asciiToFile() throws MalformedURLException{
        SwaggerUtils.generateAsciiDocsToFile();
        return "success";
    }
    
    @RequestMapping("/markdown")
    public String exportMarkdown() throws MalformedURLException{
        SwaggerUtils.generateMarkdownDocs();
        return "success";
    }
    
    @RequestMapping("/markdownToFile")
    public String exportMarkdownToFile() throws MalformedURLException{
        SwaggerUtils.generateMarkdownDocsToFile();
        return "success";
    }
    
    @RequestMapping("/confluence")
    public String confluence() throws MalformedURLException{
        SwaggerUtils.generateConfluenceDocs();
        return "success";
    }
    
    @RequestMapping("/confluenceToFile")
    public String confluenceToFile() throws MalformedURLException{
        SwaggerUtils.generateConfluenceDocsToFile();
        return "success";
    }
}

2.导出 html、pdf、xml 格式

添加依赖

<!--离线文档 -->
        <dependency>
            <groupId>org.springframework.restdocs</groupId>
            <artifactId>spring-restdocs-mockmvc</artifactId>
            <scope>test</scope>
        </dependency>
        <!--springfox-staticdocs 生成静态文档 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-staticdocs</artifactId>
            <version>2.6.1</version>
        </dependency>
<build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
                <plugin>
                    <groupId>io.github.swagger2markup</groupId>
                    <artifactId>swagger2markup-maven-plugin</artifactId>
                    <version>1.3.1</version>
                    <configuration>
                        <swaggerInput>http://127.0.0.1:8080/v2/api-docs</swaggerInput>
                        <outputDir>./docs/asciidoc/generated</outputDir>
                        <config>
                            <swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
                        </config>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.asciidoctor</groupId>
                    <artifactId>asciidoctor-maven-plugin</artifactId>
                    <version>1.5.3</version>
                    <!-- <version>2.0.0-RC.1</version> -->
                    <!-- Include Asciidoctor PDF for pdf generation -->
                    <dependencies>
                        <dependency>
                            <groupId>org.asciidoctor</groupId>
                            <artifactId>asciidoctorj-pdf</artifactId>
                            <version>1.5.0-alpha.10.1</version>
                        </dependency>
                        <dependency>
                            <groupId>org.jruby</groupId>
                            <artifactId>jruby-complete</artifactId>
                            <version>1.7.21</version>
                        </dependency>
                    </dependencies>
                    <configuration>
                        <sourceDirectory>./docs/asciidoc/generated</sourceDirectory>
                        <outputDirectory>./docs/asciidoc/html</outputDirectory> 
                        <backend>html</backend>
                        <!-- <outputDirectory>./docs/asciidoc/pdf</outputDirectory> 
                        <backend>pdf</backend> -->
                        <headerFooter>true</headerFooter> 
                        <doctype>book</doctype> 
                        <sourceHighlighter>coderay</sourceHighlighter>
                        <attributes>
                            <!-- 菜单栏在左边 -->
                            <toc>left</toc>
                            <!-- 多标题排列 -->
                            <toclevels>3</toclevels>
                            <!-- 自动打数字序号 -->
                            <sectnums>true</sectnums>
                        </attributes>
                    </configuration>                    
                </plugin>
            </plugins>
        </pluginManagement>

    </build>

可以修改此处 html 和 pdf,通过 mvn asciidoctor:process-asciidoc 可以导出相应格式文件

<outputDirectory>./docs/asciidoc/html</outputDirectory> 
                        <backend>html</backend>

执行 mvn asciidoctor:process-asciidoc 后再执行 mvn generate-resources,可在 targt/generated-docs 目录下生成 xml 格式文件。

完整代码

github

码云

非特殊说明,本文版权归 朝雾轻寒 所有,转载请注明出处.

原文标题:Spring Boot 2.X(十五):集成 Swagger2 开发 API 文档(在线+离线)

原文地址: https://www.zwqh.top/article/info/24

相关文章
|
4天前
|
数据采集 搜索推荐 API
小红书笔记详情 API 接口的开发、应用与收益
小红书(RED)作为国内领先的生活方式分享平台,汇聚了大量用户生成内容(UGC),尤其是“种草”笔记。小红书笔记详情API接口为开发者提供了获取笔记详细信息的强大工具,包括标题、内容、图片、点赞数等。通过注册开放平台账号、申请API权限并调用接口,开发者可以构建内容分析工具、笔记推荐系统、数据爬虫等应用,提升用户体验和运营效率,创造新的商业模式。本文详细介绍API的开发流程、应用场景及潜在收益,并附上Python代码示例。
119 61
|
5天前
|
供应链 搜索推荐 数据挖掘
阿里巴巴热卖商品推荐 API 接口的开发、应用与收益
阿里巴巴热卖商品推荐API为开发者提供了获取平台热卖商品信息的强大工具,涵盖商品标题、价格、销量等数据。通过注册开放平台账号、申请API权限并调用接口,开发者可构建热卖商品推荐系统、数据分析工具及供应链管理系统等应用,提升用户体验与运营效率,创造新的商业模式。该API采用RESTful风格,支持多种应用场景,助力电商从业者实现创新与增值。
37 7
|
7天前
|
供应链 数据挖掘 API
1688APP 原数据 API 接口的开发、应用与收益
1688作为阿里巴巴旗下的B2B平台,汇聚海量供应商和商品资源。其APP原数据API接口为开发者提供获取商品详细信息的强大工具,涵盖商品标题、价格、图片等。通过注册开放平台账号、申请API权限并调用接口,开发者可构建比价工具、供应链管理及自动化上架工具等应用,提升用户体验与运营效率,创造新的商业模式。示例代码展示了如何使用Python调用API并解析返回结果。
57 8
|
5天前
|
搜索推荐 数据挖掘 API
亚马逊详情 API 接口的开发、应用与收益
亚马逊详情API接口是亚马逊开放平台提供的强大工具,允许开发者编程获取商品的详细信息,如标题、价格、描述等。通过注册账号、申请权限并调用API,开发者可构建比价工具、推荐系统和数据分析工具等应用,提升用户体验与运营效率,创造新商业模式。本文详细介绍其开发流程、应用场景及潜在收益,并附代码示例。
24 6
|
前端开发 Java 测试技术
SpringBoot整合Swagger管理API接口详解
本文详细分析了如何在SpringBoot框架的项目中使用Swagger管理API接口,解决前后端分离项目中的接口文档难以有效管理的问题。在使用Swagger之前,介绍了Swagger相关的概念,分析了传统API文档管理的痛点,提出了Swagger工具使用的优点。详细说明了SpringBoot整合Swagger管理API接口文档的方式,主要介绍了Swagger在SpringBoot项目以及微服务架构项目中的应用。
690 0
SpringBoot整合Swagger管理API接口详解
|
8天前
|
JSON API 数据格式
微店商品列表接口(微店 API 系列)
微店商品列表接口是微店API系列的一部分,帮助开发者获取店铺中的商品信息。首先需注册微店开发者账号并完成实名认证,选择合适的开发工具如PyCharm或VS Code,并确保熟悉HTTP协议和JSON格式。该接口支持GET/POST请求,主要参数包括店铺ID、页码、每页数量和商品状态等。响应数据为JSON格式,包含商品详细信息及状态码。Python示例代码展示了如何调用此接口。应用场景包括商品管理系统集成、数据分析、多平台数据同步及商品展示推广。
|
2天前
|
存储 搜索推荐 API
淘宝拍立淘按图搜索API接口系列概述
淘宝拍立淘按图搜索API接口允许用户通过上传图片或拍摄实物来搜索相似或相同的商品。这一功能主要依赖于图像识别技术,系统会对上传的图片进行分析和处理,提取出商品的特征信息,并在淘宝的商品数据库中进行匹配搜索,最终返回与上传图片相似或相同的商品列表。
|
1天前
|
JSON 监控 API
速卖通商品列表接口(速卖通API系列)
速卖通提供商品列表API,开发者可通过关键词、类目、价格范围等条件获取商品标题、价格、销量等基本信息。使用前需注册开发者账号、创建应用并授权获取access_token。Python示例代码展示了如何调用接口,返回JSON格式数据,包含商品列表、总数、页码等信息。应用场景包括商品监控、数据分析和个性化推荐。注意API会更新,请参考官方文档。
|
2天前
|
API PHP 开发者
速卖通商品详情接口(速卖通API系列)
速卖通(AliExpress)是阿里巴巴旗下的跨境电商平台,提供丰富的商品数据。通过速卖通开放平台(AliExpress Open API),开发者可获取商品详情、订单管理等数据。主要功能包括商品搜索、商品详情、订单管理和数据报告。商品详情接口aliexpress.affiliate.productdetail.get用于获取商品标题、价格、图片等详细信息。开发者需注册账号并创建应用以获取App Key和App Secret,使用PHP等语言调用API。该接口支持多种请求参数和返回字段,方便集成到各类电商应用中。
|
2天前
|
缓存 Java 应用服务中间件
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
23 5

热门文章

最新文章