当前位置:网站首页>(5) Cloud integrated gateway gateway +swagger documentation tool
(5) Cloud integrated gateway gateway +swagger documentation tool
2022-07-24 09:04:00 【Still mourning】
1. Preface
1.1 Why do I need to introduce a gateway ?
Unified the entrance of each service , Users only need to know where the gateway is , In addition, it may also have authentication 、 monitor 、 cache 、 Request management 、 Static response processing and other functions . On the other hand , Flexible routing strategies can also be developed at the gateway layer . For some specific API, We need to set up a white list 、 Routing rules and other restrictions
Be careful ! This section contains only gateway The introduction of gateway , And integration Swagger Documentation tool , The deep usage of gateway is not included for the time being
1.2 Swagger file
Document tool class , Docking and self-test are more convenient
2. Project iteration process
No update here , Please refer to previous articles
3. Project access
3.1 newly build gateway Gateway module
introduce pom.xml Related dependencies , Only major dependencies are introduced here
.....
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>3.1.1</version>
</dependency>
<!-- gateway -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
<version>2021.0.1.0</version>
</dependency>
<!-- <!– Support only SWAGGER Related dependencies , No UI A choice –>-->
<!-- <dependency>-->
<!-- <groupId>com.github.xiaoymin</groupId>-->
<!-- <artifactId>knife4j-micro-spring-boot-starter</artifactId>-->
<!-- <version>3.0.3</version>-->
<!-- </dependency>-->
<!-- Full version SWG rely on , belt UI A choice The gateway must be selected UI-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
.....Create a new cross domain profile CorsConfig
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // allow cookies Cross domain
config.addAllowedOrigin("*");// # Allow requests to be submitted to this server URI,* That all are allowed , stay SpringMVC in , If set to *, It will be automatically converted to... In the current request header Origin
config.addAllowedHeader("*");// # Allow access to header information ,* All
config.setMaxAge(18000L);// Preview the cache time of the request ( second ), In this period of time , For the same cross domain request, there will be no pre check
config.addAllowedMethod("OPTIONS");// The type of method allowed to submit the request ,* That all are allowed
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}newly build swagger Get policy configuration file swaggerProvider
/**
* @author zxg
* obtain Api-doc, namely SwaggerResources
*/
@Component
@Primary
public class SwaggerProvider implements SwaggerResourcesProvider {
public static final String API_URI = "/v3/api-docs";
private final RouteLocator routeLocator;
private final GatewayProperties gatewayProperties;
public SwaggerProvider(RouteLocator routeLocator, GatewayProperties gatewayProperties) {
this.routeLocator = routeLocator;
this.gatewayProperties = gatewayProperties;
}
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<String> routes = new ArrayList<>();
// Take out gateway Of route
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
// Combined with configured route- route (Path), and route Filter , Only get the... Described in the enumeration route node
gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId()))
.forEach(routeDefinition -> routeDefinition.getPredicates().stream()
.filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
.forEach(predicateDefinition -> resources.add(swaggerResource(routeDefinition.getId(),
predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
.replace("/**", API_URI)))
)
);
return resources;
}
private SwaggerResource swaggerResource(String name, String location) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
swaggerResource.setSwaggerVersion("3.0");
return swaggerResource;
}
}newly build swagger Intercept configuration
/**
* @author zxg
* Swagger According to X-Forwarded-Prefix This Header To get BasePath, Add it to the interface path and host middle , Only in this way can the interface test be carried out normally
*/
@Component
public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory {
private static final String HEADER_NAME = "X-Forwarded-Prefix";
@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
if (!StringUtils.endsWithIgnoreCase(path, SwaggerProvider.API_URI)) {
return chain.filter(exchange);
}
String basePath = path.substring(0, path.lastIndexOf(SwaggerProvider.API_URI));
ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build();
ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
return chain.filter(newExchange);
};
}
}newly build swagger Interface configuration
/**
* @author zxg
* because Gateway There is no configuration in the SwaggerConfig, And running Swagger-ui You need to rely on some interfaces , So my idea is to establish corresponding swagger-resource Endpoint
*/
@RestController
@RequestMapping("/swagger-resources")
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("/configuration/security")
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/configuration/ui")
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("")
public Mono<ResponseEntity> swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
}stay application Configure service routing
Only the routing part is posted here
spring:
cloud:
gateway:
routes:
- id: user-server
uri: lb://user-server # use LoadBalanceClient Mode request , With lb:// start , The last one is registered in nacos Service name on
predicates:
- Path=/lb/user-server/**
filters:
- SwaggerHeaderFilter
- StripPrefix=1
3.2 Other services
To introduce the relevant pom.xml rely on
<!-- Support only SWAGGER Related dependencies , No UI A choice -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-micro-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!-- <!– Full version SWG rely on , belt UI A choice –>-->
<!-- <dependency>-->
<!-- <groupId>com.github.xiaoymin</groupId>-->
<!-- <artifactId>knife4j-spring-boot-starter</artifactId>-->
<!-- <version>3.0.3</version>-->
<!-- </dependency>-->increase swagger The configuration file SwaggerConfig
/**
* @author zxg
*/
@EnableOpenApi
@Configuration
public class SwaggerConfig {
@Value("${spring.application.name}")
private String applicationName;
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.select()
// To have @Api Annotated Controller Generate API file
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.paths(PathSelectors.any())
.build()
.securitySchemes(unifiedAuth())
.securityContexts(securityContexts())
;
}
private static List<SecurityScheme> unifiedAuth() {
List<SecurityScheme> arrayList = new ArrayList();
arrayList.add(new ApiKey("Authorization", "Authorization", "header"));
return arrayList;
}
private List<SecurityContext> securityContexts() {
List<SecurityContext> securityContexts=new ArrayList<>();
securityContexts.add(
SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("^(?!auth).*$"))
.build());
return securityContexts;
}
List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
List<SecurityReference> securityReferences=new ArrayList<>();
securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
return securityReferences;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(applicationName + " Interface document ")
.description(applicationName)
.contact(new Contact("xueliman", "www.xueliman-iov.com", ""))
.version("1.0")
.build();
}
@Bean
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
List<T> copy = mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
}3.3 Start project
Access gateway swagger Address , The contents are as follows

4. summary
springcloud2021.x Version pair gateway The introduction of , And integration swagger file , Slightly different from the previous version , But not bad .
The above content is a summary of personal learning process and obtained by referring to online materials , If there is something wrong in the text , Welcome to advise , No joy, no spray. .
边栏推荐
- Porting boa server on imx6ull
- 0 threshold takes you to know two-point search
- Relationship between fork and pipeline
- How to configure env.js in multiple environments in uni app
- pip3 带源安装大全
- How can tiktok transport videos not be streaming limited?
- 【汇编语言实战】(二)、编写一程序计算表达式w=v-(x+y+z-51)的值(含代码、过程截图)
- Tiktok shop platform will take disciplinary measures against sellers who violate rules and policies
- Ansible 常用模块介绍
- dp最长公共子序列详细版本(LCS)
猜你喜欢

Android system security - 5.3-apk V2 signature introduction

林业调查巡检数据采集解决方案

【FFH】OpenHarmony啃论文成长计划---cJSON在传统C/S模型下的应用

排序入门—插入排序和希尔排序

Source code analysis of BlockingQueue (arraybq and linkedbq)

Run little turtle to test whether the ROS environment in the virtual machine is complete

Super complete summary: how to operate files in go language

Configuration of uni app page.json title bar

Houdini notes

Paclitaxel loaded tpgs reduced albumin nanoparticles /ga-hsa gambogic acid human serum protein nanoparticles
随机推荐
How should tiktok shop cooperate with live broadcast in the background?
After watching the documentary "pirate treasure on Adak Island", I thought of the lost treasure in Chinese history
& 和 &&、| 和 || 的区别
JUC powerful auxiliary class
Why is TCP a triple handshake
From single architecture to distributed architecture, there are many pits and bugs!
Discuz论坛搭建详细过程,一看就懂
Treap
C language - the difference between sizeof and strlen
Practice 4-6 number guessing game (15 points)
Office fallback version, from 2021 to 2019
First acquaintance with JVM
[translation] integration challenges in microservice architecture using grpc and rest
Linked list - 24. Exchange nodes in the linked list in pairs
Leetcode102-二叉树的层序遍历详解
[example of URDF exercise based on ROS] use of four wheeled robot and camera
面试官:哥们Go语言的读写锁了解多少?
RPC中实现提供者信息变化后通知消费者
Three tips for finding the latest trends on tiktok
Houdini 官方HDA SideFX Labs 安装