From 99d90d60ccd0aeb898356601a21cbbb9b0eaba80 Mon Sep 17 00:00:00 2001 From: tanghc Date: Sun, 10 Mar 2019 21:55:53 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=E6=8E=A5easyopen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- sop-gateway-common/pom.xml | 144 +++++++++++------- .../sop/gatewaycommon/bean/ApiConfig.java | 5 + .../bean/BaseRouteDefinition.java | 5 + .../sop/gatewaycommon/bean/SopConstants.java | 4 +- .../easyopen/EasyopenResultExecutor.java | 27 ++++ .../easyopen/EasyopenSigner.java | 34 +++++ .../easyopen/EasyopenZuulConfiguration.java | 26 ++++ .../gateway/param/GatewayParamBuilder.java | 7 +- .../manager/BaseRouteManager.java | 35 +++-- .../manager/RouteDefinitionItemContext.java | 27 ++++ .../gatewaycommon/param/ApiParamFactory.java | 25 +++ .../result/BaseExecutorAdapter.java | 9 ++ .../gatewaycommon/result/ResultExecutor.java | 4 +- .../zuul/filter/PostResultFilter.java | 3 + .../zuul/filter/PreValidateFilter.java | 3 + .../zuul/param/ZuulParamBuilder.java | 23 +-- .../zuul/result/ZuulResultExecutor.java | 10 +- sop-gateway/pom.xml | 4 + .../gitee/sop/gateway/config/ZuulConfig.java | 13 +- sop-service-common/pom.xml | 125 ++++++++++----- .../servercommon/annotation/ApiAbility.java | 5 + .../servercommon/annotation/ApiMapping.java | 5 + .../sop/servercommon/bean/ServiceApiInfo.java | 2 + .../sop/servercommon/bean/ServiceConfig.java | 5 + .../BaseServiceConfiguration.java | 13 +- .../EasyopenServiceConfiguration.java | 102 +++++++++++++ .../manager/DefaultRequestMappingEvent.java | 72 +++++---- .../ServiceZookeeperApiMetaManager.java | 29 +++- .../mapping/ApiMappingHandlerMapping.java | 9 ++ .../servercommon/mapping/ApiMappingInfo.java | 1 + .../route/GatewayRouteDefinition.java | 2 + .../com/gitee/sop/EasyopenClientPostTest.java | 93 +++++++++++ 33 files changed, 710 insertions(+), 165 deletions(-) create mode 100644 sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenResultExecutor.java create mode 100644 sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenSigner.java create mode 100644 sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenZuulConfiguration.java create mode 100644 sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteDefinitionItemContext.java create mode 100644 sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ApiParamFactory.java create mode 100644 sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/EasyopenServiceConfiguration.java create mode 100644 sop-test/src/test/java/com/gitee/sop/EasyopenClientPostTest.java diff --git a/README.md b/README.md index bdf76e95..8512f4f7 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,11 @@ SOP封装了开放平台大部分功能包括:签名验证、统一异常处 - 秘钥管理 - 微服务端自动验证(JSR-303) - 支持Spring Cloud Gateway +- 关闭签名校验功能 +- 整合[easyopen](https://gitee.com/durcframework/easyopen) ## 后期规划 -- 关闭签名校验功能 -- 整合[easyopen](https://gitee.com/durcframework/easyopen) - 配置中心,Spring Cloud Config(Zookeeper) - Admin管理平台,统一管理微服务配置,管理路由信息,微服务上下线,API文档管理等功能 diff --git a/sop-gateway-common/pom.xml b/sop-gateway-common/pom.xml index 02114892..6a4d2c6f 100644 --- a/sop-gateway-common/pom.xml +++ b/sop-gateway-common/pom.xml @@ -2,21 +2,19 @@ 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.2.RELEASE - - com.gitee.sop sop-gateway-common 1.0.0-SNAPSHOT + jar sop-gateway-common sop-gateway-common 1.8 Greenwich.RELEASE + 2.1.2.RELEASE + 1.8 + 1.8 1.0.13 1.7.5 @@ -28,28 +26,44 @@ 2.5 1.3.3 3.2.2 - 1.4.7 - 1.7 - 6.0.10.Final - 0.31 - 3.2.0 - 18.0 - 1.8.8.RELEASE - 4.1.25.Final - 2.0.5.Final - 5.5.12 - 5.5.8 - 5.2.0 - 6.2 + 3.8.1 1.11 + 1.4.7 + 3.4.12 + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + org.springframework.cloud spring-cloud-starter-netflix-zuul true + + org.springframework.cloud + spring-cloud-netflix-ribbon + compile + + org.springframework.cloud spring-cloud-starter-gateway @@ -60,10 +74,6 @@ spring-boot-starter-webflux true - - org.springframework.boot - spring-boot-starter-actuator - @@ -84,7 +94,7 @@ org.apache.zookeeper zookeeper - 3.4.12 + ${zookeeper.version} org.slf4j @@ -93,11 +103,17 @@ + + org.springframework.boot + spring-boot-starter-data-redis + + org.springframework.boot spring-boot-starter-test test + com.thoughtworks.xstream xstream @@ -109,15 +125,11 @@ fastjson ${fastjson.version} - - org.springframework.boot - spring-boot-starter-data-redis - org.apache.commons commons-lang3 - 3.8.1 + ${commons-lang3.version} commons-collections @@ -151,42 +163,60 @@ 3.1.0 provided - - org.springframework.cloud - spring-cloud-netflix-ribbon - 2.1.0.RELEASE - compile - - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud.version} - pom - import - - - - + - org.springframework.boot - spring-boot-maven-plugin + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + UTF-8 + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9 + + + attach-javadocs + + jar + + + + -Xdoclint:none + + + - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - - diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java index ad230a20..13c7b25e 100644 --- a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java @@ -95,6 +95,11 @@ public class ApiConfig { */ private boolean ignoreValidate; + /** + * 是否对结果进行合并 + */ + private boolean mergeResult = true; + /** * 超时时间 */ diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/BaseRouteDefinition.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/BaseRouteDefinition.java index 2b51ef4f..e95605ca 100644 --- a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/BaseRouteDefinition.java +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/BaseRouteDefinition.java @@ -21,4 +21,9 @@ public class BaseRouteDefinition { * 路由执行的顺序 */ private int order = 0; + + /** + * 是否忽略验证,业务参数验证除外 + */ + private boolean ignoreValidate; } diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java index cbb100a1..6466edf5 100644 --- a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java @@ -32,7 +32,7 @@ public class SopConstants { public static final int BIZ_ERROR_STATUS = 4000; /** - * zookeeper存放接口信息的根目录 + * zookeeper存放接口路由信息的根目录 */ - public static final String SOP_SERVICE_API_PATH = "/sop-service-api"; + public static final String SOP_SERVICE_ROUTE_PATH = "/sop-service-route"; } diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenResultExecutor.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenResultExecutor.java new file mode 100644 index 00000000..2f1a2eac --- /dev/null +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenResultExecutor.java @@ -0,0 +1,27 @@ +package com.gitee.sop.gatewaycommon.easyopen; + +import com.alibaba.fastjson.JSON; +import com.gitee.sop.gatewaycommon.message.Error; +import com.gitee.sop.gatewaycommon.result.ApiResult; +import com.gitee.sop.gatewaycommon.result.ResultExecutor; +import com.gitee.sop.gatewaycommon.zuul.result.ZuulResultExecutor; +import com.netflix.zuul.context.RequestContext; + +/** + * @author tanghc + */ +public class EasyopenResultExecutor implements ResultExecutor { + @Override + public String mergeResult(RequestContext request, String serviceResult) { + return serviceResult; + } + + @Override + public String buildErrorResult(RequestContext request, Throwable ex) { + ApiResult apiResult = new ApiResult(); + Error error = ZuulResultExecutor.getError(ex); + apiResult.setCode(error.getSub_code()); + apiResult.setMsg(error.getSub_msg()); + return JSON.toJSONString(apiResult); + } +} diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenSigner.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenSigner.java new file mode 100644 index 00000000..d77eb6cd --- /dev/null +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenSigner.java @@ -0,0 +1,34 @@ +package com.gitee.sop.gatewaycommon.easyopen; + +import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.validate.AbstractSigner; +import com.gitee.sop.gatewaycommon.validate.taobao.TaobaoSigner; +import org.apache.commons.codec.digest.DigestUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * @author tanghc + */ +public class EasyopenSigner extends AbstractSigner { + @Override + protected String buildServerSign(ApiParam params, String secret) { + Set keySet = params.keySet(); + List paramNames = new ArrayList(keySet); + + Collections.sort(paramNames); + + StringBuilder paramNameValue = new StringBuilder(); + + for (String paramName : paramNames) { + paramNameValue.append(paramName).append(params.get(paramName)); + } + + String source = secret + paramNameValue.toString() + secret; + + return DigestUtils.md5Hex(source).toUpperCase(); + } +} diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenZuulConfiguration.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenZuulConfiguration.java new file mode 100644 index 00000000..cc8741eb --- /dev/null +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenZuulConfiguration.java @@ -0,0 +1,26 @@ +package com.gitee.sop.gatewaycommon.easyopen; + +import com.gitee.sop.gatewaycommon.bean.ApiConfig; +import com.gitee.sop.gatewaycommon.bean.ApiContext; +import com.gitee.sop.gatewaycommon.gateway.configuration.BaseGatewayConfiguration; +import com.gitee.sop.gatewaycommon.param.ParamNames; +import com.gitee.sop.gatewaycommon.validate.taobao.TaobaoSigner; +import com.gitee.sop.gatewaycommon.zuul.configuration.BaseZuulConfiguration; + +/** + * @author tanghc + */ +public class EasyopenZuulConfiguration extends BaseZuulConfiguration { + + static { + ParamNames.APP_KEY_NAME = "app_key"; + ParamNames.API_NAME = "name"; + ParamNames.SIGN_TYPE_NAME = "sign_type"; + ParamNames.APP_AUTH_TOKEN_NAME = "access_token"; + ApiConfig apiConfig = ApiContext.getApiConfig(); + apiConfig.setSigner(new EasyopenSigner()); + apiConfig.setZuulResultExecutor(new EasyopenResultExecutor()); + apiConfig.setMergeResult(false); + } + +} diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java index bcd898f0..a0954a2d 100644 --- a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java @@ -2,6 +2,7 @@ package com.gitee.sop.gatewaycommon.gateway.param; import com.gitee.sop.gatewaycommon.bean.SopConstants; import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.param.ApiParamFactory; import com.gitee.sop.gatewaycommon.param.ParamBuilder; import org.springframework.web.server.ServerWebExchange; @@ -14,11 +15,7 @@ public class GatewayParamBuilder implements ParamBuilder { @Override public ApiParam build(ServerWebExchange exchange) { Map params = exchange.getAttribute(SopConstants.CACHE_REQUEST_BODY_FOR_MAP); - ApiParam apiParam = new ApiParam(); - for (Map.Entry entry : params.entrySet()) { - apiParam.put(entry.getKey(), entry.getValue()); - } - return apiParam; + return ApiParamFactory.build(params); } diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteManager.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteManager.java index 74c10d73..867c9855 100644 --- a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteManager.java +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteManager.java @@ -16,7 +16,7 @@ import org.springframework.util.StringUtils; import java.util.List; -import static com.gitee.sop.gatewaycommon.bean.SopConstants.SOP_SERVICE_API_PATH; +import static com.gitee.sop.gatewaycommon.bean.SopConstants.SOP_SERVICE_ROUTE_PATH; /** @@ -30,7 +30,7 @@ import static com.gitee.sop.gatewaycommon.bean.SopConstants.SOP_SERVICE_API_PATH @Slf4j public abstract class BaseRouteManager, E extends BaseRouteDefinition, T> implements RouteManager { - protected String sopServiceApiPath = SOP_SERVICE_API_PATH; + protected String sopServiceApiPath = SOP_SERVICE_ROUTE_PATH; protected Environment environment; @@ -93,10 +93,7 @@ public abstract class BaseRouteManager, E exte String nodeData = new String(childData.getData()); log.info("\t* 子节点路径:" + childData.getPath() + ",该节点的数据为:" + nodeData); R serviceRouteInfo = JSON.parseObject(nodeData, getServiceRouteInfoClass()); - for (E routeDefinitionItem : serviceRouteInfo.getRouteDefinitionList()) { - T routeDefinition = buildRouteDefinition(serviceRouteInfo, routeDefinitionItem); - routeRepository.add(serviceRouteInfo, routeDefinition); - } + saveRouteDefinitionList(serviceRouteInfo); } // 添加事件监听器 childrenCache.getListenable().addListener(new PathChildrenCacheListener() { @@ -110,10 +107,7 @@ public abstract class BaseRouteManager, E exte R serviceRouteInfo = JSON.parseObject(nodeData, getServiceRouteInfoClass()); // 添加子节点时触发 log.info("子节点:{}添加,数据为:{}", event.getData().getPath(), nodeData); - for (E routeDefinitionItem : serviceRouteInfo.getRouteDefinitionList()) { - T routeDefinition = buildRouteDefinition(serviceRouteInfo, routeDefinitionItem); - routeRepository.add(serviceRouteInfo, routeDefinition); - } + saveRouteDefinitionList(serviceRouteInfo); } else if (PathChildrenCacheEvent.Type.CHILD_UPDATED.equals(type)) { String nodeData = new String(event.getData().getData()); R serviceRouteInfo = JSON.parseObject(nodeData, getServiceRouteInfoClass()); @@ -122,20 +116,31 @@ public abstract class BaseRouteManager, E exte // 删除下面所有节点 routeRepository.deleteAll(serviceRouteInfo); // 添加新节点 - for (E routeDefinitionItem : serviceRouteInfo.getRouteDefinitionList()) { - T routeDefinition = buildRouteDefinition(serviceRouteInfo, routeDefinitionItem); - routeRepository.add(serviceRouteInfo, routeDefinition); - } + saveRouteDefinitionList(serviceRouteInfo); } else if (PathChildrenCacheEvent.Type.CHILD_REMOVED.equals(type)) { String nodeData = new String(event.getData().getData()); log.info("子节点:{}删除,数据为:{}", event.getData().getPath(), nodeData); R serviceRouteInfo = JSON.parseObject(nodeData, getServiceRouteInfoClass()); - routeRepository.deleteAll(serviceRouteInfo); + deleteRouteDefinitionList(serviceRouteInfo); } } } }); } + protected void saveRouteDefinitionList(R serviceRouteInfo) { + for (E routeDefinitionItem : serviceRouteInfo.getRouteDefinitionList()) { + RouteDefinitionItemContext.add(routeDefinitionItem); + T routeDefinition = buildRouteDefinition(serviceRouteInfo, routeDefinitionItem); + routeRepository.add(serviceRouteInfo, routeDefinition); + } + } + + protected void deleteRouteDefinitionList(R serviceRouteInfo) { + for (E routeDefinitionItem : serviceRouteInfo.getRouteDefinitionList()) { + RouteDefinitionItemContext.delete(routeDefinitionItem); + } + routeRepository.deleteAll(serviceRouteInfo); + } } diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteDefinitionItemContext.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteDefinitionItemContext.java new file mode 100644 index 00000000..5e8802f0 --- /dev/null +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteDefinitionItemContext.java @@ -0,0 +1,27 @@ +package com.gitee.sop.gatewaycommon.manager; + +import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author tanghc + */ +public class RouteDefinitionItemContext { + // key:id + private static Map routeDefinitionMap = new HashMap<>(64); + + public static void add(BaseRouteDefinition routeDefinition) { + routeDefinitionMap.put(routeDefinition.getId(), routeDefinition); + } + + public static BaseRouteDefinition getRouteDefinition(String id) { + return routeDefinitionMap.get(id); + } + + public static void delete(BaseRouteDefinition routeDefinition) { + routeDefinitionMap.remove(routeDefinition.getId()); + } + +} diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ApiParamFactory.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ApiParamFactory.java new file mode 100644 index 00000000..8ecea4ef --- /dev/null +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ApiParamFactory.java @@ -0,0 +1,25 @@ +package com.gitee.sop.gatewaycommon.param; + +import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition; +import com.gitee.sop.gatewaycommon.manager.RouteDefinitionItemContext; +import com.gitee.sop.gatewaycommon.message.ErrorEnum; + +import java.util.Map; + +/** + * @author tanghc + */ +public class ApiParamFactory { + public static ApiParam build(Map params) { + ApiParam apiParam = new ApiParam(); + for (Map.Entry entry : params.entrySet()) { + apiParam.put(entry.getKey(), entry.getValue()); + } + BaseRouteDefinition routeDefinition = RouteDefinitionItemContext.getRouteDefinition(apiParam.fetchNameVersion()); + if (routeDefinition == null) { + throw ErrorEnum.ISV_INVALID_METHOD.getErrorMeta().getException(); + } + apiParam.setIgnoreValidate(routeDefinition.isIgnoreValidate()); + return apiParam; + } +} diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java index fc619085..26ed6030 100644 --- a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java @@ -2,10 +2,14 @@ package com.gitee.sop.gatewaycommon.result; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.gitee.sop.gatewaycommon.bean.ApiContext; import com.gitee.sop.gatewaycommon.bean.SopConstants; +import com.gitee.sop.gatewaycommon.exception.ApiException; +import com.gitee.sop.gatewaycommon.message.Error; import com.gitee.sop.gatewaycommon.message.ErrorEnum; import com.gitee.sop.gatewaycommon.message.ErrorMeta; import com.gitee.sop.gatewaycommon.param.ParamNames; +import com.netflix.zuul.exception.ZuulException; import org.springframework.http.HttpStatus; import org.springframework.util.StringUtils; @@ -45,6 +49,10 @@ public abstract class BaseExecutorAdapter implements ResultExecutor @Override public String mergeResult(T request, String serviceResult) { + boolean isMergeResult = ApiContext.getApiConfig().isMergeResult(); + if (!isMergeResult) { + return serviceResult; + } serviceResult = wrapResult(serviceResult); int responseStatus = this.getBizHeaderCode(request); JSONObject jsonObjectService; @@ -99,4 +107,5 @@ public abstract class BaseExecutorAdapter implements ResultExecutor ret.put(ParamNames.SIGN_NAME, sign); return ret.toJSONString(); } + } diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutor.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutor.java index b265a60f..f7a264df 100644 --- a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutor.java +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutor.java @@ -37,7 +37,7 @@ public interface ResultExecutor { * 合并结果 * @param request * @param serviceResult - * @return + * @return 返回最终输出结果 */ String mergeResult(T request, String serviceResult); @@ -45,7 +45,7 @@ public interface ResultExecutor { * 合并错误结果 * @param request * @param ex - * @return + * @return 返回最终输出结果 */ R buildErrorResult(T request, Throwable ex); } diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PostResultFilter.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PostResultFilter.java index 248b9b11..bafb3767 100644 --- a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PostResultFilter.java +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PostResultFilter.java @@ -30,6 +30,9 @@ public class PostResultFilter extends BaseZuulFilter { @Override protected Object doRun(RequestContext requestContext) throws ZuulException { + if (requestContext.getResponse().isCommitted()) { + return null; + } InputStream responseDataStream = requestContext.getResponseDataStream(); ApiConfig apiConfig = ApiContext.getApiConfig(); ResultExecutor resultExecutor = apiConfig.getZuulResultExecutor(); diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreValidateFilter.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreValidateFilter.java index ceec5e90..374c9652 100644 --- a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreValidateFilter.java +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreValidateFilter.java @@ -2,10 +2,13 @@ package com.gitee.sop.gatewaycommon.zuul.filter; import com.gitee.sop.gatewaycommon.bean.ApiContext; import com.gitee.sop.gatewaycommon.bean.ApiConfig; +import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition; import com.gitee.sop.gatewaycommon.exception.ApiException; +import com.gitee.sop.gatewaycommon.manager.RouteDefinitionItemContext; import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.validate.Validator; import com.gitee.sop.gatewaycommon.zuul.ZuulContext; +import com.gitee.sop.gatewaycommon.zuul.route.ZuulRouteDefinition; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParamBuilder.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParamBuilder.java index 87710181..a4e1556a 100644 --- a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParamBuilder.java +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParamBuilder.java @@ -1,14 +1,17 @@ package com.gitee.sop.gatewaycommon.zuul.param; import com.alibaba.fastjson.JSON; +import com.gitee.sop.gatewaycommon.bean.SopConstants; import com.gitee.sop.gatewaycommon.message.ErrorEnum; import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.param.ApiParamFactory; import com.gitee.sop.gatewaycommon.param.ApiUploadContext; import com.gitee.sop.gatewaycommon.param.ParamBuilder; import com.gitee.sop.gatewaycommon.util.RequestUtil; import com.gitee.sop.gatewaycommon.zuul.ZuulContext; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.http.HttpServletRequestWrapper; +import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; @@ -24,6 +27,7 @@ import java.util.Set; * * @author tanghc */ +@Slf4j public class ZuulParamBuilder implements ParamBuilder { private static final String CONTENT_TYPE_MULTIPART = MediaType.MULTIPART_FORM_DATA_VALUE; @@ -33,16 +37,12 @@ public class ZuulParamBuilder implements ParamBuilder { @Override public ApiParam build(RequestContext ctx) { - try { - HttpServletRequest request = ctx.getRequest(); - Map params = this.getJson(request); - return new ApiParam(params); - } catch (Exception e) { - throw ErrorEnum.ISV_INVALID_PARAMETER.getErrorMeta().getException(); - } + HttpServletRequest request = ctx.getRequest(); + Map params = this.getParams(request); + return ApiParamFactory.build(params); } - public Map getJson(HttpServletRequest request) throws Exception { + public Map getParams(HttpServletRequest request) { // zuul会做一层包装 if (request instanceof HttpServletRequestWrapper) { HttpServletRequestWrapper req = (HttpServletRequestWrapper) request; @@ -63,7 +63,12 @@ public class ZuulParamBuilder implements ParamBuilder { // json或者纯文本形式 if (contectType.contains(CONTENT_TYPE_JSON) || contectType.contains(CONTENT_TYPE_TEXT)) { - String txt = RequestUtil.getText(request); + String txt = SopConstants.EMPTY_JSON; + try { + txt = RequestUtil.getText(request); + } catch (Exception e) { + log.error("获取纯文本内容失败", e); + } params = JSON.parseObject(txt); } else if (contectType.contains(CONTENT_TYPE_MULTIPART)) { // 上传文件形式 diff --git a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java index f27805dd..753782fc 100644 --- a/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java +++ b/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java @@ -40,6 +40,12 @@ public class ZuulResultExecutor extends BaseExecutorAdapterorg.springframework.boot spring-boot-starter-webflux + + org.springframework.boot + spring-boot-starter-actuator + --> diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/config/ZuulConfig.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/config/ZuulConfig.java index 44b3818b..2bc294ba 100644 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/config/ZuulConfig.java +++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/config/ZuulConfig.java @@ -1,6 +1,7 @@ package com.gitee.sop.gateway.config; import com.gitee.sop.gatewaycommon.bean.ApiContext; +import com.gitee.sop.gatewaycommon.easyopen.EasyopenZuulConfiguration; import com.gitee.sop.gatewaycommon.zuul.configuration.AlipayZuulConfiguration; import com.gitee.sop.gatewaycommon.zuul.configuration.TaobaoZuulConfiguration; import org.springframework.context.annotation.Configuration; @@ -42,4 +43,14 @@ public class ZuulConfig extends AlipayZuulConfiguration { // } //} - +/** + * 对接easyopen + */ +//@Configuration +//public class ZuulConfig extends EasyopenZuulConfiguration { +// { +// Map appSecretStore = new HashMap(); +// appSecretStore.put("easyopen_test", "G9w0BAQEFAAOCAQ8AMIIBCgKCA"); +// ApiContext.getApiConfig().addAppSecret(appSecretStore); +// } +//} diff --git a/sop-service-common/pom.xml b/sop-service-common/pom.xml index 3d6f1341..0a3a3b0a 100644 --- a/sop-service-common/pom.xml +++ b/sop-service-common/pom.xml @@ -3,27 +3,53 @@ 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.2.RELEASE - - com.gitee.sop sop-service-common sop-service-common 1.0.0-SNAPSHOT + jar + 1.8 UTF-8 Greenwich.RELEASE + 2.1.2.RELEASE 1.8 1.8 - 1.8.8.RELEASE 1.2.15 + 3.4.12 + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-redis + + com.alibaba fastjson @@ -49,7 +75,7 @@ org.apache.zookeeper zookeeper - 3.4.12 + ${zookeeper.version} org.slf4j @@ -59,26 +85,25 @@ - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-data-redis + net.oschina.durcframework + easyopen + 1.16.0 + true - - org.apache.tomcat.embed - tomcat-embed-core - 9.0.14 - provided - + org.projectlombok lombok 1.18.4 provided + + javax.servlet + javax.servlet-api + 3.1.0 + provided + junit @@ -89,23 +114,55 @@ - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud.version} - pom - import - - - - + - org.springframework.boot - spring-boot-maven-plugin + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + UTF-8 + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9 + + + attach-javadocs + + jar + + + + -Xdoclint:none + + + diff --git a/sop-service-common/src/main/java/com/gitee/sop/servercommon/annotation/ApiAbility.java b/sop-service-common/src/main/java/com/gitee/sop/servercommon/annotation/ApiAbility.java index 91f2af05..07c5ba8c 100644 --- a/sop-service-common/src/main/java/com/gitee/sop/servercommon/annotation/ApiAbility.java +++ b/sop-service-common/src/main/java/com/gitee/sop/servercommon/annotation/ApiAbility.java @@ -20,4 +20,9 @@ public @interface ApiAbility { * 版本号,如:1.0 */ String version() default ""; + + /** + * 忽略验证,业务参数除外 + */ + boolean ignoreValidate() default false; } diff --git a/sop-service-common/src/main/java/com/gitee/sop/servercommon/annotation/ApiMapping.java b/sop-service-common/src/main/java/com/gitee/sop/servercommon/annotation/ApiMapping.java index 5a5a16d0..b728f9ce 100644 --- a/sop-service-common/src/main/java/com/gitee/sop/servercommon/annotation/ApiMapping.java +++ b/sop-service-common/src/main/java/com/gitee/sop/servercommon/annotation/ApiMapping.java @@ -27,6 +27,11 @@ public @interface ApiMapping { */ String version() default ""; + /** + * 忽略验证,业务参数除外 + */ + boolean ignoreValidate() default false; + /** * 接口名 * Alias for {@link RequestMapping#value}. diff --git a/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceApiInfo.java b/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceApiInfo.java index 3eb368f1..78ceca92 100644 --- a/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceApiInfo.java +++ b/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceApiInfo.java @@ -24,6 +24,8 @@ public class ServiceApiInfo { private String path; /** 版本号 */ private String version; + /** 是否忽略验证 */ + private boolean ignoreValidate; public ApiMeta() { } diff --git a/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceConfig.java b/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceConfig.java index a6292458..0d929ce9 100644 --- a/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceConfig.java +++ b/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceConfig.java @@ -47,6 +47,11 @@ public class ServiceConfig { */ private GlobalExceptionHandler globalExceptionHandler = new DefaultGlobalExceptionHandler(); + /** + * 设置为true,所有接口不进行校验 + */ + private boolean ignoreValidate; + public static ServiceConfig getInstance() { return instance; } diff --git a/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/BaseServiceConfiguration.java b/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/BaseServiceConfiguration.java index f8eba85a..72ce4e96 100644 --- a/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/BaseServiceConfiguration.java +++ b/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/BaseServiceConfiguration.java @@ -4,6 +4,7 @@ import com.gitee.sop.servercommon.bean.ServiceConfig; import com.gitee.sop.servercommon.interceptor.ServiceContextInterceptor; import com.gitee.sop.servercommon.manager.ApiMetaManager; import com.gitee.sop.servercommon.manager.DefaultRequestMappingEvent; +import com.gitee.sop.servercommon.manager.RequestMappingEvent; import com.gitee.sop.servercommon.manager.ServiceZookeeperApiMetaManager; import com.gitee.sop.servercommon.mapping.ApiMappingHandlerMapping; import com.gitee.sop.servercommon.message.ServiceErrorFactory; @@ -41,11 +42,19 @@ public class BaseServiceConfiguration extends WebMvcConfigurationSupport { */ @Override protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() { - ApiMetaManager apiMetaManager = new ServiceZookeeperApiMetaManager(environment); - DefaultRequestMappingEvent requestMappingEvent = new DefaultRequestMappingEvent(apiMetaManager, environment); + ApiMetaManager apiMetaManager = getApiMetaManager(environment); + RequestMappingEvent requestMappingEvent = getRequestMappingEvent(apiMetaManager, environment); return new ApiMappingHandlerMapping(requestMappingEvent); } + protected RequestMappingEvent getRequestMappingEvent(ApiMetaManager apiMetaManager, Environment environment) { + return new DefaultRequestMappingEvent(apiMetaManager, environment); + } + + protected ApiMetaManager getApiMetaManager(Environment environment) { + return new ServiceZookeeperApiMetaManager(environment); + } + @Bean GlobalExceptionHandler globalExceptionHandler() { return ServiceConfig.getInstance().getGlobalExceptionHandler(); diff --git a/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/EasyopenServiceConfiguration.java b/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/EasyopenServiceConfiguration.java new file mode 100644 index 00000000..090afcde --- /dev/null +++ b/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/EasyopenServiceConfiguration.java @@ -0,0 +1,102 @@ +package com.gitee.sop.servercommon.configuration; + +import com.gitee.easyopen.ApiContext; +import com.gitee.easyopen.annotation.Api; +import com.gitee.easyopen.annotation.ApiService; +import com.gitee.easyopen.util.ReflectionUtil; +import com.gitee.sop.servercommon.bean.ServiceApiInfo; +import com.gitee.sop.servercommon.manager.ApiMetaManager; +import com.gitee.sop.servercommon.manager.DefaultRequestMappingEvent; +import com.gitee.sop.servercommon.manager.RequestMappingEvent; +import com.gitee.sop.servercommon.mapping.ApiMappingHandlerMapping; +import org.springframework.context.ApplicationContext; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.env.Environment; +import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +/** + * 提供给easyopen项目使用 + * @author tanghc + */ +public class EasyopenServiceConfiguration extends BaseServiceConfiguration { + + @Override + protected RequestMappingEvent getRequestMappingEvent(ApiMetaManager apiMetaManager, Environment environment) { + return new EasyopenRequestMappingEvent(apiMetaManager, environment); + } + + class EasyopenRequestMappingEvent extends DefaultRequestMappingEvent { + String prefixPath; + + public EasyopenRequestMappingEvent(ApiMetaManager apiMetaManager, Environment environment) { + super(apiMetaManager, environment); + + String prefixPath = getEnvironment().getProperty("easyopen.prefix-path"); + if (prefixPath == null) { + throw new IllegalArgumentException("请在application.propertis中设置easyopen.prefix-path属性,填IndexController上面的@RequestMapping()中的值"); + } + this.prefixPath = prefixPath; + } + + @Override + protected List buildApiMetaList(ApiMappingHandlerMapping apiMappingHandlerMapping) { + ApplicationContext ctx = getApplicationContext(); + String[] apiServiceNames = ReflectionUtil.findApiServiceNames(ctx); + List apiMetaList = new ArrayList<>(); + for (String apiServiceName : apiServiceNames) { + Object bean = ctx.getBean(apiServiceName); + doWithMethods(bean.getClass(), method -> { + Api api = AnnotationUtils.findAnnotation(method, Api.class); + ServiceApiInfo.ApiMeta apiMeta = new ServiceApiInfo.ApiMeta(); + apiMeta.setName(api.name()); + apiMeta.setVersion(api.version()); + apiMeta.setIgnoreValidate(api.ignoreValidate()); + // /api/goods.get/ + String servletPath = this.buildPath(api); + apiMeta.setPath(servletPath); + apiMetaList.add(apiMeta); + }); + } + return apiMetaList; + } + + protected void doWithMethods(Class clazz, Consumer consumer) { + // Keep backing up the inheritance hierarchy. + Method[] methods = clazz.getDeclaredMethods(); + for (Method method : methods) { + boolean match = !method.isSynthetic() && AnnotationUtils.findAnnotation(method, Api.class) != null; + if (match) { + consumer.accept(method); + } + } + } + + protected String buildPath(Api api) { + // /api/goods.get/ + String servletPath = prefixPath + "/" + api.name() + "/"; + String version = api.version(); + if (StringUtils.hasLength(version)) { + // /api/goods.get/1.0/ + servletPath = servletPath + version + "/"; + } + return servletPath; + } + } + + @Override + public void after() { + super.after(); + // 取消验证 + // todo:需要在easyopen端修改 + //ApiContext.getApiConfig().setIgnoreValidate(true); + } +} diff --git a/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/DefaultRequestMappingEvent.java b/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/DefaultRequestMappingEvent.java index 06d29b3f..51c9394e 100644 --- a/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/DefaultRequestMappingEvent.java +++ b/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/DefaultRequestMappingEvent.java @@ -35,38 +35,11 @@ public class DefaultRequestMappingEvent implements RequestMappingEvent { @Override public void onRegisterSuccess(ApiMappingHandlerMapping apiMappingHandlerMapping) { - Map handlerMethods = apiMappingHandlerMapping.getHandlerMethods(); - Set requestMappingInfos = handlerMethods.keySet(); - List store = new ArrayList<>(requestMappingInfos.size()); - List apis = new ArrayList<>(requestMappingInfos.size()); - - for (RequestMappingInfo requestMappingInfo : requestMappingInfos) { - Set patterns = requestMappingInfo.getPatternsCondition().getPatterns(); - RequestCondition customCondition = requestMappingInfo.getCustomCondition(); - if (customCondition instanceof ApiMappingRequestCondition) { - ApiMappingRequestCondition condition = (ApiMappingRequestCondition) customCondition; - ApiMappingInfo apiMappingInfo = condition.getApiMappingInfo(); - String name = apiMappingInfo.getName(); - String version = apiMappingInfo.getVersion(); - String path = patterns.iterator().next(); - // 不是ApiMapping注解的接口,name属性是null - if (name == null) { - name = buildName(path); - } - String key = path + version; - if (store.contains(key)) { - throw new RuntimeException("重复申明接口,请检查path和version,path:" + path + ", version:" + version); - } else { - store.add(key); - } - apis.add(new ServiceApiInfo.ApiMeta(name, path, version)); - } - } - String appName = environment.getProperty("spring.application.name"); if (appName == null) { throw new RuntimeException("请在application.properties中指定spring.application.name属性"); } + List apis = this.buildApiMetaList(apiMappingHandlerMapping); // 排序 Collections.sort(apis, new Comparator() { @Override @@ -83,6 +56,49 @@ public class DefaultRequestMappingEvent implements RequestMappingEvent { apiMetaManager.uploadApi(serviceApiInfo); } + protected List buildApiMetaList(ApiMappingHandlerMapping apiMappingHandlerMapping) { + Map handlerMethods = apiMappingHandlerMapping.getHandlerMethods(); + Set requestMappingInfos = handlerMethods.keySet(); + List store = new ArrayList<>(); + List apis = new ArrayList<>(requestMappingInfos.size()); + + for (Map.Entry handlerMethodEntry : handlerMethods.entrySet()) { + ServiceApiInfo.ApiMeta apiMeta = this.buildApiMeta(handlerMethodEntry); + if (apiMeta == null) { + continue; + } + String key = apiMeta.fetchNameVersion(); + if (store.contains(key)) { + throw new RuntimeException("重复申明接口,请检查path和version,path:" + apiMeta.getPath() + ", version:" + apiMeta.getVersion()); + } else { + store.add(key); + } + apis.add(apiMeta); + } + return apis; + } + + protected ServiceApiInfo.ApiMeta buildApiMeta(Map.Entry handlerMethodEntry) { + RequestMappingInfo requestMappingInfo = handlerMethodEntry.getKey(); + Set patterns = requestMappingInfo.getPatternsCondition().getPatterns(); + RequestCondition customCondition = requestMappingInfo.getCustomCondition(); + if (customCondition instanceof ApiMappingRequestCondition) { + ApiMappingRequestCondition condition = (ApiMappingRequestCondition) customCondition; + ApiMappingInfo apiMappingInfo = condition.getApiMappingInfo(); + String name = apiMappingInfo.getName(); + String version = apiMappingInfo.getVersion(); + String path = patterns.iterator().next(); + // 不是ApiMapping注解的接口,name属性是null + if (name == null) { + name = buildName(path); + } + ServiceApiInfo.ApiMeta apiMeta = new ServiceApiInfo.ApiMeta(name, path, version); + apiMeta.setIgnoreValidate(apiMappingInfo.isIgnoreValidate()); + return apiMeta; + } + return null; + } + protected String buildName(String path) { path = StringUtils.trimLeadingCharacter(path, '/'); path = StringUtils.trimTrailingCharacter(path, '/'); diff --git a/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java b/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java index 06379318..6788c619 100644 --- a/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java +++ b/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java @@ -27,6 +27,11 @@ import java.util.List; @Setter public class ServiceZookeeperApiMetaManager implements ApiMetaManager { + /** + * zookeeper存放接口路由信息的根目录 + */ + public static final String SOP_SERVICE_ROUTE_PATH = "/sop-service-route"; + public static final String PATH_START_CHAR = "/"; /** * NameVersion=alipay.story.get1.0 @@ -36,8 +41,6 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager { private static ServiceApiInfo.ApiMeta FIRST_API_META = new ServiceApiInfo.ApiMeta("_" + System.currentTimeMillis() + "_", "/", "0.0"); - private String sopServiceApiPath = "/sop-service-api"; - private Environment environment; public ServiceZookeeperApiMetaManager(Environment environment) { @@ -97,11 +100,27 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager { List predicates = Arrays.asList(this.buildNameVersionPredicateDefinition(apiMeta)); gatewayRouteDefinition.setPredicates(predicates); // lb://story-service#/alipay.story.get/ - String servletPath = "#" + apiMeta.getPath(); - gatewayRouteDefinition.setUri("lb://" + serviceApiInfo.getAppName() + servletPath); + String uri = this.buildUri(serviceApiInfo, apiMeta); + gatewayRouteDefinition.setUri(uri); + gatewayRouteDefinition.setIgnoreValidate(apiMeta.isIgnoreValidate()); return gatewayRouteDefinition; } + protected String buildUri(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) { + String servletPath = getServletPath(serviceApiInfo, apiMeta); + if (servletPath == null) { + servletPath = PATH_START_CHAR; + } + if (!servletPath.startsWith(PATH_START_CHAR)) { + servletPath = PATH_START_CHAR + servletPath; + } + return "lb://" + serviceApiInfo.getAppName() + "#" + servletPath; + } + + protected String getServletPath(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) { + return apiMeta.getPath(); + } + protected GatewayPredicateDefinition buildNameVersionPredicateDefinition(ServiceApiInfo.ApiMeta apiMeta) { return new GatewayPredicateDefinition(String.format(QUERY_PREDICATE_DEFINITION_TPL, apiMeta.fetchNameVersion())); } @@ -120,7 +139,7 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager { CuratorFramework client = null; try { // 保存路径 - String savePath = sopServiceApiPath + "/" + serviceRouteInfo.getAppName(); + String savePath = SOP_SERVICE_ROUTE_PATH + "/" + serviceRouteInfo.getAppName(); client = CuratorFrameworkFactory.builder() .connectString(zookeeperServerAddr) diff --git a/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java b/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java index 1c2b9c66..733fe290 100644 --- a/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java +++ b/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java @@ -3,6 +3,7 @@ package com.gitee.sop.servercommon.mapping; import com.gitee.sop.servercommon.annotation.ApiMapping; import com.gitee.sop.servercommon.annotation.ApiAbility; import com.gitee.sop.servercommon.bean.ServiceConfig; +import com.gitee.sop.servercommon.bean.ServiceContext; import com.gitee.sop.servercommon.manager.RequestMappingEvent; import org.springframework.core.PriorityOrdered; import org.springframework.core.annotation.AnnotationUtils; @@ -42,14 +43,17 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple method.setAccessible(true); String name = null; String version; + boolean ignoreValidate = false; ApiMapping apiMapping = method.getAnnotation(ApiMapping.class); if (apiMapping != null) { name = apiMapping.value()[0]; version = apiMapping.version(); + ignoreValidate = apiMapping.ignoreValidate(); } else { ApiAbility apiAbility = this.findApiAbilityAnnotation(method); if (apiAbility != null) { version = apiAbility.version(); + ignoreValidate = apiAbility.ignoreValidate(); } else { return super.getCustomMethodCondition(method); } @@ -58,6 +62,11 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple version = ServiceConfig.getInstance().getDefaultVersion(); } ApiMappingInfo apiMappingInfo = new ApiMappingInfo(name, version); + // 如果是默认配置,则采用全局配置 + if (!ignoreValidate) { + ignoreValidate = ServiceConfig.getInstance().isIgnoreValidate(); + } + apiMappingInfo.setIgnoreValidate(ignoreValidate); logger.info("注册接口,method:" + method + ", version:" + version); return new ApiMappingRequestCondition(apiMappingInfo); } diff --git a/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingInfo.java b/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingInfo.java index 3f14ba6c..79da7a65 100644 --- a/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingInfo.java +++ b/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingInfo.java @@ -9,6 +9,7 @@ import lombok.Data; public class ApiMappingInfo { private String name; private String version; + private boolean ignoreValidate; public ApiMappingInfo(String name, String version) { this.name = name; diff --git a/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/GatewayRouteDefinition.java b/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/GatewayRouteDefinition.java index 6227c95f..5d70d1be 100644 --- a/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/GatewayRouteDefinition.java +++ b/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/GatewayRouteDefinition.java @@ -20,4 +20,6 @@ public class GatewayRouteDefinition { private String uri; /** 路由执行的顺序 */ private int order = 0; + /** 是否忽略验证,业务参数验证除外 */ + private boolean ignoreValidate; } \ No newline at end of file diff --git a/sop-test/src/test/java/com/gitee/sop/EasyopenClientPostTest.java b/sop-test/src/test/java/com/gitee/sop/EasyopenClientPostTest.java new file mode 100644 index 00000000..a1445034 --- /dev/null +++ b/sop-test/src/test/java/com/gitee/sop/EasyopenClientPostTest.java @@ -0,0 +1,93 @@ +package com.gitee.sop; + +import com.alibaba.fastjson.JSON; +import junit.framework.TestCase; +import org.apache.commons.codec.digest.DigestUtils; +import org.junit.Test; + +import java.io.IOException; +import java.net.URLEncoder; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author tanghc + */ +public class EasyopenClientPostTest extends TestBase { + + String url = "http://localhost:8081/api"; + String appKey = "easyopen_test"; + String secret = "G9w0BAQEFAAOCAQ8AMIIBCgKCA"; + + @Test + public void testPost() throws IOException { + // 业务参数 + Map bizParams = new HashMap(); + bizParams.put("goods_name", "iphoneX"); + + String json = JSON.toJSONString(bizParams); + json = URLEncoder.encode(json, "utf-8"); + + // 系统参数 + Map params = new HashMap<>(); + params.put("name", "goods.get"); + params.put("app_key", appKey); + params.put("data", json); + params.put("timestamp", getTime()); + params.put("version", ""); + + String sign = buildSign(params, secret); + + params.put("sign", sign); + + System.out.println("=====请求数据====="); + System.out.println(JSON.toJSONString(params)); + System.out.println("=====返回结果====="); + String resp = post(url, params); + System.out.println(resp); + } + + /** + * 构建签名串 + * @param paramsMap 请求参数 + * @param secret 秘钥 + * @return + * @throws IOException + */ + public String buildSign(Map paramsMap, String secret) throws IOException { + Set keySet = paramsMap.keySet(); + List paramNames = new ArrayList(keySet); + + Collections.sort(paramNames); + + StringBuilder paramNameValue = new StringBuilder(); + + for (String paramName : paramNames) { + paramNameValue.append(paramName).append(paramsMap.get(paramName)); + } + + String source = secret + paramNameValue.toString() + secret; + + return md5(source); + } + + /** + * 生成md5,全部大写。 + * + * @param source + * @return + */ + public static String md5(String source) { + return DigestUtils.md5Hex(source).toUpperCase(); + } + + public String getTime() { + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); + } +}