springcloud-gateway集成knife4j的示例詳解
springcloud-gateway集成knife4j
環(huán)境信息
環(huán)境信息
- spring-boot:2.6.3
- spring-cloud-alibaba:2021.0.1.0
- knife4j-openapi2-spring-boot-starter:4.0.0
準備工作
各微服務&網(wǎng)關引入依賴
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
<version>4.0.0</version>
</dependency>微服務集成knife4j 第一步:編寫Knife4jApiInfoProperties
import com.ideaaedi.springcloud.jd.commonspring.config.Knife4jConfig;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* api 基礎信息配置。更多配置信息項見{@link Knife4jConfig}
*
* @author <font size = "20" color = "#3CAA3C"><a >JustryDeng</a></font> <img
* src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
* @since 2021.0.1.D
*/
@Data
@Component
public class Knife4jApiInfoProperties {
/**
* 要掃描api的base包
*/
@Value("${api-info.base-package:com}")
private String basePackage;
/**
* 是否啟用登錄認證
*/
@Value("${api-info.enable-security:true}")
private boolean enableSecurity;
/**
* 文檔標題
*/
@Value("${api-info.title:}")
private String title;
/**
* 文檔描述
*/
@Value("${api-info.description:api info}")
private String description;
/**
* 文檔版本
*/
@Value("${api-info.version:1.0.0}")
private String version;
/**
* 聯(lián)系人姓名
*/
@Value("${api-info.contact-name:JustryDeng}")
private String contactName;
/**
* 聯(lián)系人網(wǎng)址
*/
@Value("${api-info.contact-url:https://gitee.com/JustryDeng/projects}")
private String contactUrl;
/**
* 聯(lián)系人郵箱
*/
@Value("${api-info.contact-email:13548417409@163.com}")
private String contactEmail;
}
第二步:編寫配置類Knife4jConfig
import com.ideaaedi.springcloud.jd.commonds.constant.BaseConstant;
import com.ideaaedi.springcloud.jd.commonspring.config.properties.Knife4jApiInfoProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;
import java.util.List;
/**
* knife4j配置類
*
* @author <font size = "20" color = "#3CAA3C"><a >JustryDeng</a></font> <img
* src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
* @since 2021.0.1.D
*/
@Slf4j
@Configuration
public class Knife4jConfig implements WebMvcConfigurer {
/** 文檔相關資源的鏈接(需保證這些資源不需要鑒權即可訪問) */
public static String[] RESOURCE_URLS = new String[]{"/webjars/**", "/swagger**", "/v2/api-docs", "/doc.html"};
@Value("${spring.application.name:}")
private String applicationName;
@Bean
public Docket docket(Knife4jApiInfoProperties knife4jApiInfoProperties) {
String apiBasePackage = knife4jApiInfoProperties.getBasePackage();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo(knife4jApiInfoProperties))
.select()
.apis(RequestHandlerSelectors.basePackage(apiBasePackage))
.paths(PathSelectors.any())
.build();
if (knife4jApiInfoProperties.isEnableSecurity()) {
docket.securitySchemes(securitySchemes()).securityContexts(securityContexts());
}
return docket;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
private ApiInfo apiInfo(Knife4jApiInfoProperties knife4jApiInfoProperties) {
return new ApiInfoBuilder()
.title(knife4jApiInfoProperties.getTitle())
.description(knife4jApiInfoProperties.getDescription())
.termsOfServiceUrl(StringUtils.isBlank(applicationName) ? "" : "/" + applicationName)
.contact(new Contact(knife4jApiInfoProperties.getContactName(), knife4jApiInfoProperties.getContactUrl(), knife4jApiInfoProperties.getContactEmail()))
.version(knife4jApiInfoProperties.getVersion())
.build();
}
private List<SecurityScheme> securitySchemes() {
// 設置請求頭信息
List<SecurityScheme> result = new ArrayList<>();
// 第一個參數(shù),自定義即可。 如:BaseConstant.JWT_TOKEN_KEY=Auth-Token,然后在代碼里request.getHeader(BaseConstant.JWT_TOKEN_KEY)取值
ApiKey apiKey = new ApiKey(BaseConstant.JWT_TOKEN_KEY, "Authorization", "header");
result.add(apiKey);
return result;
}
private List<SecurityContext> securityContexts() {
// 設置需要登錄認證的路徑
List<SecurityContext> result = new ArrayList<>();
result.add(getContextByPath("/*/.*"));
return result;
}
private SecurityContext getContextByPath(String pathRegex) {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex(pathRegex))
.build();
}
private List<SecurityReference> defaultAuth() {
List<SecurityReference> result = new ArrayList<>();
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
result.add(new SecurityReference("Authorization", authorizationScopes));
return result;
}
}
第三步:放行相關靜態(tài)資源
對于管控了權限的應用,應放行以下資源
# 需要放行的資源已經(jīng)定義進上面編寫的Knife4jConfig中
public static String[] RESOURCE_URLS = new String[]{"/webjars/**", "/swagger**", "/v2/api-docs", "/doc.html"};網(wǎng)關集成knife4j
編寫配置類Knife4jGatewayConfig
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.SecurityConfiguration;
import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import springfox.documentation.swagger.web.UiConfiguration;
import springfox.documentation.swagger.web.UiConfigurationBuilder;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 網(wǎng)關knife4j配置
*
* @author <font size = "20" color = "#3CAA3C"><a >JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
* @since 2021.0.1.D
*/
@RestController
public class Knife4jGatewayConfig {
private final SecurityConfiguration securityConfiguration;
private final UiConfiguration uiConfiguration;
private final SwaggerResourceAdapter swaggerResourceAdapter;
public Knife4jGatewayConfig(@Autowired(required = false) SecurityConfiguration securityConfiguration,
@Autowired(required = false) UiConfiguration uiConfiguration,
SwaggerResourceAdapter swaggerResourceAdapter) {
this.securityConfiguration = securityConfiguration;
this.uiConfiguration = uiConfiguration;
this.swaggerResourceAdapter = swaggerResourceAdapter;
}
/**
* 安全配置
*/
@GetMapping("/swagger-resources/configuration/security")
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
}
/**
* 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));
}
/**
* 資源配置,自動路由到微服務中的各個服務的api-docs信息
*/
@GetMapping("/swagger-resources")
public Mono<ResponseEntity<List<SwaggerResource>>> swaggerResources() {
return Mono.just(new ResponseEntity<>(swaggerResourceAdapter.get(), HttpStatus.OK));
}
/**
* favicon.ico
*/
@GetMapping("/favicon.ico")
public Mono<ResponseEntity<?>> favicon() {
return Mono.just(new ResponseEntity<>(null, HttpStatus.OK));
}
/**
* swagger資源適配器
*
* @author <font size = "20" color = "#3CAA3C"><a >JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
* @since 2021.0.1.D
*/
@Slf4j
@Component
public static class SwaggerResourceAdapter implements SwaggerResourcesProvider {
/**
* spring-cloud-gateway是否開啟了根據(jù)服務發(fā)現(xiàn)自動為服務創(chuàng)建router
*/
@Value("${spring.cloud.gateway.discovery.locator.enabled:false}")
private boolean autoCreateRouter;
@Value("${spring.application.name:}")
private String applicationName;
@Resource
private RouteLocator routeLocator;
@Resource
private GatewayProperties gatewayProperties;
/**
* 根據(jù)當前所有的微服務路由信息,創(chuàng)建對應的SwaggerResource
*/
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> finalResources;
Set<String> routes = new LinkedHashSet<>(16);
// 獲取所有路由的id
routeLocator.getRoutes().subscribe(route -> {
String routeId = route.getId();
routeId = routeId.replace("ReactiveCompositeDiscoveryClient_", "");
routes.add(routeId);
});
// 沒有開啟自動創(chuàng)建路由,那么走配置文件中配置的路由
if (!autoCreateRouter) {
finalResources = new ArrayList<>(16);
gatewayProperties.getRoutes().stream()
// 過濾出配置文件中定義的路由
.filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(route -> {
route.getPredicates().stream()
// 過濾出設置有Path Predicate的路由
.filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
// 根據(jù)路徑拼接成api-docs路徑,生成SwaggerResource
.forEach(predicateDefinition -> finalResources.add(swaggerResource(route.getId(),
predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
.replace("**", "v2/api-docs"))));
});
} else {
finalResources = routes.stream().map(routeId -> swaggerResource(routeId, routeId + "/v2/api-docs")).collect(Collectors.toList());
}
List<SwaggerResource> resources = new ArrayList<>(finalResources);
// resources過濾掉網(wǎng)關的SwaggerResource, 我們一般也不會在網(wǎng)關中編寫業(yè)務controller
if (StringUtils.isNotBlank(applicationName)) {
resources = resources.stream().filter(x -> !applicationName.equalsIgnoreCase(x.getName())).collect(Collectors.toList());
}
// 排序
resources.sort(Comparator.comparing(x -> x.getName().length()));
return resources;
}
/**
* 創(chuàng)建swagger資源
*
* @param name
* swagger資源名(注:一般對應 {路由id})
* @param location
* swagger資源路徑(注:一般對應 {路由id}/v2/api-docs)
* @return swager資源
*/
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;
}
}
}
測試驗證
啟動微服務后,訪問{網(wǎng)關}/doc.html完成驗證

相關資料
到此這篇關于springcloud-gateway集成knife4j的文章就介紹到這了,更多相關springcloud-gateway集成knife4j內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot通過源碼探究靜態(tài)資源的映射規(guī)則實現(xiàn)
這篇文章主要介紹了SpringBoot通過源碼探究靜態(tài)資源的映射規(guī)則實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-05-05
SSH框架網(wǎng)上商城項目第6戰(zhàn)之基于DataGrid的數(shù)據(jù)顯示
SSH框架網(wǎng)上商城項目第6戰(zhàn)之基于DataGrid的數(shù)據(jù)顯示,提供了豐富的選擇、排序、分組和編輯數(shù)據(jù)的功能支持,感興趣的小伙伴們可以參考一下2016-05-05
Java Metrics系統(tǒng)性能監(jiān)控工具的使用詳解
Metrics是一個Java庫,可以對系統(tǒng)進行監(jiān)控,統(tǒng)計一些系統(tǒng)的性能指標。本文就來和大家詳細聊聊這個工具的具體使用,希望對大家有所幫助2022-11-11

