大家都知道,在前后端分離開(kāi)發(fā)的時(shí)代,前后端接口對(duì)接是一項(xiàng)必不可少的工作。
可是,作為后端開(kāi)發(fā),怎么和前端更好的配合,才能讓自己不心累、腦累,直接扔給前端一個(gè)后端開(kāi)放api接口文檔或者頁(yè)面,讓前端不用看著難受,也不用前端老問(wèn)你,來(lái)愉快的合作呢?
原來(lái)可能我們一直用的是Swagger,不得不說(shuō)Swagger是一個(gè)非常好的框架,自從它的出現(xiàn),大大減少了我們對(duì)接的繁重工作。(以前我們開(kāi)發(fā)可是經(jīng)常要寫(xiě)開(kāi)發(fā)接口文檔的)
可是我們?cè)谟肧wagger時(shí),不管是Swagger本身,還是SwaggerUI,用起來(lái)其實(shí)不是那么的便捷,尤其是SwaggerUI,反正我用起來(lái)真的很是難受,也許是因?yàn)樗皇俏覀儑?guó)人開(kāi)發(fā)的,所以操作方面根本沒(méi)有我們國(guó)人的操作習(xí)慣設(shè)計(jì)。
幸好啊,我們國(guó)人也是很厲害的。
Knife4j這個(gè)東東,簡(jiǎn)直是及時(shí)雨,用起來(lái)絲滑的很??纯此慕缑妫遣皇蔷褪菄?guó)人的思維設(shè)計(jì)?
有了這個(gè)東東,那么我們來(lái)研究一下,怎么讓他來(lái)集成我們的Gateway,那么如何實(shí)現(xiàn)Gateway,可以查看我的上一篇文章。
輕量級(jí)的Spring Cloud Gateway實(shí)踐,實(shí)現(xiàn)api和websocket轉(zhuǎn)發(fā)https://blog.csdn.net/t610654893/article/details/137783310?spm=1001.2014.3001.5501
那么,我在這個(gè)項(xiàng)目基礎(chǔ)上,實(shí)現(xiàn)Knife4j的集成實(shí)現(xiàn)。
首先,我來(lái)說(shuō)一下我的整體項(xiàng)目結(jié)構(gòu):
--- 倆個(gè)主要的Spring Boot名
【app-server】前端接口服務(wù)
【manager-server】后端管理平臺(tái)服務(wù)器接口
--- 微服網(wǎng)關(guān)、配置等平臺(tái)服務(wù)
【cloud-server】
---【gateway-starter】路由套件
---?等等
【common-server】公共starter目錄的服務(wù)
---【boot-starter】公共套件?
---?等等
好,那么我們先從gateway著手來(lái)實(shí)現(xiàn)。首先pom.xml內(nèi)引入:
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
在Gateway項(xiàng)目?jī)?nèi),新增一個(gè)類(lèi)集成SwaggerResourcesProvider來(lái)配置SwaggerProvider,獲取Api-doc!
/**
* <b>功能:</b>SWAGGER聚合服務(wù)<br>
*/
@Slf4j
@Component
@Primary
@AllArgsConstructor
public class SwaggerResourceConfig implements SwaggerResourcesProvider {
@Resource
private Environment env;
private final RouteLocator routeLocator;
private final GatewayProperties gatewayProperties;
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<String> routes = new ArrayList<>();
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
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("**", "v3/api-docs"))));
});
return resources;
}
private SwaggerResource swaggerResource(String name, String location) {
log.info("name:{},location:{}", name, location);
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(env.getProperty(name));
????????swaggerResource.setLocation(location?+?"?group=KN");
swaggerResource.setSwaggerVersion("3.0.3");
return swaggerResource;
}
}
?????為了能更好的實(shí)現(xiàn)界面的客觀(guān)性,我們這里寫(xiě)了一個(gè)swaggerResource的方法,此方法主要是為了能更好的表達(dá)我們的Api接口是屬于誰(shuí)的。比如說(shuō)我們?cè)贕ateway的配置內(nèi)配置了:routes[0].id=lb://app-server, 那么我們?cè)谂渲煤笤偌右粋€(gè)app-server=分組接口,那么在Knife4j內(nèi)就可以更直觀(guān)的選擇屬于app-server的項(xiàng)目API了。
我們這里主要還是你為了集成Swagger的內(nèi)容,來(lái)完成Knife4j的前段實(shí)現(xiàn)。
因?yàn)镚ateway里沒(méi)有配置SwaggerConfig,而運(yùn)行Swagger-ui又需要依賴(lài)一些接口,所以我們還需要自己來(lái)實(shí)現(xiàn)swagger-resource端點(diǎn)。
這里其實(shí)也很簡(jiǎn)單,我們?cè)傩陆ㄒ粋€(gè)類(lèi),來(lái)完成我們對(duì)swagger-resource的實(shí)現(xiàn)。
/**
* <b>功能:</b>SWAGGER聚合服務(wù)<br>
*/
@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;
}
@GetMapping("/swagger-resources/configuration/security")
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/swagger-resources/configuration/ui")
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/swagger-resources")
public Mono<ResponseEntity> swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
@GetMapping("/api")
@SentinelResource("api")
public Set<ApiDefinition> apiRules() {
return GatewayApiDefinitionManager.getApiDefinitions();
}
@GetMapping("/gateway")
@SentinelResource("gateway")
public Set<GatewayFlowRule> apiGateway() {
return GatewayRuleManager.getRules();
}
@GetMapping("/flow")
@SentinelResource("flow")
public List<FlowRule> apiFlow() {
return FlowRuleManager.getRules();
}
}
Gateway端接口已經(jīng)配置完成。接下來(lái)配置實(shí)現(xiàn)客戶(hù)端,由于我的工程倆個(gè)server都引入了boot-server,所以這里我只在boot-server內(nèi)實(shí)現(xiàn)即可。
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-micro-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
客戶(hù)端服務(wù)基本也就是按照Swagger的配置寫(xiě)config即可。這樣更加方便我們以Swagger為基礎(chǔ)更增強(qiáng)我們的api接口發(fā)布。為了更詳盡的使用,我們一一實(shí)現(xiàn)。
增加Swagger 配置類(lèi)
@EnableOpenApi
@Configuration
@EnableConfigurationProperties(value = {SwaggerProperties.class})
public class SwaggerConfiguration {
@Resource
private SwaggerProperties swaggerProperties;
@Bean
public Docket createRestApi() {
Boolean enable = swaggerProperties.getEnable();
String tryHost = swaggerProperties.getTryHost();
return new Docket(DocumentationType.OAS_30)
.groupName("KN")
// 定義是否開(kāi)啟swagger,false為關(guān)閉,可以通過(guò)變量控制
.enable(enable)
// 將api的元信息設(shè)置為包含在json ResourceListing響應(yīng)中。
.apiInfo(apiInfo())
// 接口調(diào)試地址
.host(tryHost)
// 選擇哪些接口作為swagger的doc發(fā)布
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.regex("/api/.*"))
.build();
?}
/**
* <b>功能描述:</b>API 頁(yè)面上半部分展示信息<br>
* <b>修訂記錄:</b><br>
* <li>20201225 | 田星亮 | 創(chuàng)建方法</li><br>
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(swaggerProperties.getApplicationName())
.description(swaggerProperties.getApplicationDescription())
.termsOfServiceUrl("https://www.kn.com/")
.contact(new Contact("KN", null, "admin@kn.com"))
.version(swaggerProperties.getApplicationVersion())
.build();
}
}
???????這里我們?cè)僭鰪?qiáng)一下,使我們的接口更符合api接口規(guī)范,給API頭增加名為T(mén)oken的頭,在createRestApi方法Docket實(shí)現(xiàn)內(nèi)增加倆個(gè)方法后綴,并付上實(shí)現(xiàn):
.build()
// 授權(quán)信息設(shè)置,必要的header token等認(rèn)證信息
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
/**
* <b>功能描述:</b>設(shè)置授權(quán)信息<br>
*/
private List<SecurityScheme> securitySchemes() {
return Collections.singletonList(new ApiKey("token", "token", In.HEADER.toValue()));
}
/**
* <b>功能描述:</b>授權(quán)信息全局應(yīng)用<br>
*/
private List<SecurityContext> securityContexts() {
return Collections.singletonList(
SecurityContext.builder()
.securityReferences(Collections.singletonList(new SecurityReference("token", new AuthorizationScope[]{new AuthorizationScope("global", "")})))
.build()
);
}
???????上方內(nèi)配置項(xiàng)詳解,完成靈活調(diào)用文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-855402.html
@Data
@ConfigurationProperties("swagger")
public class SwaggerProperties {
/**
* 是否開(kāi)啟swagger,生產(chǎn)環(huán)境一般關(guān)閉,所以這里定義一個(gè)變量
*/
private Boolean enable;
/**
* 項(xiàng)目應(yīng)用名
*/
private String applicationName;
/**
* 項(xiàng)目版本信息
*/
private String applicationVersion;
/**
* 項(xiàng)目描述信息
*/
private String applicationDescription;
/**
* 接口調(diào)試地址
*/
private String tryHost;
}
至此,我們配置完成,打開(kāi)Gateway所屬的端口鏈接即可完成Knife4j的訪(fǎng)問(wèn)。Knife4j的配置內(nèi)還有一些高級(jí)項(xiàng)配置,大家按照自己需要增強(qiáng)哦,比如說(shuō)api排序這個(gè)我就很喜歡。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-855402.html
到了這里,關(guān)于Spring Cloud Gateway集成聚合型Spring Boot API發(fā)布組件knife4j,增強(qiáng)Swagger的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!