diff --git a/blade-gateway/src/main/java/org/springblade/gateway/config/RouterFunctionConfiguration.java b/blade-gateway/src/main/java/org/springblade/gateway/config/RouterFunctionConfiguration.java index 86a92552..d68a7f31 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/config/RouterFunctionConfiguration.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/config/RouterFunctionConfiguration.java @@ -18,22 +18,17 @@ package org.springblade.gateway.config; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springblade.gateway.handler.*; +import org.springblade.gateway.handler.SwaggerResourceHandler; +import org.springblade.gateway.handler.SwaggerSecurityHandler; +import org.springblade.gateway.handler.SwaggerUiHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.web.cors.reactive.CorsUtils; import org.springframework.web.filter.reactive.HiddenHttpMethodFilter; import org.springframework.web.reactive.function.server.RequestPredicates; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Mono; @@ -47,48 +42,13 @@ import reactor.core.publisher.Mono; @AllArgsConstructor public class RouterFunctionConfiguration { - /** - * 这里为支持的请求头,如果有自定义的header字段请自己添加 - */ - private static final String ALLOWED_HEADERS = "x-requested-with, blade-auth, Content-Type, Authorization, credential, X-XSRF-TOKEN, token, username, client"; - private static final String ALLOWED_METHODS = "*"; - private static final String ALLOWED_ORIGIN = "*"; - private static final String ALLOWED_EXPOSE = "*"; - private static final String MAX_AGE = "18000L"; - - private final HystrixFallbackHandler hystrixFallbackHandler; private final SwaggerResourceHandler swaggerResourceHandler; private final SwaggerSecurityHandler swaggerSecurityHandler; private final SwaggerUiHandler swaggerUiHandler; - @Bean - public WebFilter corsFilter() { - return (ServerWebExchange ctx, WebFilterChain chain) -> { - ServerHttpRequest request = ctx.getRequest(); - if (CorsUtils.isCorsRequest(request)) { - ServerHttpResponse response = ctx.getResponse(); - HttpHeaders headers = response.getHeaders(); - headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS); - headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS); - headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN); - headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE); - headers.add("Access-Control-Max-Age", MAX_AGE); - headers.add("Access-Control-Allow-Credentials", "true"); - if (request.getMethod() == HttpMethod.OPTIONS) { - response.setStatusCode(HttpStatus.OK); - return Mono.empty(); - } - } - return chain.filter(ctx); - }; - } - @Bean public RouterFunction routerFunction() { - return RouterFunctions.route( - RequestPredicates.path("/fallback") - .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), hystrixFallbackHandler) - .andRoute(RequestPredicates.GET("/swagger-resources") + return RouterFunctions.route(RequestPredicates.GET("/swagger-resources") .and(RequestPredicates.accept(MediaType.ALL)), swaggerResourceHandler) .andRoute(RequestPredicates.GET("/swagger-resources/configuration/ui") .and(RequestPredicates.accept(MediaType.ALL)), swaggerUiHandler) diff --git a/blade-gateway/src/main/java/org/springblade/gateway/config/RateLimiterConfiguration.java b/blade-gateway/src/main/java/org/springblade/gateway/config/SwaggerRouteConfiguration.java similarity index 65% rename from blade-gateway/src/main/java/org/springblade/gateway/config/RateLimiterConfiguration.java rename to blade-gateway/src/main/java/org/springblade/gateway/config/SwaggerRouteConfiguration.java index 420367f7..fb1e039d 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/config/RateLimiterConfiguration.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/config/SwaggerRouteConfiguration.java @@ -13,25 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springblade.gateway.config; -import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; -import org.springframework.context.annotation.Bean; +import org.springblade.gateway.props.RouteProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; -import reactor.core.publisher.Mono; /** - * 路由限流配置 + * Swagger聚合文档配置 * * @author Chill */ @Configuration -public class RateLimiterConfiguration { - - @Bean(value = "remoteAddrKeyResolver") - public KeyResolver remoteAddrKeyResolver() { - return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()); - } - +@EnableConfigurationProperties(RouteProperties.class) +public class SwaggerRouteConfiguration { } diff --git a/blade-gateway/src/main/java/org/springblade/gateway/filter/RequestGlobalFilter.java b/blade-gateway/src/main/java/org/springblade/gateway/filter/RequestGlobalFilter.java deleted file mode 100644 index b3af9d9f..00000000 --- a/blade-gateway/src/main/java/org/springblade/gateway/filter/RequestGlobalFilter.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.springblade.gateway.filter; - -import org.springframework.cloud.gateway.filter.GatewayFilterChain; -import org.springframework.cloud.gateway.filter.GlobalFilter; -import org.springframework.core.Ordered; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Mono; - -import java.util.Arrays; -import java.util.stream.Collectors; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl; - -/** - *

- * 全局拦截器,作用所有的微服务 - *

- * 1. 对请求头中参数进行处理 from 参数进行清洗 - * 2. 重写StripPrefix = 1,支持全局 - * - * @author lengleng - */ -@Component -public class RequestGlobalFilter implements GlobalFilter, Ordered { - - /** - * Process the Web request and (optionally) delegate to the next - * {@code WebFilter} through the given {@link GatewayFilterChain}. - * - * @param exchange the current server exchange - * @param chain provides a way to delegate to the next filter - * @return {@code Mono} to indicate when request processing is complete - */ - @Override - public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { - // 1. 清洗请求头中from 参数 - ServerHttpRequest request = exchange.getRequest().mutate() - .headers(httpHeaders -> httpHeaders.remove("X")) - .build(); - - // 2. 重写StripPrefix - addOriginalRequestUrl(exchange, request.getURI()); - String rawPath = request.getURI().getRawPath(); - String newPath = "/" + Arrays.stream(StringUtils.tokenizeToStringArray(rawPath, "/")) - .skip(1L).collect(Collectors.joining("/")); - ServerHttpRequest newRequest = request.mutate() - .path(newPath) - .build(); - exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newRequest.getURI()); - - return chain.filter(exchange.mutate().request(newRequest.mutate().build()).build()); - } - - @Override - public int getOrder() { - return -1000; - } - -} diff --git a/blade-gateway/src/main/java/org/springblade/gateway/handler/HystrixFallbackHandler.java b/blade-gateway/src/main/java/org/springblade/gateway/handler/HystrixFallbackHandler.java deleted file mode 100644 index 63d03985..00000000 --- a/blade-gateway/src/main/java/org/springblade/gateway/handler/HystrixFallbackHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com). - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springblade.gateway.handler; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.server.HandlerFunction; -import org.springframework.web.reactive.function.server.ServerRequest; -import org.springframework.web.reactive.function.server.ServerResponse; -import reactor.core.publisher.Mono; - -/** - * Hystrix 降级处理 - * - * @author lengleng - */ -@Slf4j -@Component -public class HystrixFallbackHandler implements HandlerFunction { - @Override - public Mono handle(ServerRequest serverRequest) { - log.error("网关执行请求:{}失败,hystrix服务降级处理", serverRequest.uri()); - return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR.value()) - .contentType(MediaType.TEXT_PLAIN).body(BodyInserters.fromObject("服务异常")); - } -} diff --git a/blade-gateway/src/main/java/org/springblade/gateway/props/RouteProperties.java b/blade-gateway/src/main/java/org/springblade/gateway/props/RouteProperties.java new file mode 100644 index 00000000..9b7aa5d6 --- /dev/null +++ b/blade-gateway/src/main/java/org/springblade/gateway/props/RouteProperties.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springblade.gateway.props; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; + +import java.util.ArrayList; +import java.util.List; + +/** + * 路由配置类 + * + * @author Chill + */ +@Data +@RefreshScope +@ConfigurationProperties("blade.document") +public class RouteProperties { + + private final List resources = new ArrayList<>(); + +} diff --git a/blade-gateway/src/main/java/org/springblade/gateway/props/RouteResource.java b/blade-gateway/src/main/java/org/springblade/gateway/props/RouteResource.java new file mode 100644 index 00000000..a279a400 --- /dev/null +++ b/blade-gateway/src/main/java/org/springblade/gateway/props/RouteResource.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springblade.gateway.props; + +import lombok.Data; +import org.springblade.core.launch.constant.AppConstant; + +/** + * Swagger聚合文档属性 + * + * @author Chill + */ +@Data +public class RouteResource { + + /** + * 文档名 + */ + private String name; + + /** + * 文档所在服务地址 + */ + private String location; + + /** + * 文档版本 + */ + private String version = AppConstant.APPLICATION_VERSION; + +} diff --git a/blade-gateway/src/main/java/org/springblade/gateway/provider/SwaggerProvider.java b/blade-gateway/src/main/java/org/springblade/gateway/provider/SwaggerProvider.java index 052b5215..84b40130 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/provider/SwaggerProvider.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/provider/SwaggerProvider.java @@ -17,19 +17,15 @@ package org.springblade.gateway.provider; import lombok.AllArgsConstructor; -import org.springblade.core.launch.constant.AppConstant; -import org.springframework.cloud.gateway.config.GatewayProperties; -import org.springframework.cloud.gateway.route.RouteLocator; -import org.springframework.cloud.gateway.support.NameUtils; +import org.springblade.gateway.props.RouteProperties; +import org.springblade.gateway.props.RouteResource; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import springfox.documentation.swagger.web.SwaggerResource; import springfox.documentation.swagger.web.SwaggerResourcesProvider; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; /** * 聚合接口文档注册 @@ -40,37 +36,23 @@ import java.util.Map; @Component @AllArgsConstructor public class SwaggerProvider implements SwaggerResourcesProvider { - public static final String API_URI = "/v2/api-docs-ext"; - private final RouteLocator routeLocator; - private final GatewayProperties gatewayProperties; + private static final String API_URI = "/v2/api-docs-ext"; - private static Map routeMap = new HashMap<>(); - - static { - routeMap.put(AppConstant.APPLICATION_AUTH_NAME, "授权模块"); - routeMap.put(AppConstant.APPLICATION_DESK_NAME, "工作台模块"); - routeMap.put(AppConstant.APPLICATION_SYSTEM_NAME, "系统模块"); - } + private RouteProperties routeProperties; @Override public List get() { List resources = new ArrayList<>(); - List routes = new ArrayList<>(); - routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); - 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))))); + List routeResources = routeProperties.getResources(); + routeResources.forEach(routeResource -> resources.add(swaggerResource(routeResource))); return resources; } - private SwaggerResource swaggerResource(String name, String location) { + private SwaggerResource swaggerResource(RouteResource routeResource) { SwaggerResource swaggerResource = new SwaggerResource(); - swaggerResource.setName((routeMap.get(name) == null ? name : routeMap.get(name))); - swaggerResource.setLocation(location); - swaggerResource.setSwaggerVersion("2.0"); + swaggerResource.setName(routeResource.getName()); + swaggerResource.setLocation(routeResource.getLocation().concat(API_URI)); + swaggerResource.setSwaggerVersion(routeResource.getVersion()); return swaggerResource; } diff --git a/blade-gateway/src/main/resources/bootstrap.yml b/blade-gateway/src/main/resources/bootstrap.yml index c7f53a95..b3a18ab0 100644 --- a/blade-gateway/src/main/resources/bootstrap.yml +++ b/blade-gateway/src/main/resources/bootstrap.yml @@ -1,42 +1,9 @@ server: port: 80 -# 需要配置的服务名 -blade: - service: - blade-auth: blade-auth - blade-desk: blade-desk - blade-system: blade-system - spring: cloud: gateway: - routes: - # 认证中心 - - id: ${blade.service.blade-auth} - uri: lb://${blade.service.blade-auth} - predicates: - - Path=/${blade.service.blade-auth}/** - filters: - - name: RequestRateLimiter - args: - # 使用SpEL按名称引用bean - key-resolver: '#{@remoteAddrKeyResolver}' - # 允许用户每秒处理多少个请求 - redis-rate-limiter.replenishRate: 10 - # 允许在一秒钟内完成的最大请求数 - redis-rate-limiter.burstCapacity: 20 - - StripPrefix=1 - # 首页模块 - - id: ${blade.service.blade-desk} - uri: lb://${blade.service.blade-desk} - predicates: - - Path=/${blade.service.blade-desk}/** - # 系统模块 - - id: ${blade.service.blade-system} - uri: lb://${blade.service.blade-system} - predicates: - - Path=/${blade.service.blade-system}/** discovery: locator: enabled: true @@ -44,4 +11,15 @@ spring: retry: enabled: true +# 聚合文档配置 +blade: + document: + resources: + - name: 授权模块 + location: /blade-auth + - name: 工作台模块 + location: /blade-desk + - name: 系统模块 + location: /blade-system + diff --git a/blade-service/blade-desk/src/test/java/org/springblade/desk/test/launcher/DemoTestLauncherServiceImpl.java b/blade-service/blade-desk/src/test/java/org/springblade/desk/test/launcher/DemoTestLauncherServiceImpl.java index 94b45c32..3ba4a5c1 100644 --- a/blade-service/blade-desk/src/test/java/org/springblade/desk/test/launcher/DemoTestLauncherServiceImpl.java +++ b/blade-service/blade-desk/src/test/java/org/springblade/desk/test/launcher/DemoTestLauncherServiceImpl.java @@ -1,18 +1,17 @@ -/* - * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * Neither the name of the dreamlu.net developer nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * Author: Chill 庄骞 (smallchill@163.com) +/** + * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.springblade.desk.test.launcher;