为什么使用Swagger2
由于Spring Boot能够快速开发、便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API。而我们构建RESTful API的目的通常都是由于多终端的原因,这些终端会共用很多底层业务逻辑,因此我们会抽象出这样一层来同时服务于多个移动端或者Web前端。
这样一来,我们的RESTful API就有可能要面对多个开发人员或多个开发团队:IOS开发、Android开发或是Web开发等。为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建一份RESTful API文档来记录所有接口细节,然而这样的做法有以下几个问题:
- 由于接口众多,并且细节复杂(需要考虑不同的HTTP请求类型、HTTP头部信息、HTTP请求内容等),高质量地创建这份文档本身就是件非常吃力的事,下游的抱怨声不绝于耳。
- 随着时间推移,不断修改接口实现的时候都必须同步修改接口文档,而文档与代码又处于两个不同的媒介,除非有严格的管理机制,不然很容易导致不一致现象。
为了解决上面这样的问题,本文将介绍RESTful API的重磅好伙伴Swagger2,它可以轻松的整合到Spring Boot中,并与Spring MVC程序配合组织出强大RESTful API文档。它既可以减少我们创建文档的工作量,同时说明内容又整合入实现代码中,让维护文档和修改代码整合为一体,可以让我们在修改代码逻辑的同时方便的修改文档说明。另外Swagger2也提供了强大的页面测试功能来调试每个RESTful API。具体效果如下图所示:
springboot与swagger的集成:
Idea目录结构:
第一步:添加Swagger2依赖,在pom.xml
中加入Swagger2的依赖
<!-- Swagger 接口文档 -->
<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>
整个pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.loafer</groupId>
<artifactId>springboot02</artifactId>
<version>1.0-SNAPSHOT</version>
<name>springboot02</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- Swagger 接口文档 -->
<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>
</dependencies>
</project>
关于jar包的引入出现了一个问题就是版本的问题,可能需要与你的编辑器或者jdk要匹配吧,试了几个才最终成功导入jar。
第二步:swagger的配置启动类编写:
要使用swagger要进行一些配置,这个在界面的图上是可以显示的:类似于说明书:在这个类中我们会使用注解来进行启动swagger:
接下来需要在项目启动类中进行声明@EnableSwagger2
@EnableSwagger2
@SpringBootApplication
public class StartApplication {
public static void main(String[] args){
SpringApplication.run(StartApplication.class,args);
}
}
声明Swagger2配置内容的配置
package com.loafer;
import io.swagger.annotations.ApiOperation;
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;
@Configuration
@EnableSwagger2
public class Swagger2 {
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("demo")
.apiInfo(apiInfo())
.select()
// 设置basePackage会将包下的所有类的所有方法作为api
// .apis(RequestHandlerSelectors.basePackage("com.example.demo2.controller"))
// 只有标记@ApiOperation才会暴露出给swagger
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.regex("/api/.*"))
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("API接口文档")
.description("RESTful风格接口")
.termsOfServiceUrl("https://blog.csdn.net/vbirdbest") //服务条款网址
.version("1.0")
.contact(new Contact("zhangsan","http://www.baidu.com","18148590@qq.com"))
.build();
}
}
业务代码配置,如UserController.java
package com.loafer.controller;
import com.loafer.common.PagerIDto;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
@RestController
@RequestMapping("/api/v1/users")
@Api(value = "User API接口", tags = "user", description = "User API接口")
public class UserController {
@ApiOperation(value = "用户登录", notes = "用户登录接口")
@ApiResponses({
@ApiResponse(code = 0, message = "success"),
@ApiResponse(code = 10001, message = "用户名错误", response = IllegalArgumentException.class),
@ApiResponse(code = 10002, message = "密码错误")
})
@PostMapping(value = "/login")
public String login(@ApiParam(name = "username", value = "用户名", required = true) @RequestParam String username,
@ApiParam(name = "password", value = "密码", required = true) @RequestParam String password){
return "{'username':'" + username + "', 'password':'" + password + "'}";
}
@ApiOperation(value = "修改用户信息", notes = "修改用户信息")
@ApiImplicitParams({
@ApiImplicitParam(dataTypeClass = String.class, paramType = "header", name = "phone", required = true, value = "手机号"),
@ApiImplicitParam(dataTypeClass = String.class, paramType = "query", name = "nickname", required = true, value = "nickname", defaultValue = "双击666"),
@ApiImplicitParam(dataTypeClass = String.class, paramType = "path", name = "platform", required = true, value = "平台", defaultValue = "PC"),
@ApiImplicitParam(dataTypeClass = String.class, paramType = "body", name = "password", required = true, value = "密码")
})
@PutMapping(value = "/{platform}/regist")
public String regist(@RequestHeader String phone, @RequestParam String nickname, @PathVariable String platform, @RequestBody String password){
return "{'username':'" + phone + "', 'nickname':'" + nickname + "', 'platform': '" + platform + "', 'password':'"+password+"'}";
}
@ApiOperation(value = "用户列表", notes = "查询用户列表")
@GetMapping(value = "/list")
public String getUserList(PagerIDto pager){
return "[{'id': "+pager.getPage()+", 'username': 'zhangsan"+pager.getSize()+"'}]";
}
@ApiOperation(value = "删除用户", notes = "删除用户")
@DeleteMapping("/{id}")
public String removeUser(@PathVariable Long id){
return "success";
}
@ApiIgnore
@RequestMapping("/ignoreApi")
public String ignoreApi(){
return "docs";
}
}
yml文件配置:application.yml
server:
port: 8001
在编写完后,我们进行运行我们的项目后可以访问http://localhost:8001/swagger-ui.html 进行访问Swagger2
的相关内容。注意:端口号为server.port
定义的,根据自己定义的更换。
进入调试页面
执行
是不是很方便!
至此swagger2与springboot的集成完毕。
swagger-ui增加登录密码
pom.xml加入权限依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
application.yml
spring:
security:
basic:
path: /swagger-ui.html
enabled: true
user:
name: admin
password: 123456
server:
port: 8001
新增config目录,并新增WebSecurityConfigurerAdapter.java文件
/**
* Spring Security 会拦截swagger-ui.html 同样也会拦截api,这里将或略掉/api/下的所有子路径
*/
@EnableWebSecurity
@Configuration
class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
web.ignoring().antMatchers("/api/v1/**");
}
}
重启项目再次访问swagger-ui
访问 http://localhost:8001/swagger-ui.html 会跳转到 http://localhost:8001/login 输入application.yml配置的用户名密码即可跳转到到swagger-ui.html
常用注解解释:
注解 | 描述 |
@Api | @Api(description = “接口类的描述”) |
@ApiOperation | @ApiOperation(value = “接口方法的名称”, notes = “备注说明”) |
@ApiParam | @ApiParam(name = “参数名称”, value = “备注说明”, required = 是否必须):标注在方法的参数上 用于描述参数的名称、备注、是否必须等信息 |
@ApiImplicitParam | @ApiImplicitParam(paramType = “query”, name = “password”, dataType = “String”, required = true, value = “密码”, defaultValue = “123456”)用于描述方法的参数,标注在方法上,和@ApiParam功能一样,只是标注的位置不同而已
|
@ApiImplicitParams | 用于包含多个@ApiImplicitParam |
@ApiResponse | @ApiResponse(code = 0, message = “success”), code:响应码,例如400 message:信息,一般是对code的描述 response:抛出异常的类 |
@ApiModel | 描述一个Model的信息(这种一般用在post创建的时候,使用@RequestBody这样的场景,请求参数无法使用 |
@ApiModelProperty | @ApiModelProperty:描述一个model的属性
|
@ApiIgnore | 用于或略该接口,不生成该接口的文档 apis(RequestHandlerSelectors.basePackage(“com.example.demo2.controller”)) 会将包下的所有Controller类带有@RequestMapping或者XxxMapping都会给暴露给swagger,如果想部分类暴露出去部分不暴露出去,只能将不暴露的controller放到其他package中,放在同一个package是做不到的。 |
代码地址:https://github.com/loafer7423/springboot/tree/master/springboot02