Spring Security技术栈学习笔记(七)使用Swagger自动生成API文档

由于Spring Boot能够快速开发、便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API。而我们构建RESTful API的目的通常都是由于多终端的原因,这些终端会共用很多底层业务逻辑,因此我们会抽象出这样一层来同时服务于多个移动端或者Web前端。本文将介绍RESTful API的重磅好伙伴Swagger2,它可以轻松的整合到Spring Boot中,并与Spring MVC程序配合组织出强大RESTful API文档。它既可以减少我们创建文档的工作量,同时说明内容又整合入实现代码中,让维护文档和修改代码整合为一体,可以让我们在修改代码逻辑的同时方便的修改文档说明。另外Swagger2也提供了强大的页面测试功能来调试每个RESTful API。此引用来自程序猿DD

Spring Boot中应用中Swagger2构建强大的API文档十分方便,只需要在项目中添加Swagger2的依赖,然后在Spring Boot的启动的main方法的类上加上注解@EnableSwagger2就可以完成构建工作。效果图如下:
这里写图片描述
在图中可以看出,我自定义的Controller只有FileController,而其他的都是Spring Boot的一些控制器,而这些API文档往往是我们不需要的,所以,仅仅使用Swagger2的默认方式显然是不能满足我们的需求的,所以,我们需要自定义Swagger文档。

添加依赖
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.8.0</version>
</dependency>

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.8.0</version>
</dependency>
配置Swagger

我们写一个Swagger的配置类,添加上@Configuration注解方便被Spring Boot配置,添加@EnableSwagger2注解启动Swagger文档构建能力。需要注意的是,一般配置类可以放在Spring Boot启动类的同一个包里,如果没有放,那么请在Spring Boot的启动类上添加包扫描注解@ComponentScan(basePackages = {"com.lemon.security"}),然后配置类可以放在任何的这个包的子包下面。

package com.lemon.security.web.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 lemon
 * @date 2018/4/3 下午1:01
 */
@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket createRestfulApiDocs() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.lemon.security.web.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("自定义RESTful API文档")
                .description("更多内容请关注CSDN博客:https://blog.csdn.net/Lammonpeter")
                .termsOfServiceUrl("https://blog.csdn.net/Lammonpeter")
                .contact(new Contact("Lemon", "https://blog.csdn.net/Lammonpeter", "lemon_jiang@aliyun.com"))
                .version("1.0.0")
                .build();
    }
}

对上面的代码有如下解释:
通过createRestfulApiDocs方法创建DocketBean之后,apiInfo()用来创建该API的基本信息(这些基本信息会展现在文档页面中)。select()函数返回一个ApiSelectorBuilder实例用来控制哪些接口暴露给Swagger来展现,本例采用指定扫描的包路径来定义,Swagger会扫描该包下所有Controller定义的API,并产生文档内容(除了被@ApiIgnore指定的请求)。

添加文档内容

在完成了上述配置后,其实已经可以生产文档内容,但是这样的文档主要针对请求本身,而描述主要来源于函数等命名产生,对用户并不友好,我们通常需要自己增加一些说明来丰富文档内容。如下所示,我们通过@ApiOperation注解来给API方法增加说明,通过@ApiImplicitParams@ApiImplicitParam注解来给参数增加说明,通过@ApiModelProperty注解来给实体类的属性增加说明。

  • Controller添加文档说明:
package com.lemon.security.web.controller;

import cn.hutool.core.io.IoUtil;
import com.lemon.security.web.dto.FileInfo;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

/**
 * @author lemon
 * @date 2018/4/2 下午2:19
 */
@RestController
@RequestMapping("/file")
public class FileController {

    private static String folder = "/Users/lemon/IdeaProjects/spring-security/lemon-security-demo";

    @PostMapping
    @ApiOperation(value = "文件上传接口", notes = "访问此接口可以实现文件上传")
    @ApiImplicitParam(name = "file", value = "使用MultipartFile的实例对象来接收文件数据", required = true, dataTypeClass = MultipartFile.class)
    public FileInfo upload(@RequestParam("file") MultipartFile file) throws IOException {
        System.out.println("上传文件的表单name值为:" + file.getName());
        System.out.println("文件路径为:" + file.getOriginalFilename());
        System.out.println("文件大小为:" + file.getSize());
        File localFile = new File(folder, System.currentTimeMillis() + ".txt");
        // 执行上传操作
        file.transferTo(localFile);
        return new FileInfo(localFile.getAbsolutePath());
    }

    @GetMapping("/{id}")
    @ApiOperation(value = "文件下载接口", notes = "访问此接口并提供文件ID即可下载文件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "文件ID", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(name = "request", value = "HttpServletRequest实例对象,自动注入,无需传递", required = true, dataTypeClass = HttpServletRequest.class),
            @ApiImplicitParam(name = "response", value = "HttpServletResponse实例对象,自动注入,无需传递", required = true, dataTypeClass = HttpServletResponse.class)
    })
    public void download(@PathVariable String id, HttpServletRequest request, HttpServletResponse response) {
        System.out.println(folder);
        try (
                // 这是JDK7的特性,关于流的操作,可以写在try后面的圆括号里,这样就无需手动关闭流
                InputStream inputStream = new FileInputStream(new File(folder, id + ".txt"));
                OutputStream outputStream = response.getOutputStream()
        ) {
            // 设置下载的文件类型
            response.setContentType("application/x-download");
            // 设置下载后的文件名
            response.setHeader("Content-Disposition", "attachment;filename=test.txt");
            IoUtil.copy(inputStream, outputStream);
            // 刷新输出流
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

其中,
@ApiOperation注解的value属性一般都是简单描述API的功能,notes属性详细描述API的功能;
@ApiImplicitParams用来描述一个方法的多个参数的注解;
@ApiImplicitParam用来表述单个参数,name属性来描述参数的名称,value用来描述参数的意思,required表示参数是否是必需值,dataTypeClass或者dataType指定了数据的类型。
这里仅仅是对注解进行说明,而代码本身来自上一节内容,即《Spring Security技术栈开发企业级认证与授权(六)使用REST方式处理文件服务》。

  • 给实体类添加文档说明:
package com.lemon.security.web.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @author lemon
 * @date 2018/4/2 下午2:24
 */
@Data
public class FileInfo {

    @ApiModelProperty(value = "文件上传后的文件路径")
    private String path;

    public FileInfo(String path) {
        this.path = path;
    }
}

其中,@ApiModelProperty用来描述参数的意义。

配置完成以后,运行Spring Boot应用,在地址栏访问http://localhost:8080/swagger-ui.html就可以进入自定义的Swagger文档界面,效果图如下:
这里写图片描述
这里写图片描述

API文档访问与调试

在上图请求的页面中,Swagger除了查看接口功能外,还提供了调试测试功能,点击“Try it out!”按钮,即可完成了一次请求调用!此时,你也可以通过几个POST请求来验证之前的POST请求是否正确。相比为这些接口编写文档的工作,我们增加的配置内容是非常少而且精简的,对于原有代码的侵入也在忍受范围之内。因此,在构建RESTful API的同时,加入Swagger来对API文档进行管理,是个不错的选择。

Spring Security技术栈开发企业级认证与授权系列文章列表:

Spring Security技术栈学习笔记(一)环境搭建
Spring Security技术栈学习笔记(二)RESTful API详解
Spring Security技术栈学习笔记(三)表单校验以及自定义校验注解开发
Spring Security技术栈学习笔记(四)RESTful API服务异常处理
Spring Security技术栈学习笔记(五)使用Filter、Interceptor和AOP拦截REST服务
Spring Security技术栈学习笔记(六)使用REST方式处理文件服务
Spring Security技术栈学习笔记(七)使用Swagger自动生成API文档
Spring Security技术栈学习笔记(八)Spring Security的基本运行原理与个性化登录实现
Spring Security技术栈学习笔记(九)开发图形验证码接口
Spring Security技术栈学习笔记(十)开发记住我功能
Spring Security技术栈学习笔记(十一)开发短信验证码登录
Spring Security技术栈学习笔记(十二)将短信验证码验证方式集成到Spring Security
Spring Security技术栈学习笔记(十三)Spring Social集成第三方登录验证开发流程介绍
Spring Security技术栈学习笔记(十四)使用Spring Social集成QQ登录验证方式
Spring Security技术栈学习笔记(十五)解决Spring Social集成QQ登录后的注册问题
Spring Security技术栈学习笔记(十六)使用Spring Social集成微信登录验证方式

示例代码下载地址:

项目已经上传到码云,欢迎下载,内容所在文件夹为chapter007

更多干货分享,欢迎关注我的微信公众号:爪哇论剑(微信号:itlemon)
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值