共计 6948 个字符,预计需要花费 18 分钟才能阅读完成。
SpringBoot 实战电商我的项目 mall(35k+star)地址:https://github.com/macrozheng/mall
摘要
记得我的 mall-swarm
微服务项目中,没有做 API 文档聚合,拜访每个服务的 API 文档都须要拜访独自的 swagger-ui.html
页面,既然咱们应用了微服务,就应该有对立的 API 文档入口,最近发现 knife4j
有这方面的反对,本文将具体介绍其实现,心愿对大家有所帮忙!
前置常识
咱们将采纳 Nacos 作为注册核心,Gateway 作为网关,应用
knife4j
来生成 API 文档,对这些技术不理解的敌人能够看下上面的文章。
- Spring Cloud Gateway:新一代 API 网关服务
- Spring Cloud Alibaba:Nacos 作为注册核心和配置核心应用
- 给 Swagger 换了个新皮肤,霎时高大上了!
利用架构
咱们现实的解决方案应该是这样的,网关作为 API 文档的对立入口,网关聚合所有微服务的文档,通过在网关进行切换来实现对其余服务 API 文档的拜访。
相干服务划分:
- micro-knife4j-gateway:网关服务,作为微服务 API 文档的拜访入口,聚合所有 API 文档,须要引入文档前端 UI 包;
- micro-knife4j-user:用户服务,一般 API 服务,不须要引入文档前端 UI 包;
- micro-knife4j-order:订单服务,一般 API 服务,不须要引入文档前端 UI 包。
具体实现
上面具体介绍下 Spring Cloud Gateway + knife4j 聚合 API 文档的具体实现,顺次搭建用户服务、订单服务和网关服务。
micro-knife4j-user
咱们首先来搭建用户服务,一个一般的 API 服务,很简略,仅需三步即可集成 knife4j。
- 在
pom.xml
中增加相干依赖,一个 SpringBoot 的 web 性能依赖,knife4j 的微服务依赖(不蕴含 API 文档的前端 UI 包);
<dependencies> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-web</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>com.github.xiaoymin</groupId> | |
<artifactId>knife4j-micro-spring-boot-starter</artifactId> | |
</dependency> | |
</dependencies> |
- 在
application.yml
这增加相干配置,配置一下 Nacos 注册核心即可;
server: | |
port: 9501 | |
spring: | |
profiles: | |
active: dev | |
application: | |
name: micro-knife4j-user | |
cloud: | |
nacos: | |
discovery: | |
server-addr: localhost:8848 | |
management: | |
endpoints: | |
web: | |
exposure: | |
include: "*" |
- 增加 Swagger 相干配置,十分惯例的配置,增加
@EnableKnife4j
注解开启 knife4j 的加强性能。
/** | |
* Swagger API 相干配置 | |
*/ | |
@Configuration | |
@EnableSwagger2 | |
@EnableKnife4j | |
public class Swagger2Config { | |
@Bean | |
public Docket createRestApi(){return new Docket(DocumentationType.SWAGGER_2) | |
.apiInfo(apiInfo()) | |
.select() | |
.apis(RequestHandlerSelectors.basePackage("com.macro.cloud.controller")) | |
.paths(PathSelectors.any()) | |
.build();} | |
private ApiInfo apiInfo() {return new ApiInfoBuilder() | |
.title("micro-knife4j-user") | |
.description("用户服务 API 文档") | |
.contact("macro") | |
.version("1.0") | |
.build();} | |
} |
micro-knife4j-order
咱们接下来搭建订单服务,一个一般的 API 服务,间接参考下面用户服务的搭建即可。
micro-knife4j-gateway
最初咱们搭建网关服务,作为微服务 API 文档的的对立入口,聚合所有微服务的 API 文档。
- 在
pom.xml
中增加相干依赖,Gateway 相干依赖和 knife4j 的 Starter(蕴含 API 文档的前端 UI 包);
<dependencies> | |
<dependency> | |
<groupId>org.springframework.cloud</groupId> | |
<artifactId>spring-cloud-starter-gateway</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>com.github.xiaoymin</groupId> | |
<artifactId>knife4j-spring-boot-starter</artifactId> | |
</dependency> | |
</dependencies> |
- 在
application.yml
这增加相干配置,配置一下 Nacos 注册核心,用户服务和订单服务的路由即可;
server: | |
port: 9201 | |
spring: | |
profiles: | |
active: dev | |
application: | |
name: micro-knife4j-gateway | |
cloud: | |
nacos: | |
discovery: | |
server-addr: localhost:8848 | |
gateway: | |
routes: #配置路由门路 | |
- id: user-service | |
uri: lb://micro-knife4j-user | |
predicates: | |
- Path=/user-service/** | |
filters: | |
- StripPrefix=1 | |
- id: order-service | |
uri: lb://micro-knife4j-order | |
predicates: | |
- Path=/order-service/** | |
filters: | |
- StripPrefix=1 | |
discovery: | |
locator: | |
enabled: true #开启从注册核心动态创建路由的性能 | |
lower-case-service-id: true #应用小写服务名,默认是大写 |
- 在网关上增加 Swagger 资源配置,用于聚合其余微服务中 Swagger 的
api-docs
拜访门路;
/** | |
* Swagger 资源配置 | |
* Created by macro on 2020/7/9. | |
*/ | |
@Slf4j | |
@Component | |
@Primary | |
@AllArgsConstructor | |
public class SwaggerResourceConfig implements SwaggerResourcesProvider { | |
private final RouteLocator routeLocator; | |
private final GatewayProperties gatewayProperties; | |
@Override | |
public List<SwaggerResource> get() {List<SwaggerResource> resources = new ArrayList<>(); | |
List<String> routes = new ArrayList<>(); | |
// 获取所有路由的 ID | |
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); | |
// 过滤出配置文件中定义的路由 -> 过滤出 Path Route Predicate-> 依据门路拼接成 api-docs 门路 -> 生成 SwaggerResource | |
gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(route -> {route.getPredicates().stream() | |
.filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName())) | |
.forEach(predicateDefinition -> resources.add(swaggerResource(route.getId(), | |
predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0") | |
.replace("**", "v2/api-docs")))); | |
}); | |
return resources; | |
} | |
private SwaggerResource swaggerResource(String name, String location) {log.info("name:{},location:{}", name, location); | |
SwaggerResource swaggerResource = new SwaggerResource(); | |
swaggerResource.setName(name); | |
swaggerResource.setLocation(location); | |
swaggerResource.setSwaggerVersion("2.0"); | |
return swaggerResource; | |
} | |
} |
- 什么是 Swagger 的
api-docs
拜访门路?该门路会返回 JSON 格局数据,Swagger 渲染 API 文档页面的所有数据就是来源于此,比方咱们的用户服务会返回如下信息,拜访地址:http://localhost:9201/user-service/v2/api-docs
- 接下来咱们须要自定义 Swagger 各个配置的节点,简略来说就是自定义 Swagger 外部的各个获取数据的接口;
/** | |
* 自定义 Swagger 的各个配置节点 | |
* Created by macro on 2020/7/9. | |
*/ | |
@RestController | |
public class SwaggerHandler {@Autowired(required = false) | |
private SecurityConfiguration securityConfiguration; | |
@Autowired(required = false) | |
private UiConfiguration uiConfiguration; | |
private final SwaggerResourcesProvider swaggerResources; | |
@Autowired | |
public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {this.swaggerResources = swaggerResources;} | |
/** | |
* Swagger 平安配置,反对 oauth 和 apiKey 设置 | |
*/ | |
@GetMapping("/swagger-resources/configuration/security") | |
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() { | |
return Mono.just(new ResponseEntity<>(Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK)); | |
} | |
/** | |
* Swagger UI 配置 | |
*/ | |
@GetMapping("/swagger-resources/configuration/ui") | |
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() { | |
return Mono.just(new ResponseEntity<>(Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); | |
} | |
/** | |
* Swagger 资源配置,微服务中这各个服务的 api-docs 信息 | |
*/ | |
@GetMapping("/swagger-resources") | |
public Mono<ResponseEntity> swaggerResources() {return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); | |
} | |
} |
- 比如说
swagger-resources
这个接口,可用于获取所有微服务的api-docs
拜访门路,获取信息如下,拜访地址:http://localhost:9201/swagger-resources
性能演示
接下来咱们来演示下微服务 API 文档聚合的性能,仅须要拜访网关的 API 文档页面即可,可自行切换到相干服务的 API 文档。
- 在此之前先启动咱们的 Nacos 注册核心,而后顺次启动
micro-knife4j-user
、micro-knife4j-order
及micro-knife4j-gateway
服务;
- 从网关拜访 API 文档,拜访地址:http://localhost:9201/doc.html
- 咱们通过左上角的切换组件即可切换到对应服务的 API 文档;
- 查看 API 文档,咱们能够发现所有接口都曾经增加了对应的拜访前缀,能够失常拜访。
切换回 Swagger UI
如果你不想应用 knife4j 的界面,想用原来的 Swagger 界面,也是能够反对的,切换办法非常简单,上面咱们来讲讲。
- 首先咱们须要在
pom.xml
中去除 knife4j 的相干依赖,次要就是上面两个依赖;
<dependencies> | |
<dependency> | |
<groupId>com.github.xiaoymin</groupId> | |
<artifactId>knife4j-micro-spring-boot-starter</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>com.github.xiaoymin</groupId> | |
<artifactId>knife4j-spring-boot-starter</artifactId> | |
</dependency> | |
</dependencies> |
- 在
pom.xml
中增加 Swagger 相干依赖,并去除原来应用的@EnableKnife4j
注解;
<dependencies> | |
<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> | |
<dependency> | |
<groupId>io.swagger</groupId> | |
<artifactId>swagger-models</artifactId> | |
<version>1.6.0</version> | |
</dependency> | |
<dependency> | |
<groupId>io.swagger</groupId> | |
<artifactId>swagger-annotations</artifactId> | |
<version>1.6.0</version> | |
</dependency> | |
</dependencies> |
- 重新启动所有服务,拜访网关的 API 文档门路即可查看:http://localhost:9201/swagger-ui.html
总结
比照 knife4j 和原生 Swagger 的微服务应用,再次证实 knife4j 是 springfox-swagger 的加强 UI 实现,齐全遵循了 springfox-swagger 中的应用形式。
参考资料
官网文档:https://doc.xiaominfo.com/gui…
我的项目源码地址
https://github.com/macrozheng…
公众号
mall 我的项目全套学习教程连载中,关注公众号 第一工夫获取。