1. Swagger是什么
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。这个解释简单点来讲就是说,Swagger是一款可以根据RESTful风格生成接口开发文档,并且支持进行功能测试的应用。
2.Swagger的优点
功能比较丰富:支持多种注解,自动生成接口文档界面,支持在界面测试API接口功能
可以做到文档及时更新:开发过程中花一点写注释的时间,就可以及时的更新API文档,省心省力
集成简单:通过添加pom依赖和简单配置,内嵌于应用中就可同时发布API接口文档界面,不需要部署独立服务。
3. SpringFox是什么
但即便如此,对于许多开发来说,编写这个yml或json格式的描述文件,本身也是有一定负担的工作,特别是在后面持续迭代开发的时候,往往会忽略更新这个描述文件,直接更改代码。久而久之,这个描述文件也和实际项目渐行渐远,基于该描述文件生成的接口文档也失去了参考意义。所以作为Java届服务端的大一统框架Spring,迅速将Swagger规范纳入自身的标准,建立了swagger-springmvc项目,后面改成了现在的Springfox。通过在项目中引入Springfox,可以扫描相关的代码,生成该描述文件,进而生成与代码一致的接口文档和客户端代码。这种通过代码生成接口文档的形式,在后面需求持续迭代的项目中,显得尤为重要和高效。
SpringFox是一个开源的API Doc的框架, 它的前身是swagger-springmvc,可以将我们的Controller中的方法以文档的形式展现。官方定义为: Automated JSON API documentation for API’s built with Spring。
4. Swagger快速入门
- 在要使用Swagger的项目的pom.xml中引入Swagger2相关依赖
<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>
Springfox Swagger: Spring 基于swagger规范,可以将基于SpringMVC和Spring Boot项目的项目代码,自动生成JSON格式的描述文件。本身不是属于Swagger官网提供的,在这里列出来做个说明,方便后面作一个使用的展开。
- 新建Swagger配置类
package com.fh.Config;
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
// api扫包范围
.apis(RequestHandlerSelectors.basePackage("com.fh.controller")).paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("商品模块在线API接口文档") // 文档名称
.description("商品模块在线API接口文档") // 文档描述
.version("1.0") //版本号
.build();
}
}
- 在controller类上加上相应注解
package com.fh.controller;
@CrossOrigin
@RestController
@RequestMapping("tProductController")
@Api(tags = "这是一个商品模块接口")
public class TProductController {
@Autowired
public IProductService iProductService;
//查询商品列表
@RequestMapping(value = "selectProductList",method = RequestMethod.GET)
@ApiOperation(value = "查询商品信息")
public List<TProduct> selectProductList(){
List<TProduct> productList = iProductService.getProductList();
return productList;
}
@RequestMapping(value = "testProduct",method = RequestMethod.POST)
@ApiOperation("这个一个用来测试的方法")
@ApiImplicitParams({
@ApiImplicitParam(name = "pid",value = "商品id",required = true,dataType = "Long"),
@ApiImplicitParam(name = "pname",value = "商品名称",required = false,dataType = "String"),
@ApiImplicitParam(name = "price",value = "商品价格",required = true,dataType = "BigDecimal")
})
public void testProduct(Long pid, String pname, BigDecimal price){
}
//根据商品id查收商品信息
@RequestMapping(value = "selectProductById",method = RequestMethod.GET)
@ApiOperation(value = "根据商品id查询商品信息")
@ApiImplicitParam(name = "pid",value = "商品信息",required = true,dataType = "Long")
public TProduct selectProductById(Long pid){
return iProductService.selectProductById(pid);
}
}
- 启动项目,访问http://localhost:端口号/swagger-ui.html测试效果
注意:不要使用RequestMapping注解了,此注解如果没有对应的Method属性,表示所有的请求方式都可以访问,当然使用对应的GetMapping或者PostMapping等,指定特定的请求方式。
5.Zuul 整合Swagger 实现分布式API接口管理平台
在微服务系统中,每一个微服务都会集成一个swagger,这称作swagger集群;但是每一个微服务都会有一个地址,我们不可能查看一个微服务的文档,就换一个地址,这样很显然是不合适的。这个时候我们就需要把所有的swagger的进行合成到同一台服务器中,如何实现呢,我们有两种方式可以选择:
使用Nginx + Swagger,在Nginx里配置,以项目区分,不同的项目跳转到不同的接口文档
使用Zuul + Swagger,根据对应的服务,转发请求,调用对应的服务接口文档
SpringBoot支持对Swagger管理,只需要在Zuul网关中添加对应服务的Swagger文档支持即可。
1. 在Zuul服务网关项目中导入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>
2. 新建一个Swagger配置类,注意这块不需要扫描controller包
package com.fh.config;
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
// api扫包范围
// .apis(RequestHandlerSelectors.basePackage("com.fh.controller")).paths(PathSelectors.any()).build();
.paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("商品模块在线API接口文档") // 文档名称
.description("商品模块在线API接口文档") // 文档描述
.version("1.0") //版本号
.build();
}
}
3. 新建一个类实现SwaggerResourcesProvider接口,重写get方法
package com.fh.config;
public class DocumentationConfig implements SwaggerResourcesProvider {
@Override
public List<SwaggerResource> get() {
List resources = new ArrayList<>();
resources.add(swaggerResource("商品接口文档", "/shop-provider-product/v2/api-docs", "2.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;
}
}
- 启动zuul服务网关项目,访问**http://localhost:端口号/swagger-ui.html查看效果
这个时候,可以直接访问网关,然后通过网关去访问product微服务
注意:如果在Zuul网关项目中有身份认证的过滤器,则需要在过滤器中放行对应微服务Swagger接口文档地址。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
附加
JavaBean
@ApiModel(value = "商品实体类",description = "商品实体类")
public class TProduct {
private Long id;
@ApiModelProperty(name = "pid",value = "商品id",required = true,dataType = "Long")
private Long pid;
@ApiModelProperty(name = "pname",value = "商品名称",required = true,dataType = "String")
private String pname;
测试传JavaBean
@PostMapping
@ApiOperation("这个方法用来测试传JavaBean")
public void testAddProduct(TProduct product){
}
传单个参数
@RequestMapping(value = "selectProductById",method = RequestMethod.GET)
@ApiOperation(value = "根据商品id查询商品信息")
@ApiImplicitParam(name = "pid",value = "商品信息",required = true,dataType = "Long")
public TProduct selectProductById(Long pid){
return iProductService.selectProductById(pid);
}
传多个参数
@RequestMapping(value = "testProduct",method = RequestMethod.POST)
@ApiOperation("这个一个用来测试的方法")
@ApiImplicitParams({
@ApiImplicitParam(name = "pid",value = "商品id",required = true,dataType = "Long"),
@ApiImplicitParam(name = "pname",value = "商品名称",required = false,dataType = "String"),
@ApiImplicitParam(name = "price",value = "商品价格",required = true,dataType = "BigDecimal")
})
public void testProduct(Long pid, String pname, BigDecimal price){
System.out.println("这是测试方法");
}
END