集成spring-boot-starter-swagger构建强大的API文档

参考地址:https://github.com/SpringForAll/spring-boot-starter-swagger

前言

随着前后端分离架构和微服务架构的流行,我们使用Spring Boot来构建RESTful API项目的场景越来越多。通常我们的一个RESTful API就有可能要服务于多个不同的开发人员或开发团队:IOS开发、Android开发、Web开发甚至其他的后端服务等。为了减少与其他团队平时开发期间的频繁沟通成本,传统做法就是创建一份RESTful API文档来记录所有接口细节,然而这样的做法有以下几个问题:

  • 由于接口众多,并且细节复杂(需要考虑不同的HTTP请求类型、HTTP头部信息、HTTP请求内容等),高质量地创建这份文档本身就是件非常吃力的事,下游的抱怨声不绝于耳;
  • 随着时间推移,不断修改接口实现的时候都必须同步修改接口文档,而文档与代码又处于两个不同的媒介,除非有严格的管理机制,不然很容易导致不一致现象;

为了解决上面这样的问题,Swagger2应运而生,通过将Swagger2整合到我们的Spring Boot应用中,我们可以快速的组织出强大RESTful API文档,Swagger2大量的减少了我们创建文档的工作量,同时通过简单的Annotation将API说明内容整合入实现代码中,让维护文档和修改代码整合为一体,可以让我们在修改代码逻辑的同时方便的修改文档说明,进一步减少了我们维护文档的成本。

本文将要介绍的是一个GitHub上的一个开源项目spring-boot-starter-swagger。该项目主要利用Spring Boot的自动化配置特性,对Swagger2进行了进一步的封装,更加简化了我们在Spring Boot应用中整合Swagger2的步骤。

Swagger2 简介

Swagger2是一款业界比较流行的实现RESTful API的文档在线自动生成及RESTful API在线调试的工具。优点有:

  1. Swagger2可以轻松的整合到Spring Boot工程中,并与Spring MVC程序配合组织出强大RestFul接口文档,通过在项目中引入Swagger,可以使用简单的Annotation,就实现了接口文档化;
  2. Swagger2既可以减少我们创建文档的工作量,同时说明内容又整合入实现代码中,让维护文档和修改代码整合为一体,可以让我们在修改代码逻辑的同时方便的修改文档说明;
  3. Swagger2提供标准的json或yaml文档,方便做进一步解析,典型应用是接口自动化测试;
  4. Swagger2也提供了强大的页面测试功能来调试每个RESTful API,Swagger2页面可以直接进行测试(try-it-out功能,部分替代Postman);
  5. Swagger还提供类似于github的SwaggerHub,相当于公共的API文档集散地

Swagger2项目主页:https://swagger.io/

spring-boot-starter-swagger 简介

spring-boot-starter-swagger是一个GitHub上的一个开源项目,该项目主要利用Spring Boot的自动化配置特性来实现快速的将swagger2引入spring boot应用来生成API文档,简化原生使用swagger2的整合代码。

版本基础

  • SpringBoot版本:1.5.x
  • Swagger版本:2.8.x

集成步骤

  • pom.xml中引入依赖:
<dependency>
  <groupId>com.spring4all</groupId>
  <artifactId>swagger-spring-boot-starter</artifactId>
	<version>1.9.0.RELEASE</version>
</dependency>

说明

1. 当前最新版本 1.9.0.RELEASE

2. 从1.6.0版本开始,artifactId修改为swagger-spring-boot-starter1.6.0之前的版本不做修改,依然为spring-boot-starter-swagger

  • 在应用主类中增加@EnableSwagger2Doc注解
/**
 *
 * @ClassName: DemoApplication
 * @Description: Demo应用启动类
 * @author jjava
 * @date 2019年10月31日 上午10:53:23
 *
 */
@EnableSwagger2Doc
@SpringBootApplication
public class DemoApplication {

    /**
     * @Title main
     * @Description 测试应用启动入口
     * @author java
     * @param args
     */
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
  • 默认情况下就能产生所有当前Spring MVC加载的请求映射文档。

参数配置

全局配置说明

swagger:
  base-package: swagger扫描的基础包,默认:全扫描
  base-path: 需要处理的基础URL规则,默认:/**
  contact:
    email: 维护人email
    name: 维护人
    url: 维护人URL
  description: 描述
  enabled: 是否启用swagger,默认:true
  exclude-path: 需要排除的URL规则,默认:空
  globalOperationParameters:
  - description: 描述信息
    modelRef: 指定参数类型
    name: 参数名
    parameterType: 指定参数存放位置,可选header,query,path,body.form
    required: 指定参数是否必传,true,false
  host: 文档的host信息,默认:空
  license: 许可证
  licenseUrl: 许可证URL
  termsOfServiceUrl: 服务条款URL
  title: 标题
  version: 版本
  • 全局配置示例
swagger:
  apply-default-response-messages: false # 取消使用默认预定义的响应消息,并使用自定义响应消息
  base-package: com.yuanx
  base-path: /**
  contact:
    email: yx_222@163.com
    name: YuanXu
    url: https://blog.csdn.net/yx_222
  description: Starter for swagger 2.x
  enabled: true
  exclude-path: /error, /ops/**
  global-response-message:
    get:
    - code: 401
      message: 页面不存在
    - code: 500
      message: 系统内部错误
      modelRef: ERROR
    post:
    - code: 500
      message: 系统内部错误
      modelRef: ERROR
  globalOperationParameters:
  - description: some description one
    modelRef: string
    name: name one
    parameterType: header
    required: true
  - description: some description two
    modelRef: string
    name: name two
    parameterType: body
    required: false
  license: Apache License, Version 2.0
  licenseUrl: https://www.apache.org/licenses/LICENSE-2.0.html
  termsOfServiceUrl: https://github.com/dyc87112/spring-boot-starter-swagger
  title: spring-boot-starter-swagger
  version: 1.9.0.RELEASE

path规则说明

swagger.base-pathswagger.exclude-path使用ANT规则配置。

我们可以使用swagger.base-path来指定所有需要生成文档的请求路径基础规则,然后再利用swagger.exclude-path来剔除部分我们不需要的。

例如:

management:
  context-path: /ops

swagger:
  base-path: /**
  exclude-path: /ops/**, /error

上面的设置将解析所有除了/ops/开始以及spring boot自带/error请求路径。

其中,exclude-path可以配合management.context-path=/ops设置的spring boot actuator的context-path来排除所有监控端点。

分组配置说明

当我们一个项目的API非常多的时候,我们希望对API文档实现分组。从1.2.0.RELEASE开始,将支持分组配置功能,具体配置内容如下:

swagger:
  docket:
    <name>:
      base-package: swagger扫描的基础包,默认:全扫描
      base-path: 需要处理的基础URL规则,默认:/**
      contact:
        email: 维护人email
        name: 维护人
        url: 维护人URL
      description: 描述
      exclude-path: 需要排除的URL规则,默认:空
      globalOperationParameters:
      - description: 描述信息
        modelRef: 指定参数存放位置,可选header,query,path,body.form
        name: 参数名
        parameterType: 指定参数是否必传,true,false
      license: 许可证
      licenseUrl: 许可证URL
      modelRef: 指定参数类型
      name: 参数名
      parameterType: 指定参数存放位置,可选header,query,path,body.form
      required: true=指定参数是否必传,true,false
      termsOfServiceUrl: 服务条款URL
      title: 标题
      version: 版本

<name>为swagger文档的分组名称,同一个项目中可以配置多个分组,用来划分不同的API文档。

分组配置示例

swagger:
  docket:
    group-a:
      contact:
        email: yuan163.com
        name: YuanXu
        url: https://blog.csdn.net/yuan
      description: Starter for swagger 2.x
      excludePath: /ops/**, /error
      globalOperationParameters:
      - description: some description three override
        modelRef: string
        name: name three
        parameterType: header
      termsOfServiceUrl: https://gitee.com/didispace/spring-boot-starter-swagger
      title: group-a
      basePackage: com.hnu
      version: 1.3.0.RELEASE
    group-b:
      title: group-b
      basePackage: com.hnu
      version: 1.3.0.RELEASE

默认配置与分组配置可以一起使用。在分组配置中没有配置的内容将使用默认配置替代,所以默认配置可以作为分组配置公共部分属性的配置。swagger.docket.aaa.globalOperationParameters[0].name会覆盖同名的全局配置。

公共参数配置说明

像每个接口都需要鉴权这种参数,可以在配置文件中统一定义,这样省去每个接口再写的麻烦,也能兼顾页面的测试。

swagger:
  global-operation-parameters:
  - name: TOKEN
    description: 鉴权
    modelRef: string
    parameterType: header
    required: true # 公共参数写成requierd, 对于不需要登录的接口随便写一个字符串即可

忽略参数类型配置说明

基础配置

swagger:
  ignored-parameter-types:
  - com.didispace.demo.User
  - com.didispace.demo.Product

分组配置

swagger:
  group-a:
    ignored-parameter-types:
    - com.didispace.demo.User
    - com.didispace.demo.Product

自定义全局响应消息配置说明(1.6.0 + 支持)

支持 POST,GET,PUT,PATCH,DELETE,HEAD,OPTIONS,TRACE 全局响应消息配置,具体配置内容如下:

swagger:
  apply-default-response-messages: false # 取消使用默认预定义的响应消息,并使用自定义响应消息
  global-response-message:
    get:
    - code: 401
      message: 401get
    - code: 500
      message: 500get
      modelRef: ERROR
    post:
    - code: 500
      message: 500post
      modelRef: ERROR

UI功能配置说明(1.6.0 + 支持)

调试按钮的控制(try it out)

swagger:
  ui-config:
    submit-methods: get,delete

该参数值为提供调试按钮的HTTP请求类型,多个用逗号分割,如果不想开启调试功能,只需要如下设置即可:

swagger:
  ui-config:
    submit-methods:

其他配置

swagger:
  ui-config:
    json-editor: false  # json编辑器
    request-timeout: 5000 # 页面调试请求的超时时间
    show-request-headers: true # 显示请求头

更多配置说明见官方说明:https://github.com/SpringForAll/spring-boot-starter-swagger

使用Annotation添加API文档内容

在整合完Swagger之后,在http://localhost:8080/swagger-ui.html页面中可以看到,关于各个接口的描述还都是英文或遵循代码定义的名称产生的。这些内容对用户并不友好,所以我们需要自己增加一些说明来丰富文档内容。我们通过@Api@ApiOperation注解来给API增加说明、通过@ApiImplicitParam@ApiModel@ApiModelProperty注解来给参数增加说明。
如下所示:

UserController.java 类

/**
 *
 * @ClassName: UserController
 * @Description: 用户管理Controller
 * @author YuanXu
 * @date 2019年10月31日 下午4:49:00
 *
 */
@Api(tags = "用户管理")
@RestController
@RequestMapping(value = "/users") // 通过这里配置使下面的映射都在/users下
public class UserController {

    /**
     * 创建线程安全的Map,模拟users信息的存储
     */
    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());

    @GetMapping("/")
    @ApiOperation(value = "获取用户列表")
    public List<User> getUserList() {
        List<User> r = new ArrayList<>(users.values());
        return r;
    }

    @PostMapping("/")
    @ApiOperation(value = "创建用户", notes = "根据User对象创建用户")
    public String postUser(@RequestBody User user) {
        users.put(user.getId(), user);
        return "success";
    }

    @GetMapping("/{id}")
    @ApiOperation(value = "获取用户详细信息", notes = "根据url的id来获取用户详细信息")
    public User getUser(@PathVariable Long id) {
        return users.get(id);
    }

    @PutMapping("/{id}")
    @ApiImplicitParam(paramType = "path", dataType = "Long", name = "id", value = "用户编号", required = true, example = "1")
    @ApiOperation(value = "更新用户详细信息", notes = "根据url的id来指定更新对象,并根据传过来的user信息来更新用户详细信息")
    public String putUser(@PathVariable Long id, @RequestBody User user) {
        User u = users.get(id);
        u.setName(user.getName());
        u.setAge(user.getAge());
        users.put(id, u);
        return "success";
    }

    @DeleteMapping("/{id}")
    @ApiOperation(value = "删除用户", notes = "根据url的id来指定删除对象")
    public String deleteUser(@PathVariable Long id) {
        users.remove(id);
        return "success";
    }
}

User.java 类

/**
 *
 * @ClassName: User
 * @Description: 用户 实体
 * @author YuanXu
 * @date 2019年10月31日 下午4:53:23
 *
 */
@Data
@ApiModel(description = "用户实体")
public class User {

    @ApiModelProperty("用户编号")
    private Long id;

    @ApiModelProperty("用户姓名")
    private String name;

    @ApiModelProperty("用户年龄")
    private Integer age;
}

完成上述代码添加后,启动Spring Boot程序,访问:http://localhost:8080/swagger-ui.html,就能看到中文说明的文档了。

API效果查看

打开API文档页面地址:http://localhost:8080/swagger-ui.html

API文档JSON数据获取地址:http://localhost:8080/v2/api-docs

Zuul整合Swagger2汇总API接口文档

Zuul工程pom.xml引入依赖

<!-- 引入 springboot parent ,帮我们实现了很多jar包的依赖管理 -->
<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.1.7.RELEASE</version>
</parent>

<dependencyManagement>
  <dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Greenwich.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
	<!-- 引入spring-cloud-starter-zuul的依赖 -->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
	</dependency>

	<!-- 引入spring-cloud-starter-netflix-eureka-client的依赖 -->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>

  <!-- 引入swagger-spring-boot-starter的依赖 -->
  <dependency>
		<groupId>com.spring4all</groupId>
		<artifactId>swagger-spring-boot-starter</artifactId>
		<version>1.9.0.RELEASE</version>
	</dependency>
</dependencies>

添加DocumentationConfig.java

通过遍历eureka路由方式自动添加所有微服务 API 文档,SwaggerResourcesProvider 是资源提供者,我们重写他,把各个微服务的API文档资源路径返回,注释部分为手动添加的方式。

/**
 *
 * @ClassName: DocumentationConfig
 * @Description: Zuul整合Swagger2汇总API接口文档
 * @author Yuan
 * @date 2019年11月1日 上午10:30:37
 *
 */
@Primary
@Component
public class DocumentationConfig implements SwaggerResourcesProvider {

    private final RouteLocator routeLocator;

    public DocumentationConfig(RouteLocator routeLocator) {
        this.routeLocator = routeLocator;
    }

    /*
     * (非 Javadoc)
     * <p>Title: get </p>
     * <p>遍历eureka路由方式自动添加所有微服务API文档</p>
     * <p>Author: yuan </p>
     * @return
     * @see com.google.common.base.Supplier#get()
     */
    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<SwaggerResource>();
        List<Route> routes = routeLocator.getRoutes();
        routes.forEach(route -> {
            resources.add(swaggerResource(route.getId(), route.getFullPath().replace("**", "v2/api-docs"), "1.0"));
        });
        return null;
    }

    /*
     * (非 Javadoc)
     * <p>Title: get </p>
     * <p>手动添加微服务API文档</p>
     * <p>Author: aa </p>
     * @return
     * @see com.google.common.base.Supplier#get()
     */
    /*
     * @Override
     * public List<SwaggerResource> get() {
     * List resources = new ArrayList<>();
     * resources.add(swaggerResource("基础服务API文档", "/yx-base-service/v2/api-docs", "1.0"));
     * resources.add(swaggerResource("文件服务API文档", "/yx-file-service/v2/api-docs", "1.0"));
     * return resources;
     * }
     */

    private SwaggerResource swaggerResource(String name, String location, String version) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion(version);
        return swaggerResource;
    }

}

查看API整合效果
运行相关服务和zuul网关服务

浏览器输入:http://localhost:8090/swagger-ui.html可查看API文档整合后的效果

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一一可可

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值