Spring Boot之整合Swagger

作者: 狄仁杰666 | 来源:发表于2020-07-17 22:01 被阅读0次

    前言

    经过之前文章的学习,我们学会了:

    有了这些基础知识,可以说,我们已经拥有Spring Boot项目开发的入门基础了。

    现实场景中,我们往往需要知道API的文档,才能用于测试、交付等,土一点的做法是开发人员编写API文档,如Wiki、Word、其他在线文档等,实际上,有很多开源资源帮我们从技术上实现了API规格的文档化,而Swagger是Spring Boot生态中的佼佼者,也是官方推荐的。

    Swagger的主要优点有:

    1. 免费开源,并且官网提供了丰富的工具和文档介绍;
    2. 通过代码添加注解,自动生成API文档;
    3. 提供在线API文档,API文档随API变化而自动同步更新;
    4. 可开启UI界面,界面美观、清晰;
    5. UI界面支持在线测试API;
    6. 支持多种语言(Java,PHP...);
    7. 采用OpenAPI 规范;
      (OpenAPI定义了RESTful APIs的编写规范。规范中指定了一套模式/模型。这套规范是Swagger为各种编程语言编写的服务提供接口文档奠定了基础。)
    8. ...

    那么,我们今天就一起来学习:

    Spring Boot中通过Swagger来做API文档。

    本文使用的项目代码,是基于上一篇文章使用的Spring Boot项目:
    Spring Boot数据库交互之Mybatis

    主要步骤

    1. 添加依赖;
    2. 创建config包;
    3. 创建配置类;
    4. 编写配置类;
    5. 修饰Controller;
    6. 修饰项目启动类;
    7. 启动项目、使用Swagger;

    1.添加依赖;

    //在pom.xml文件中的dependencies节点内添加以下内容:
    <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.创建config包;

    项目根目录下创建config包:

    config包

    3.创建配置类;

    配置类

    4.编写配置类;

    1. 编写Swagger配置类;

    该步骤的意义:

    配置Swagger要扫描API的Controller位置、要显示的API path的样式、初始化的Swagger页面的一些基础信息(见apiInfo()方法);

    • 特别注意,要使用@EnableSwagger2注解;

    • 设置生成API接口信息的被扫描Controller路径,常见写法:

    //生成指定包下的所有API接口信息
    RequestHandlerSelectors.basePackage("com.mycompany.sample.controller")
    //生成所有API接口
    RequestHandlerSelectors.any()
    //所有API接口都不生成
    RequestHandlerSelectors.none()
    //只生成被@Api 这个注解注解过的类接口
    RequestHandlerSelectors.withClassAnnotation(Api.class)
    //只生成被@ApiOperation 这个注解注解过的API接口
    RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)
    
    • 设置API路径筛选规则,常见写法有:

    //所有API均允许生成
    PathSelectors.any()
    //所有API均不允许生成
    PathSelectors.none()
    //正则表达式匹配,匹配上则允许生成,如包含getLead的API:
    PathSelectors.regex("^(?!getLead).*$")
    //只扫描指定的路径下的请求,如只想扫描getLead API路径下的:
    //getLead为API path的一部分
    PathSelectors.ant("/getLead/**")
    

    代码如下:

    package com.mycompany.sample.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.builders.ApiInfoBuilder;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.service.Contact;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
    
    /**
     * @author : dylanz
     * @since : 07/17/2020
     **/
    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {
        @Bean
        public Docket api() {//名字不限
            return new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo())
                    .enable(true)
                    .select()
                    .apis(RequestHandlerSelectors.basePackage("com.mycompany.sample.controller"))
                    .paths(PathSelectors.any())
                    .build();
        }
    
        private ApiInfo apiInfo() {//名字不限
            Contact contact = new Contact("Dylan Zhang", "https://www.jianshu.com/u/56578a39a99a", "997604787@qq.com");
            return new ApiInfoBuilder()
                    .title("Lead API")
                    .contact(contact)
                    .description("Lead related operations")
                    .termsOfServiceUrl("http://127.0.0.1:8080/getLead/10130546")
                    .version("1.0")
                    .build();
        }
    }
    
    • 如果想关闭Swagger UI:

    enable设置为:.enable(false),之后访问Swagger UI时就会如下:

    关闭Swagger UI

    2. 编写WebMvcConfig配置类;

    该步骤的意义:覆盖、重写项目配置的(如有)、默认的静态资源路径,这样才能读取到Swagger jar包内的静态文件(html、css文件等);

    package com.mycompany.sample.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
    
    import javax.annotation.PostConstruct;
    
    /**
     * @author : dylanz
     * @since : 07/17/2020
     **/
    @Configuration
    public class WebMvcConfig extends WebMvcConfigurationSupport {
        @PostConstruct
        public void init() {
            System.out.println("Init in WebMvcConfig...");
        }
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/**")
                    .addResourceLocations("classpath:/statics/");
            registry.addResourceHandler("swagger-ui.html")
                    .addResourceLocations("classpath:/META-INF/resources/");
            registry.addResourceHandler("/webjars/**")
                    .addResourceLocations("classpath:/META-INF/resources/webjars/");
        }
    }
    

    5.修饰Controller;

    package com.mycompany.sample.controller;
    
    import com.mycompany.sample.domain.Lead;
    import com.mycompany.sample.service.LeadService;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiImplicitParams;
    import io.swagger.annotations.ApiOperation;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    /**
     * @author : dylanz
     * @since : 07/07/2020
     **/
    @RestController
    @Api
    public class LeadController {
        @Autowired
        private LeadService leadService;
    
        @GetMapping("/getLead/{leadId}")
        @ResponseBody
        @ApiOperation(value = "get lead by leadId", httpMethod = "GET")
        @ApiImplicitParams(
                {@ApiImplicitParam(name = "leadId", value = "leadId", required = true, paramType = "path", dataType = "Long", example = "10130546")}
        )
        public Lead getLead(@PathVariable(name = "leadId") Long leadId) {
            return leadService.getLeadByLeadId(leadId);
        }
    }
    
    1. @Api 注解用来描述该服务的信息,如果不使用则显示类名称;
    2. @ApiOperation 注解用于描述接口信息;
    3. @ApiParam,@ApiImplicitParam,@ApiImplicitParams 注解用于描述接口的参数;
    4. @ApiResponse,@ApiResponses 注解用于描述API返回的信息,不使用会使用默认的、根据接口情况自动生成的描述信息,可在此处自定义错误返回信息,如:

    @ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),

    5. @ApiVersion 注解用于描述接口的版本信息;

    6.修饰项目启动类;

    特别注意,只增加使用@EnableSwagger2注解即可;

    package com.mycompany.sample;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
    
    /**
     * @author : dylanz
     * @since : 07/07/2020
     **/
    @SpringBootApplication
    @EnableSwagger2
    @MapperScan(basePackages = "com.mycompany.sample.dao")
    public class App {
        public static void main(String[] args) {
            SpringApplication.run(App.class, args);
        }
    }
    

    7.启动项目、使用Swagger;

    • 启动项目;

    启动项目
    • 访问Swagger UI;

    Swagger UI HTML站点:http://localhost:8080/swagger-ui.html

    HTML站点

    页面组成:

    1. 标题;
    2. API文档JSON入口:http://localhost:8080/v2/api-docs
    3. 作者信息;
    4. API文档主体;
    5. 等。

    打开折叠的API列表,我们能看到API的规格:

    API规格

    以及API使用的实体对象信息:

    实体对象信息

    我们还可以编辑实体类,修改、细化实体的展示:

    package com.mycompany.sample.domain;
    
    import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    
    import java.io.Serializable;
    
    /**
     * @author : dylanz
     * @since : 07/07/2020
     **/
    @Data
    @JsonIgnoreProperties(ignoreUnknown = true)
    @ApiModel
    public class Lead implements Serializable {
        private static final long serialVersionUID = 1L;
    
        @ApiModelProperty(value = "leadId", dataType = "Long", name = "id", example = "10130546")
        private Long leadId;
        @ApiModelProperty(value = "email", dataType = "String", name = "email", example = "dylan.zhang@xxxx.com")
        private String email;
    }
    

    @ApiModel:生成swagger时扫描的实体注解;
    @ApiModelProperty:属性注解,可用于描述实体属性;

    修改后,效果如下:

    实体注解

    还有我特别喜欢的测试API的功能

    1. 点击API规格右上角的"Try it out"按钮:

    Try it out

    2. 点击Execute按钮,测试API:

    Execute

    3. API测试返回:

    API返回

    我们可以在页面上修改API参数,如本例为leadId,进行不同参数值的测试(Request Body也支持),而不需要其他测试工具或测试代码,相当方便;

    (本例中,我们在controller内@ApiImplicitParam注解中设置了默认值:example = "10130546")

    使用Swagger来管理API文档是十分方便、快捷的,界面美观、并且有测试API的功能,对开发人员、测试人员十分友好,满足了绝大多数API文档化的需求。
    凡事也要从不同的角度来看待,Swagger强大的背后,也有其一定的局限性:
    1. 仅对于Restful API支持较为友好,其他类型的API支持得不是很好;
    2. 对代码有一定的侵入性;
    3. Swagger与代码需要强绑定;
      (每个API都需要人为添加注解,如果有人偷懒,在API开发时没有加上Swagger对应的注解,那么Swagger UI上是看不到该API的)
    4. ...
    综合来看,我还是很喜欢Swagger的,使用简单,功能强大!!!

    你Get到了吗?

    相关文章

      网友评论

        本文标题:Spring Boot之整合Swagger

        本文链接:https://www.haomeiwen.com/subject/ridphktx.html