mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
3.0.0
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
# changelog
|
||||
|
||||
## 2.6.0
|
||||
## 3.0.0
|
||||
|
||||
- 重构spring cloud gateway网关
|
||||
- zuul和gateway网关二合一
|
||||
- 代码优化
|
||||
- 精简配置文件
|
||||
- 优化文档中心页面
|
||||
|
||||
## 2.5.10
|
||||
|
||||
|
@@ -1,6 +1,17 @@
|
||||
# 固定不变,不能改
|
||||
spring.application.name=sop-gateway
|
||||
# 不用改,如果要改,请全局替换修改
|
||||
sop.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC
|
||||
|
||||
# nacos cloud配置
|
||||
spring.cloud.nacos.discovery.server-addr=${nacos.url}
|
||||
|
||||
# 数据库配置
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.datasource.url=jdbc:mysql://${mysql.host}/sop?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
|
||||
spring.datasource.username=${mysql.username}
|
||||
spring.datasource.password=${mysql.password}
|
||||
|
||||
# https://blog.csdn.net/qq_36872046/article/details/81058045
|
||||
# 路由转发超时时间,毫秒,默认值1000,详见:RibbonClientConfiguration.DEFAULT_READ_TIMEOUT。
|
||||
# 如果微服务端 处理时间过长,会导致ribbon read超时,解决办法将这个值调大一点
|
||||
|
@@ -1,3 +1,5 @@
|
||||
# 固定不变,不能改
|
||||
spring.application.name=sop-gateway
|
||||
# 入口地址,不用改,默认是/zuul
|
||||
zuul.servlet-path=/api
|
||||
# 禁用默认的过滤器,不能删,不用改
|
||||
@@ -6,6 +8,15 @@ zuul.Servlet30WrapperFilter.pre.disable=true
|
||||
# 不用改,如果要改,请全局替换修改
|
||||
sop.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC
|
||||
|
||||
# nacos cloud配置
|
||||
spring.cloud.nacos.discovery.server-addr=${nacos.url}
|
||||
|
||||
# 数据库配置
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.datasource.url=jdbc:mysql://${mysql.host}/sop?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
|
||||
spring.datasource.username=${mysql.username}
|
||||
spring.datasource.password=${mysql.password}
|
||||
|
||||
# https://blog.csdn.net/qq_36872046/article/details/81058045
|
||||
# 路由转发超时时间,毫秒,默认值1000,详见:RibbonClientConfiguration.DEFAULT_READ_TIMEOUT。
|
||||
# 如果微服务端 处理时间过长,会导致ribbon read超时,解决办法将这个值调大一点
|
||||
|
@@ -75,4 +75,9 @@ public class RouteDefinition {
|
||||
* 是否需要token
|
||||
*/
|
||||
private int needToken;
|
||||
|
||||
/**
|
||||
* 是否是兼容模式,即使用了@ApiAbility注解
|
||||
*/
|
||||
private int compatibleMode;
|
||||
}
|
@@ -8,6 +8,8 @@ import com.gitee.sop.gatewaycommon.gateway.common.RequestContentDataExtractor;
|
||||
import com.gitee.sop.gatewaycommon.gateway.common.SopServerHttpRequestDecorator;
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||
import com.gitee.sop.gatewaycommon.param.FormHttpOutputMessage;
|
||||
import com.gitee.sop.gatewaycommon.route.ForwardInfo;
|
||||
import com.gitee.sop.gatewaycommon.param.ParamNames;
|
||||
import com.gitee.sop.gatewaycommon.util.RequestUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -57,20 +59,17 @@ public class ServerWebExchangeUtil {
|
||||
* 重定向
|
||||
*
|
||||
* @param exchange exchange
|
||||
* @param apiParam apiParam
|
||||
* @param forwardInfo forwardInfo
|
||||
* @return 返回新的ServerWebExchange,配合chain.filter(newExchange);使用
|
||||
*/
|
||||
public static ServerWebExchange getForwardExchange(ServerWebExchange exchange, ApiParam apiParam) {
|
||||
ServerHttpRequest newRequest = getForwardRequest(exchange.getRequest(), apiParam);
|
||||
public static ServerWebExchange getForwardExchange(ServerWebExchange exchange, ForwardInfo forwardInfo) {
|
||||
ServerHttpRequest newRequest = exchange.getRequest()
|
||||
.mutate()
|
||||
.header(ParamNames.HEADER_VERSION_NAME, forwardInfo.getVersion())
|
||||
.path(forwardInfo.getPath()).build();
|
||||
return exchange.mutate().request(newRequest).build();
|
||||
}
|
||||
|
||||
public static ServerHttpRequest getForwardRequest(ServerHttpRequest request, ApiParam apiParam) {
|
||||
return request
|
||||
.mutate()
|
||||
.header(SopConstants.REDIRECT_VERSION_KEY, apiParam.fetchVersion())
|
||||
.path(getForwardPath(apiParam)).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建一个接受请求体的request
|
||||
@@ -113,19 +112,6 @@ public class ServerWebExchangeUtil {
|
||||
return chain.filter(newExchange);
|
||||
}
|
||||
|
||||
private static String getForwardPath(ApiParam apiParam) {
|
||||
// 如果有异常,则重定向到这个path
|
||||
if (apiParam.getThrowable() != null) {
|
||||
return VALIDATE_ERROR_PATH;
|
||||
}
|
||||
String forwardPath = UNKNOWN_PATH;
|
||||
String method = apiParam.fetchName();
|
||||
if (org.springframework.util.StringUtils.hasText(method)) {
|
||||
forwardPath = "/" + method + "/";
|
||||
}
|
||||
return forwardPath;
|
||||
}
|
||||
|
||||
public static ApiParam getApiParam(ServerWebExchange exchange, String body) {
|
||||
MediaType contentType = exchange.getRequest().getHeaders().getContentType();
|
||||
if (contentType == null) {
|
||||
|
@@ -4,12 +4,12 @@ import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||
import com.gitee.sop.gatewaycommon.gateway.controller.ConfigChannelController;
|
||||
import com.gitee.sop.gatewaycommon.gateway.controller.ErrorLogController;
|
||||
import com.gitee.sop.gatewaycommon.gateway.controller.GatewayController;
|
||||
import com.gitee.sop.gatewaycommon.gateway.filter.EnvGrayFilter;
|
||||
import com.gitee.sop.gatewaycommon.gateway.filter.GatewayModifyResponseGatewayFilter;
|
||||
import com.gitee.sop.gatewaycommon.gateway.filter.IndexFilter;
|
||||
import com.gitee.sop.gatewaycommon.gateway.filter.LimitFilter;
|
||||
import com.gitee.sop.gatewaycommon.gateway.filter.ParameterFormatterFilter;
|
||||
import com.gitee.sop.gatewaycommon.gateway.handler.GatewayExceptionHandler;
|
||||
import com.gitee.sop.gatewaycommon.gateway.route.GatewayForwardChooser;
|
||||
import com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteCache;
|
||||
import com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteRepository;
|
||||
import com.gitee.sop.gatewaycommon.manager.AbstractConfiguration;
|
||||
@@ -107,10 +107,8 @@ public class BaseGatewayConfiguration extends AbstractConfiguration {
|
||||
return gatewayRouteRepository;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
EnvGrayFilter envGrayFilter() {
|
||||
return new EnvGrayFilter();
|
||||
GatewayForwardChooser gatewayForwardChooser() {
|
||||
return new GatewayForwardChooser();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -15,7 +15,10 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
* @deprecated
|
||||
* @see com.gitee.sop.gatewaycommon.gateway.route.GatewayForwardChooser
|
||||
*/
|
||||
@Deprecated
|
||||
public class EnvGrayFilter implements GlobalFilter, Ordered {
|
||||
|
||||
@Autowired
|
||||
|
@@ -1,11 +1,11 @@
|
||||
package com.gitee.sop.gatewaycommon.gateway.filter;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
||||
import com.gitee.sop.gatewaycommon.exception.ApiException;
|
||||
import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil;
|
||||
import com.gitee.sop.gatewaycommon.manager.EnvironmentContext;
|
||||
import com.gitee.sop.gatewaycommon.gateway.route.GatewayForwardChooser;
|
||||
import com.gitee.sop.gatewaycommon.manager.EnvironmentKeys;
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||
import com.gitee.sop.gatewaycommon.route.ForwardInfo;
|
||||
import com.gitee.sop.gatewaycommon.validate.Validator;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -16,12 +16,10 @@ import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.codec.HttpMessageReader;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
|
||||
import org.springframework.web.reactive.function.BodyInserter;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.reactive.function.server.HandlerStrategies;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
@@ -30,8 +28,6 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -50,6 +46,9 @@ public class IndexFilter implements WebFilter {
|
||||
@Autowired
|
||||
private Validator validator;
|
||||
|
||||
@Autowired
|
||||
private GatewayForwardChooser gatewayForwardChooser;
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
@@ -92,9 +91,11 @@ public class IndexFilter implements WebFilter {
|
||||
exchange, headers);
|
||||
return bodyInserter.insert(outputMessage, new BodyInserterContext())
|
||||
.then(Mono.defer(() -> {
|
||||
ForwardInfo forwardInfo = gatewayForwardChooser.getForwardInfo(exchange);
|
||||
ServerHttpRequest decorator = decorate(exchange, headers, outputMessage);
|
||||
ServerWebExchange newExchange = exchange.mutate().request(decorator).build();
|
||||
return chain.filter(newExchange);
|
||||
ServerWebExchange forwardExchange = ServerWebExchangeUtil.getForwardExchange(newExchange, forwardInfo);
|
||||
return chain.filter(forwardExchange);
|
||||
}));
|
||||
|
||||
} else {
|
||||
@@ -105,8 +106,9 @@ public class IndexFilter implements WebFilter {
|
||||
ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange, originalQuery);
|
||||
// 签名验证
|
||||
doValidate(apiParam);
|
||||
ServerWebExchange newExchange = ServerWebExchangeUtil.getForwardExchange(exchange, apiParam);
|
||||
return chain.filter(newExchange);
|
||||
ForwardInfo forwardInfo = gatewayForwardChooser.getForwardInfo(exchange);
|
||||
ServerWebExchange forwardExchange = ServerWebExchangeUtil.getForwardExchange(exchange, forwardInfo);
|
||||
return chain.filter(forwardExchange);
|
||||
}
|
||||
} else {
|
||||
return ServerWebExchangeUtil.forwardUnknown(exchange, chain);
|
||||
@@ -127,9 +129,7 @@ public class IndexFilter implements WebFilter {
|
||||
, HttpHeaders headers
|
||||
, CachedBodyOutputMessage outputMessage
|
||||
) {
|
||||
ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange);
|
||||
ServerHttpRequest newRequest = ServerWebExchangeUtil.getForwardRequest(exchange.getRequest(), apiParam);
|
||||
return new ServerHttpRequestDecorator(newRequest) {
|
||||
return new ServerHttpRequestDecorator(exchange.getRequest()) {
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
long contentLength = headers.getContentLength();
|
||||
@@ -140,7 +140,6 @@ public class IndexFilter implements WebFilter {
|
||||
} else {
|
||||
httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
|
||||
}
|
||||
httpHeaders.set(SopConstants.REDIRECT_VERSION_KEY, apiParam.fetchVersion());
|
||||
return httpHeaders;
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,16 @@
|
||||
package com.gitee.sop.gatewaycommon.gateway.route;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil;
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||
import com.gitee.sop.gatewaycommon.route.BaseForwardChooser;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class GatewayForwardChooser extends BaseForwardChooser<ServerWebExchange> {
|
||||
@Override
|
||||
protected ApiParam getApiParam(ServerWebExchange exchange) {
|
||||
return ServerWebExchangeUtil.getApiParam(exchange);
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
package com.gitee.sop.gatewaycommon.route;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.RouteDefinition;
|
||||
import com.gitee.sop.gatewaycommon.bean.TargetRoute;
|
||||
import com.gitee.sop.gatewaycommon.manager.EnvGrayManager;
|
||||
import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public abstract class BaseForwardChooser<T> implements ForwardChooser<T> {
|
||||
|
||||
@Autowired
|
||||
private EnvGrayManager envGrayManager;
|
||||
|
||||
protected abstract ApiParam getApiParam(T t);
|
||||
|
||||
@Override
|
||||
public ForwardInfo getForwardInfo(T t) {
|
||||
ApiParam apiParam = getApiParam(t);
|
||||
ForwardInfo forwardInfo = new ForwardInfo();
|
||||
String nameVersion = apiParam.fetchNameVersion();
|
||||
TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(nameVersion);
|
||||
RouteDefinition routeDefinitionOrig = targetRoute.getRouteDefinition();
|
||||
String path = routeDefinitionOrig.getPath();
|
||||
String versionInHead = apiParam.fetchVersion();
|
||||
String serviceId = targetRoute.getServiceRouteInfo().fetchServiceIdLowerCase();
|
||||
// 如果服务在灰度阶段,返回一个灰度版本号
|
||||
String grayVersion = envGrayManager.getVersion(serviceId, nameVersion);
|
||||
// 如果是灰度环境
|
||||
if (grayVersion != null && envGrayManager.containsKey(serviceId, apiParam.fetchAppKey())) {
|
||||
String newNameVersion = apiParam.fetchName() + grayVersion;
|
||||
TargetRoute targetRouteDest = RouteRepositoryContext.getRouteRepository().get(newNameVersion);
|
||||
if (targetRouteDest != null) {
|
||||
if (BooleanUtils.toBoolean(routeDefinitionOrig.getCompatibleMode())) {
|
||||
versionInHead = grayVersion;
|
||||
} else {
|
||||
// 获取灰度接口
|
||||
RouteDefinition routeDefinition = targetRouteDest.getRouteDefinition();
|
||||
path = routeDefinition.getPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
forwardInfo.setPath(path);
|
||||
forwardInfo.setVersion(versionInHead);
|
||||
|
||||
return forwardInfo;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
package com.gitee.sop.gatewaycommon.route;
|
||||
|
||||
/**
|
||||
* 转发选择
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface ForwardChooser<T> {
|
||||
|
||||
/**
|
||||
* 返回转发信息
|
||||
* @param t 上下文
|
||||
* @return 返回转发信息
|
||||
*/
|
||||
ForwardInfo getForwardInfo(T t);
|
||||
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package com.gitee.sop.gatewaycommon.route;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class ForwardInfo {
|
||||
private String path;
|
||||
private String version;
|
||||
private String domain;
|
||||
}
|
@@ -12,13 +12,13 @@ import com.gitee.sop.gatewaycommon.zuul.controller.ZuulIndexController;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.ErrorFilter;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.FormBodyWrapperFilterExt;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.PostResultFilter;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.PreEnvGrayFilter;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.PreHttpServletRequestWrapperFilter;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.PreLimitFilter;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.PreParameterFormatterFilter;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.PreValidateFilter;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.Servlet30WrapperFilterExt;
|
||||
import com.gitee.sop.gatewaycommon.zuul.route.SopRouteLocator;
|
||||
import com.gitee.sop.gatewaycommon.zuul.route.ZuulForwardChooser;
|
||||
import com.gitee.sop.gatewaycommon.zuul.route.ZuulRouteCache;
|
||||
import com.gitee.sop.gatewaycommon.zuul.route.ZuulRouteRepository;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
@@ -26,7 +26,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
|
||||
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
|
||||
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
|
||||
import org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -89,22 +88,28 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
|
||||
return new Servlet30WrapperFilterExt();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SopRouteLocator sopRouteLocator() {
|
||||
return new SopRouteLocator();
|
||||
}
|
||||
|
||||
/**
|
||||
* 选取路由
|
||||
* @param zuulRouteRepository
|
||||
* @param sopRouteLocator
|
||||
* @param proxyRequestHelper
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
PreDecorationFilter preDecorationFilter(ZuulRouteRepository zuulRouteRepository, ProxyRequestHelper proxyRequestHelper) {
|
||||
PreDecorationFilter preDecorationFilter(SopRouteLocator sopRouteLocator, ProxyRequestHelper proxyRequestHelper) {
|
||||
// 自定义路由
|
||||
RouteLocator routeLocator = new SopRouteLocator(zuulRouteRepository);
|
||||
return new PreDecorationFilter(routeLocator,
|
||||
return new PreDecorationFilter(sopRouteLocator,
|
||||
this.server.getServlet().getContextPath(),
|
||||
this.zuulProperties,
|
||||
proxyRequestHelper);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 路由管理
|
||||
* @param zuulRouteRepository 路由仓库
|
||||
@@ -140,14 +145,6 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
|
||||
return new PreLimitFilter();
|
||||
}
|
||||
|
||||
/**
|
||||
* 决定版本号
|
||||
*/
|
||||
@Bean
|
||||
PreEnvGrayFilter preEnvGrayFilter() {
|
||||
return new PreEnvGrayFilter();
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误处理扩展
|
||||
*/
|
||||
@@ -173,4 +170,9 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
|
||||
return ApiContext.getApiConfig().getZuulErrorController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
ZuulForwardChooser zuulForwardChooser() {
|
||||
return new ZuulForwardChooser();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -14,7 +14,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
* 灰度发布判断,改变版本号
|
||||
*
|
||||
* @author tanghc
|
||||
* @deprecated
|
||||
* @see com.gitee.sop.gatewaycommon.zuul.route.ZuulForwardChooser
|
||||
*/
|
||||
@Deprecated
|
||||
public class PreEnvGrayFilter extends BaseZuulFilter {
|
||||
|
||||
@Autowired
|
||||
|
@@ -2,7 +2,11 @@ package com.gitee.sop.gatewaycommon.zuul.route;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.AbstractTargetRoute;
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||
import com.gitee.sop.gatewaycommon.route.ForwardInfo;
|
||||
import com.gitee.sop.gatewaycommon.param.ParamNames;
|
||||
import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.netflix.zuul.filters.Route;
|
||||
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
|
||||
import org.springframework.core.Ordered;
|
||||
@@ -19,11 +23,11 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public class SopRouteLocator implements RouteLocator, Ordered {
|
||||
|
||||
@Autowired
|
||||
private ZuulRouteRepository zuulRouteRepository;
|
||||
|
||||
public SopRouteLocator(ZuulRouteRepository zuulRouteRepository) {
|
||||
this.zuulRouteRepository = zuulRouteRepository;
|
||||
}
|
||||
@Autowired
|
||||
private ZuulForwardChooser zuulForwardChooser;
|
||||
|
||||
@Override
|
||||
public Collection<String> getIgnoredPaths() {
|
||||
@@ -52,7 +56,13 @@ public class SopRouteLocator implements RouteLocator, Ordered {
|
||||
if (zuulTargetRoute == null) {
|
||||
return null;
|
||||
}
|
||||
return zuulTargetRoute.getTargetRouteDefinition();
|
||||
Route targetRouteDefinition = zuulTargetRoute.getTargetRouteDefinition();
|
||||
ForwardInfo forwardInfo = zuulForwardChooser.getForwardInfo(RequestContext.getCurrentContext());
|
||||
String forwardPath = forwardInfo.getPath();
|
||||
targetRouteDefinition.setPath(forwardPath);
|
||||
String versionInHead = forwardInfo.getVersion();
|
||||
RequestContext.getCurrentContext().addZuulRequestHeader(ParamNames.HEADER_VERSION_NAME, versionInHead);
|
||||
return targetRouteDefinition;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -0,0 +1,18 @@
|
||||
package com.gitee.sop.gatewaycommon.zuul.route;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||
import com.gitee.sop.gatewaycommon.route.BaseForwardChooser;
|
||||
import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class ZuulForwardChooser extends BaseForwardChooser<RequestContext> {
|
||||
|
||||
@Override
|
||||
protected ApiParam getApiParam(RequestContext requestContext) {
|
||||
return ZuulContext.getApiParam();
|
||||
}
|
||||
|
||||
}
|
@@ -34,6 +34,8 @@ public class ServiceApiInfo {
|
||||
private int permission;
|
||||
/** 是否需要token */
|
||||
private int needToken;
|
||||
/** 是否是兼容模式,即使用了@ApiAbility注解 */
|
||||
private int compatibleMode;
|
||||
/** 是否是原始Mapping */
|
||||
private boolean originalMapping;
|
||||
|
||||
|
@@ -95,6 +95,7 @@ public class ApiMetaBuilder {
|
||||
apiMeta.setMergeResult(BooleanUtils.toInteger(apiMappingInfo.isMergeResult()));
|
||||
apiMeta.setPermission(BooleanUtils.toInteger(apiMappingInfo.isPermission()));
|
||||
apiMeta.setNeedToken(BooleanUtils.toInteger(apiMappingInfo.isNeedToken()));
|
||||
apiMeta.setCompatibleMode(BooleanUtils.toInteger(apiMappingInfo.isCompatibleMode()));
|
||||
return apiMeta;
|
||||
} else {
|
||||
if (!ServiceContext.getCurrentContext().getBoolean(ServiceContext.RESTFUL_KEY, false)) {
|
||||
|
@@ -5,6 +5,7 @@ import com.gitee.sop.servercommon.annotation.ApiMapping;
|
||||
import com.gitee.sop.servercommon.bean.ServiceConfig;
|
||||
import com.gitee.sop.servercommon.bean.ServiceContext;
|
||||
import com.gitee.sop.servercommon.util.OpenUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.core.PriorityOrdered;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
import org.springframework.web.servlet.mvc.condition.RequestCondition;
|
||||
@@ -29,7 +30,11 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple
|
||||
ApiAbility apiAbility = OpenUtil.getAnnotationFromMethodOrClass(method, ApiAbility.class);
|
||||
StringValueResolver valueResolver = null;
|
||||
if (apiMapping != null) {
|
||||
valueResolver = stringValueResolver;
|
||||
String version = apiMapping.version();
|
||||
if (StringUtils.isBlank(version)) {
|
||||
version = ServiceConfig.getInstance().getDefaultVersion();
|
||||
}
|
||||
valueResolver = new ApiMappingStringValueResolverVersion(version);
|
||||
}
|
||||
if (isMvc || apiAbility != null) {
|
||||
valueResolver = stringValueResolverMVC;
|
||||
@@ -46,7 +51,8 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple
|
||||
boolean ignoreValidate;
|
||||
boolean mergeResult;
|
||||
boolean permission;
|
||||
boolean needToken = false;
|
||||
boolean needToken;
|
||||
boolean compatibleMode = false;
|
||||
ApiMapping apiMapping = method.getAnnotation(ApiMapping.class);
|
||||
if (apiMapping != null) {
|
||||
name = apiMapping.value()[0];
|
||||
@@ -63,6 +69,7 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple
|
||||
mergeResult = apiAbility.mergeResult();
|
||||
permission = apiAbility.permission();
|
||||
needToken = apiAbility.needToken();
|
||||
compatibleMode = true;
|
||||
} else {
|
||||
return super.getCustomMethodCondition(method);
|
||||
}
|
||||
@@ -87,6 +94,7 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple
|
||||
apiMappingInfo.setMergeResult(mergeResult);
|
||||
apiMappingInfo.setPermission(permission);
|
||||
apiMappingInfo.setNeedToken(needToken);
|
||||
apiMappingInfo.setCompatibleMode(compatibleMode);
|
||||
logger.info("注册接口,name:" + method + ", version:" + version);
|
||||
return new ApiMappingRequestCondition(apiMappingInfo);
|
||||
}
|
||||
|
@@ -13,6 +13,8 @@ public class ApiMappingInfo {
|
||||
private boolean mergeResult;
|
||||
private boolean permission;
|
||||
private boolean needToken;
|
||||
private boolean compatibleMode;
|
||||
|
||||
|
||||
public ApiMappingInfo(String name, String version) {
|
||||
this.name = name;
|
||||
|
@@ -37,6 +37,11 @@ public class ApiMappingRequestCondition implements RequestCondition<ApiMappingRe
|
||||
*/
|
||||
@Override
|
||||
public ApiMappingRequestCondition getMatchingCondition(HttpServletRequest request) {
|
||||
String servletPath = request.getServletPath();
|
||||
String path = apiMappingInfo.getName() + "/" + apiMappingInfo.getVersion() + "/";
|
||||
if (servletPath.contains(path)) {
|
||||
return this;
|
||||
}
|
||||
String version = this.getVersion(request);
|
||||
if (version.equals(this.apiMappingInfo.getVersion())) {
|
||||
return this;
|
||||
|
@@ -0,0 +1,25 @@
|
||||
package com.gitee.sop.servercommon.mapping;
|
||||
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class ApiMappingStringValueResolverVersion implements StringValueResolver {
|
||||
|
||||
private static final String SPLIT = "/";
|
||||
|
||||
private String version;
|
||||
|
||||
public ApiMappingStringValueResolverVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveStringValue(String strVal) {
|
||||
if (strVal == null) {
|
||||
return null;
|
||||
}
|
||||
return strVal + SPLIT + version + SPLIT;
|
||||
}
|
||||
}
|
@@ -73,4 +73,9 @@ public class RouteDefinition {
|
||||
* 是否需要token
|
||||
*/
|
||||
private int needToken;
|
||||
|
||||
/**
|
||||
* 是否是兼容模式,即使用了@ApiAbility注解
|
||||
*/
|
||||
private int compatibleMode;
|
||||
}
|
@@ -180,7 +180,7 @@ public class AlipayController {
|
||||
}
|
||||
|
||||
// http://localhost:2222/alipay.story.get/
|
||||
@ApiOperation(value="获取故事信息2", notes = "获取故事信息2的详细信息")
|
||||
@ApiOperation(value="获取故事信息", notes = "获取故事信息的详细信息")
|
||||
@ApiMapping(value = "alipay.story.get")
|
||||
public StoryResult getStory(StoryParam param) {
|
||||
StoryResult story = new StoryResult();
|
||||
@@ -193,6 +193,7 @@ public class AlipayController {
|
||||
* @param param 对应biz_content中的内容,并自动JSR-303校验
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value="获取故事信息", notes = "获取故事信息的详细信息")
|
||||
@ApiMapping(value = "alipay.story.get", version = "1.2")
|
||||
public StoryResult getStory11(StoryParam param) {
|
||||
StoryResult story2 = new StoryResult();
|
||||
|
@@ -1,24 +1,11 @@
|
||||
server.port=8081
|
||||
# 固定不变,不能改
|
||||
spring.application.name=sop-gateway
|
||||
|
||||
# ------- 需要改的配置 -------
|
||||
# mysql数据库账号
|
||||
# mysql数据库配置
|
||||
mysql.host=localhost:3306
|
||||
mysql.username=root
|
||||
mysql.password=root
|
||||
|
||||
# nacos地址
|
||||
nacos.url=127.0.0.1:8848
|
||||
# ------- 需要改的配置end -------
|
||||
|
||||
# nacos cloud配置
|
||||
spring.cloud.nacos.discovery.server-addr=${nacos.url}
|
||||
|
||||
# 数据库配置
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.datasource.url=jdbc:mysql://${mysql.host}/sop?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
|
||||
spring.datasource.username=${mysql.username}
|
||||
spring.datasource.password=${mysql.password}
|
||||
|
||||
logging.level.com.gitee=debug
|
@@ -96,12 +96,30 @@
|
||||
</div>
|
||||
|
||||
<div class="site-content">
|
||||
<h1 class="site-h1"><i class="layui-icon layui-icon-slider"></i> <span class="sop-name"></span>(<span
|
||||
class="sop-summary"></span>)
|
||||
<h1 class="site-h1">
|
||||
<i class="layui-icon layui-icon-slider"></i><span class="sop-summary"></span> <span class="sop-version"></span>
|
||||
</h1>
|
||||
<blockquote class="layui-elem-quote layui-text sop-description">
|
||||
</blockquote>
|
||||
|
||||
<div class="site-text">
|
||||
<table class="layui-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 60px;background-color: #f2f2f2;">接口名</td>
|
||||
<td><span class="sop-name"></span></td>
|
||||
<td style="width: 60px;background-color: #f2f2f2;">版本号</td>
|
||||
<td style="width: 40px;"><span class="sop-version"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
<legend>接口描述</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
<!-- 接口描述 -->
|
||||
<div class="site-text sop-description"></div>
|
||||
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
|
@@ -61,7 +61,7 @@ layui.config({
|
||||
</li>
|
||||
*/
|
||||
html.push('<li class="site-tree-noicon" nameversion="'+docItem.nameVersion+'">');
|
||||
html.push('<a href="#"><cite>' + docItem['summary'] + '</cite></a>')
|
||||
html.push('<a href="#"><cite>' + docItem['summary'] + ' ' + docItem.version + '</cite></a>')
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -77,11 +77,30 @@
|
||||
</div>
|
||||
|
||||
<div class="site-content">
|
||||
<h1 class="site-h1"><i class="layui-icon layui-icon-slider"></i> <span class="sop-name"></span>(<span
|
||||
class="sop-summary"></span>)
|
||||
<h1 class="site-h1">
|
||||
<i class="layui-icon layui-icon-slider"></i><span class="sop-summary"></span> <span class="sop-version"></span>
|
||||
</h1>
|
||||
<blockquote class="layui-elem-quote layui-text sop-description">
|
||||
</blockquote>
|
||||
|
||||
<div class="site-text">
|
||||
<table class="layui-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 60px;background-color: #f2f2f2;">接口名</td>
|
||||
<td><span class="sop-name"></span></td>
|
||||
<td style="width: 60px;background-color: #f2f2f2;">版本号</td>
|
||||
<td style="width: 40px;"><span class="sop-version"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
<legend>接口描述</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
<!-- 接口描述 -->
|
||||
<div class="site-text sop-description"></div>
|
||||
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
|
Reference in New Issue
Block a user