⚡ 增加gateway动态聚合文档配置
This commit is contained in:
parent
add4dad91a
commit
4299f9f807
|
|
@ -18,22 +18,17 @@ package org.springblade.gateway.config;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
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.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
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.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.filter.reactive.HiddenHttpMethodFilter;
|
||||||
import org.springframework.web.reactive.function.server.RequestPredicates;
|
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.WebFilter;
|
|
||||||
import org.springframework.web.server.WebFilterChain;
|
import org.springframework.web.server.WebFilterChain;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
|
@ -47,48 +42,13 @@ import reactor.core.publisher.Mono;
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class RouterFunctionConfiguration {
|
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 SwaggerResourceHandler swaggerResourceHandler;
|
||||||
private final SwaggerSecurityHandler swaggerSecurityHandler;
|
private final SwaggerSecurityHandler swaggerSecurityHandler;
|
||||||
private final SwaggerUiHandler swaggerUiHandler;
|
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
|
@Bean
|
||||||
public RouterFunction routerFunction() {
|
public RouterFunction routerFunction() {
|
||||||
return RouterFunctions.route(
|
return RouterFunctions.route(RequestPredicates.GET("/swagger-resources")
|
||||||
RequestPredicates.path("/fallback")
|
|
||||||
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), hystrixFallbackHandler)
|
|
||||||
.andRoute(RequestPredicates.GET("/swagger-resources")
|
|
||||||
.and(RequestPredicates.accept(MediaType.ALL)), swaggerResourceHandler)
|
.and(RequestPredicates.accept(MediaType.ALL)), swaggerResourceHandler)
|
||||||
.andRoute(RequestPredicates.GET("/swagger-resources/configuration/ui")
|
.andRoute(RequestPredicates.GET("/swagger-resources/configuration/ui")
|
||||||
.and(RequestPredicates.accept(MediaType.ALL)), swaggerUiHandler)
|
.and(RequestPredicates.accept(MediaType.ALL)), swaggerUiHandler)
|
||||||
|
|
|
||||||
|
|
@ -13,25 +13,18 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springblade.gateway.config;
|
package org.springblade.gateway.config;
|
||||||
|
|
||||||
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
|
import org.springblade.gateway.props.RouteProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 路由限流配置
|
* Swagger聚合文档配置
|
||||||
*
|
*
|
||||||
* @author Chill
|
* @author Chill
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public class RateLimiterConfiguration {
|
@EnableConfigurationProperties(RouteProperties.class)
|
||||||
|
public class SwaggerRouteConfiguration {
|
||||||
@Bean(value = "remoteAddrKeyResolver")
|
|
||||||
public KeyResolver remoteAddrKeyResolver() {
|
|
||||||
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 全局拦截器,作用所有的微服务
|
|
||||||
* <p>
|
|
||||||
* 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<Void>} to indicate when request processing is complete
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
|
||||||
* <p>
|
|
||||||
* 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
|
|
||||||
* <p>
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* <p>
|
|
||||||
* 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<ServerResponse> {
|
|
||||||
@Override
|
|
||||||
public Mono<ServerResponse> handle(ServerRequest serverRequest) {
|
|
||||||
log.error("网关执行请求:{}失败,hystrix服务降级处理", serverRequest.uri());
|
|
||||||
return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
|
|
||||||
.contentType(MediaType.TEXT_PLAIN).body(BodyInserters.fromObject("服务异常"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* 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
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* 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<RouteResource> resources = new ArrayList<>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* 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
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -17,19 +17,15 @@
|
||||||
package org.springblade.gateway.provider;
|
package org.springblade.gateway.provider;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.springblade.core.launch.constant.AppConstant;
|
import org.springblade.gateway.props.RouteProperties;
|
||||||
import org.springframework.cloud.gateway.config.GatewayProperties;
|
import org.springblade.gateway.props.RouteResource;
|
||||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
|
||||||
import org.springframework.cloud.gateway.support.NameUtils;
|
|
||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import springfox.documentation.swagger.web.SwaggerResource;
|
import springfox.documentation.swagger.web.SwaggerResource;
|
||||||
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
|
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 聚合接口文档注册
|
* 聚合接口文档注册
|
||||||
|
|
@ -40,37 +36,23 @@ import java.util.Map;
|
||||||
@Component
|
@Component
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class SwaggerProvider implements SwaggerResourcesProvider {
|
public class SwaggerProvider implements SwaggerResourcesProvider {
|
||||||
public static final String API_URI = "/v2/api-docs-ext";
|
private static final String API_URI = "/v2/api-docs-ext";
|
||||||
private final RouteLocator routeLocator;
|
|
||||||
private final GatewayProperties gatewayProperties;
|
|
||||||
|
|
||||||
private static Map<String, String> routeMap = new HashMap<>();
|
private RouteProperties routeProperties;
|
||||||
|
|
||||||
static {
|
|
||||||
routeMap.put(AppConstant.APPLICATION_AUTH_NAME, "授权模块");
|
|
||||||
routeMap.put(AppConstant.APPLICATION_DESK_NAME, "工作台模块");
|
|
||||||
routeMap.put(AppConstant.APPLICATION_SYSTEM_NAME, "系统模块");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SwaggerResource> get() {
|
public List<SwaggerResource> get() {
|
||||||
List<SwaggerResource> resources = new ArrayList<>();
|
List<SwaggerResource> resources = new ArrayList<>();
|
||||||
List<String> routes = new ArrayList<>();
|
List<RouteResource> routeResources = routeProperties.getResources();
|
||||||
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
|
routeResources.forEach(routeResource -> resources.add(swaggerResource(routeResource)));
|
||||||
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;
|
return resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SwaggerResource swaggerResource(String name, String location) {
|
private SwaggerResource swaggerResource(RouteResource routeResource) {
|
||||||
SwaggerResource swaggerResource = new SwaggerResource();
|
SwaggerResource swaggerResource = new SwaggerResource();
|
||||||
swaggerResource.setName((routeMap.get(name) == null ? name : routeMap.get(name)));
|
swaggerResource.setName(routeResource.getName());
|
||||||
swaggerResource.setLocation(location);
|
swaggerResource.setLocation(routeResource.getLocation().concat(API_URI));
|
||||||
swaggerResource.setSwaggerVersion("2.0");
|
swaggerResource.setSwaggerVersion(routeResource.getVersion());
|
||||||
return swaggerResource;
|
return swaggerResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,9 @@
|
||||||
server:
|
server:
|
||||||
port: 80
|
port: 80
|
||||||
|
|
||||||
# 需要配置的服务名
|
|
||||||
blade:
|
|
||||||
service:
|
|
||||||
blade-auth: blade-auth
|
|
||||||
blade-desk: blade-desk
|
|
||||||
blade-system: blade-system
|
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
cloud:
|
cloud:
|
||||||
gateway:
|
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:
|
discovery:
|
||||||
locator:
|
locator:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
@ -44,4 +11,15 @@ spring:
|
||||||
retry:
|
retry:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
|
# 聚合文档配置
|
||||||
|
blade:
|
||||||
|
document:
|
||||||
|
resources:
|
||||||
|
- name: 授权模块
|
||||||
|
location: /blade-auth
|
||||||
|
- name: 工作台模块
|
||||||
|
location: /blade-desk
|
||||||
|
- name: 系统模块
|
||||||
|
location: /blade-system
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,17 @@
|
||||||
/*
|
/**
|
||||||
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
*
|
* <p>
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* you may not use this file except in compliance with the License.
|
||||||
*
|
* You may obtain a copy of the License at
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
* <p>
|
||||||
* this list of conditions and the following disclaimer.
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
* <p>
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* documentation and/or other materials provided with the distribution.
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* Neither the name of the dreamlu.net developer nor the names of its
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* contributors may be used to endorse or promote products derived from
|
* See the License for the specific language governing permissions and
|
||||||
* this software without specific prior written permission.
|
* limitations under the License.
|
||||||
* Author: Chill 庄骞 (smallchill@163.com)
|
|
||||||
*/
|
*/
|
||||||
package org.springblade.desk.test.launcher;
|
package org.springblade.desk.test.launcher;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user