由于
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
方法创建Docket
的Bean
之后,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)