接口管理这下总会了吧?
时间:2022-07-24
本文章向大家介绍接口管理这下总会了吧?,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
接口管理这下总会了吧?
- 使用方式
- 引入依赖
- 添加 Swagger 注解
- 配置扫描规则 application.yaml
- 效果
- 实现原理
- 小结
利用 Spring Boot 快速集成 Swagger 实现
Swagger 作为一款优秀的 API 接口文档管理框架,在过往的使用过程中,着实踩了不少坑。一开始,也在自己的博客上整理了使用说明文档,它的配置,说老实话,很多刚上手的同学还是觉得很难使用。我就这个问题思考了下,决定基于 Spring Boot 的装配机制,写个简单好用的 Api Starter Jar 包,让使用的人专注于接口自身,而非陷于一堆配置中无法自拔。
主要目的:
- 多种扫描方式(包路径、路由前缀)
- 自定义前缀
- 接口分组管理
- 无需额外配置,专注于接口文档自身
使用方式
引入依赖
pub.dsb.framework.boot:dsb-boot-api-starter:0.0.4.RELEASE
添加 Swagger 注解
- controller
package pub.dsb.api.controller.business;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import pub.dsb.api.object.dto.ProductInfoDTO;
import pub.dsb.api.object.dto.UserInfoDTO;
import pub.dsb.framework.boot.rest.R;
import pub.dsb.framework.boot.security.annotation.Decrypt;
@Api(value = "/v1/business", tags = {"业务处理模块"})
@RestController
@RequestMapping("/v1/business")
public class BusinessController {
/**
* 下单
*
* @param productInfo
* @return
*/
@RequestMapping(value = "/order", method = RequestMethod.POST)
@ApiOperation(value = "下单", notes = "下单,返回订单号", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public R<String> userInfo(ProductInfoDTO productInfo) {
return R.ok("business_id_45454545478");
}
}
- dto
package pub.dsb.api.object.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ApiModel(description = "商品信息:流水号、信息、数量")
public class ProductInfoDTO {
@ApiModelProperty(value = "订单流水号", example = "20200812452404", dataType = "int")
private int orderNumber;
@ApiModelProperty(value = "商品名称", example = "Mac 笔记本", dataType = "string")
private String productName;
@ApiModelProperty(value = "数量", example = "2", dataType = "int")
private int count;
}
配置扫描规则 application.yaml
dsb:
webmvc:
swagger:
# 默认分组参数,配置了的话生成默认分组下的接口扫描文档
# base-package: x.x.x
# 接口分组集合
api-groups:
- group-name: 业务处理模块
# 接口前缀
path-mapping: /api/biz/
# 包路径匹配
apis: pub.dsb.api.controller.business
# 路由匹配
paths: /v1/**
api-info:
title: 接口文档标题
description: 接口文档描述
terms-of-service-url: 服务地址
name: 接口负责人:姓名
url: 接口负责人:个人地址
email: abc@example.com
license: License 授权
license-url: License 地址
version: 接口文档版本号
- group-name: 基础信息管理
# 接口前缀
path-mapping: /api/docs/
# 包路径匹配
apis: pub.dsb.api.controller.user
# 路由匹配
paths: /v1/**
api-info:
title: 接口文档标题
description: 接口文档描述
terms-of-service-url: 服务地址
name: 接口负责人:姓名
url: 接口负责人:个人地址
email: abc@example.com
license: License 授权
license-url: License 地址
version: 接口文档版本号
效果
- 访问
http://127.0.0.1:8080/swagger-ui.html
在这里插入图片描述
- 请求参数
在这里插入图片描述
实现原理
基于 Spring Boot 的约定大于配置,根据 YAML 中配置的接口分组信息,直接生成对应所需 Docket Bean
核心源码逻辑
package pub.dsb.framework.boot.webmvc.configuration;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import pub.dsb.framework.boot.webmvc.configuration.Swagger2Configuration;
import pub.dsb.framework.boot.webmvc.properties.SwaggerProperties;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.ApiSelectorBuilder;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* Swagger API Docket 配置
* </p>
*
* @author Yiyuery
* @date 2020/8/21
* @since 0.0.1
*/
@Configuration
@Import({Swagger2Configuration.class, SwaggerProperties.class})
@ConditionalOnProperty(prefix = "dsb.webmvc.swagger", value = "enabled", matchIfMissing = true)
@ConditionalOnClass(Docket.class)
public class SwaggerDocketConfiguration implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
/**
* 注册 Docket
*
* @param swaggerProperties
* @return
*/
@Bean
public List<Docket> registerDocket(SwaggerProperties swaggerProperties) {
ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;
List<Docket> beans = new ArrayList();
List<SwaggerProperties.ApiGroup> apiGroups = swaggerProperties.getApiGroups();
if (CollectionUtils.isNotEmpty(apiGroups)) {
registerDockets(apiGroups, beans, configurableBeanFactory);
} else if (StringUtils.isNotEmpty(swaggerProperties.getBasePackage())) {
//配置了默认包路径的扫描配置
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.groupName("DEFAULT_GROUP")
.select()
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
.build();
beans.add(docket);
configurableBeanFactory.registerSingleton(docket.getGroupName() + "_Docket", docket);
}
return beans;
}
/**
* 解析配置 注册 Docket
*
* @param apiGroups
* @param beans
* @param configurableBeanFactory
*/
private void registerDockets(List<SwaggerProperties.ApiGroup> apiGroups, List<Docket> beans, ConfigurableBeanFactory configurableBeanFactory) {
for (SwaggerProperties.ApiGroup apiGroup : apiGroups) {
SwaggerProperties.ApiInfo apiInfo = apiGroup.getApiInfo();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
.contact(new Contact(apiInfo.getName(), apiInfo.getUrl(), apiInfo.getEmail()))
.description(apiInfo.getDescription())
.title(apiInfo.getTitle())
.version(apiInfo.getVersion())
.termsOfServiceUrl(apiInfo.getTermsOfServiceUrl())
.license(apiInfo.getLicense())
.licenseUrl(apiInfo.getLicenseUrl()).build())
.groupName(apiGroup.getGroupName());
ApiSelectorBuilder select = docket.select();
if (CollectionUtils.isNotEmpty(apiGroup.getApis())) {
Predicate<RequestHandler>[] apis = new Predicate[apiGroup.getApis().size()];
int index = 0;
for (String pack : apiGroup.getApis()) {
apis[index++] = RequestHandlerSelectors.basePackage(pack);
}
select.apis(Predicates.or(apis));
}
if (CollectionUtils.isNotEmpty(apiGroup.getPaths())) {
Predicate<String>[] paths = new Predicate[apiGroup.getPaths().size()];
int index = 0;
for (String path : apiGroup.getPaths()) {
paths[index++] = PathSelectors.ant(path);
}
select.paths(Predicates.or(paths));
}
select.build();
if (StringUtils.isNotEmpty(apiGroup.getPathMapping())) {
docket.pathMapping(apiGroup.getPathMapping());
}
beans.add(docket);
configurableBeanFactory.registerSingleton(docket.getGroupName() + "_Docket", docket);
}
}
}
小结
基于 dsb-boot-api-starter
,对于接口文档的提供便只剩接口的注解
和扫描路径等必要的配置
工作了,是不是忍不住要赶快试试了呢?
适用场景:
- 敏捷开发
- 微服务 API 过多
- 前后端分离
- ...
Tips:使用过程中遇到问题可以直接加小编反馈哦,光速修复信不信?
- SSE(Server-sent events)技术在web端消息推送和实时聊天中的使用
- 详解 Stacking 的 python 实现
- RESTful接口设计原则和优点
- 用 Doc2Vec 得到文档/段落/句子的向量表达
- 手把手用 IntelliJ IDEA 和 SBT 创建 scala 项目
- 项目中记录影响性能的缓慢数据库查询
- memory_profiler的使用
- 使用line_profiler查看api接口函数每行代码执行时间
- GAN 的 keras 实现
- 双向 LSTM
- scrapy回调函数传递参数
- python更新数据库脚本两种方法
- 使聊天机器人具有个性
- 遇到502错误,invalid request block size 解决方法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PHP实现微信提现(企业付款到零钱)
- centos7下rsync+crontab定期同步备份
- php抽象类和接口知识点整理总结
- php中echo与print区别点整理
- laravel框架模型和数据库基础操作实例详解
- Yii Framework框架使用PHPExcel组件的方法示例
- thinkphp3.2.3框架动态切换多数据库的方法分析
- 安装docker和docker-compose实例详解
- 如何判断php复选框是否被选中
- php实现的生成排列算法示例
- php多进程应用场景实例详解
- Linux Crontab Shell脚本实现秒级定时任务的办法
- laravel框架实现为 Blade 模板引擎添加新文件扩展名操作示例
- yii框架使用分页的方法分析
- Linux服务器间文件实时同步的实现