From 6125625b876572121199b3e0db9c15be53cdb875 Mon Sep 17 00:00:00 2001 From: tanghc Date: Wed, 31 Jul 2019 20:00:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=A2=84=E5=8F=91=E5=B8=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adminserver/api/service/ServiceApi.java | 48 +++++++++++- .../api/service/result/ServiceInstanceVO.java | 5 ++ .../sop/adminserver/bean/MetadataEnum.java | 37 ++++++++++ .../src/views/service/serviceList.vue | 73 ++++++++++++++++--- .../sop/gatewaycommon/bean/SopConstants.java | 1 + .../gateway/result/GatewayResultExecutor.java | 2 +- .../route/ReadBodyRoutePredicateFactory.java | 2 +- .../sop/gatewaycommon/message/ErrorEnum.java | 4 +- .../gatewaycommon/message/ErrorFactory.java | 4 +- .../gatewaycommon/param/BaseParamBuilder.java | 2 +- .../result/BaseExecutorAdapter.java | 2 +- .../result/CustomDataNameBuilder.java | 2 +- .../result/DefaultDataNameBuilder.java | 2 +- .../gatewaycommon/result/ResultExecutor.java | 2 +- .../session/ApiSessionManager.java | 2 +- .../zuul/loadbalancer/BaseServerChooser.java | 72 ++++++++++++++++++ .../zuul/result/ZuulResultExecutor.java | 2 +- .../sop/registryapi/bean/EurekaInstance.java | 41 +++++++++++ .../gitee/sop/registryapi/bean/EurekaUri.java | 10 +++ .../gitee/sop/registryapi}/bean/HttpTool.java | 21 +++--- .../sop/registryapi/bean/ServiceInstance.java | 8 ++ .../registryapi/service/RegistryService.java | 9 +++ .../service/impl/RegistryServiceEureka.java | 6 ++ .../service/impl/RegistryServiceNacos.java | 67 +++++++++++------ .../message/ServiceErrorEnum.java | 2 +- .../resources/i18n/isp/error_en.properties | 2 +- .../resources/i18n/isp/error_zh_CN.properties | 2 +- .../gitee/sop/gateway/config/ZuulConfig.java | 8 ++ .../PreEnvironmentServerChooser.java | 55 ++++++++++++++ .../loadbalancer/SopPropertiesFactory.java | 39 ++++++++++ .../sop/sdk/common/CustomDataNameBuilder.java | 2 +- .../sdk/common/DefaultDataNameBuilder.java | 2 +- .../gitee/sop/sdk/response/BaseResponse.java | 2 +- .../java/com/gitee/sop/test/HttpTool.java | 16 ++-- sop-website/website-front/pages/doc/code.html | 2 +- .../website-front/pages/doc/docEvent.js | 2 +- .../controller/SandboxController.java | 4 +- 37 files changed, 484 insertions(+), 78 deletions(-) create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/MetadataEnum.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java rename {sop-website/website-server/src/main/java/com/gitee/sop/websiteserver => sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi}/bean/HttpTool.java (94%) create mode 100644 sop-gateway/src/main/java/com/gitee/sop/gateway/loadbalancer/PreEnvironmentServerChooser.java create mode 100644 sop-gateway/src/main/java/com/gitee/sop/gateway/loadbalancer/SopPropertiesFactory.java diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java index a80393e5..fa3d4b0a 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java @@ -10,6 +10,7 @@ import com.gitee.sop.adminserver.api.service.param.ServiceSearchParam; import com.gitee.sop.adminserver.api.service.result.RouteServiceInfo; import com.gitee.sop.adminserver.api.service.result.ServiceInfoVo; import com.gitee.sop.adminserver.api.service.result.ServiceInstanceVO; +import com.gitee.sop.adminserver.bean.MetadataEnum; import com.gitee.sop.adminserver.bean.ServiceRouteInfo; import com.gitee.sop.adminserver.bean.ZookeeperContext; import com.gitee.sop.adminserver.common.BizException; @@ -144,6 +145,9 @@ public class ServiceApi { int id = idGen.getAndIncrement(); instanceVO.setId(id); instanceVO.setParentId(pid); + if (instanceVO.getMetadata() == null) { + instanceVO.setMetadata(Collections.emptyMap()); + } serviceInfoVoList.add(instanceVO); } }); @@ -152,21 +156,57 @@ public class ServiceApi { } @Api(name = "service.instance.offline") - @ApiDocMethod(description = "服务下线") + @ApiDocMethod(description = "服务禁用") void serviceOffline(ServiceInstance param) { try { registryService.offlineInstance(param); } catch (Exception e) { - log.error("下线失败,param:{}", param, e); - throw new BizException("下线失败,请查看日志"); + log.error("服务禁用失败,param:{}", param, e); + throw new BizException("服务禁用失败,请查看日志"); } } @Api(name = "service.instance.online") - @ApiDocMethod(description = "服务上线") + @ApiDocMethod(description = "服务启用") void serviceOnline(ServiceInstance param) throws IOException { try { registryService.onlineInstance(param); + } catch (Exception e) { + log.error("服务启用失败,param:{}", param, e); + throw new BizException("服务启用失败,请查看日志"); + } + } + + @Api(name = "service.instance.env.pre") + @ApiDocMethod(description = "预发布") + void serviceEnvPre(ServiceInstance param) throws IOException { + try { + MetadataEnum envPre = MetadataEnum.ENV_PRE; + registryService.setMetadata(param, envPre.getKey(), envPre.getValue()); + } catch (Exception e) { + log.error("预发布失败,param:{}", param, e); + throw new BizException("预发布失败,请查看日志"); + } + } + + @Api(name = "service.instance.env.gray") + @ApiDocMethod(description = "灰度发布") + void serviceEnvGray(ServiceInstance param) throws IOException { + try { + MetadataEnum envPre = MetadataEnum.ENV_GRAY; + registryService.setMetadata(param, envPre.getKey(), envPre.getValue()); + } catch (Exception e) { + log.error("灰度发布失败,param:{}", param, e); + throw new BizException("灰度发布失败,请查看日志"); + } + } + + @Api(name = "service.instance.env.online") + @ApiDocMethod(description = "上线") + void serviceEnvOnline(ServiceInstance param) throws IOException { + try { + MetadataEnum envPre = MetadataEnum.ENV_ONLINE; + registryService.setMetadata(param, envPre.getKey(), envPre.getValue()); } catch (Exception e) { log.error("上线失败,param:{}", param, e); throw new BizException("上线失败,请查看日志"); diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java index 7cffb7de..9c48e516 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java @@ -3,6 +3,8 @@ package com.gitee.sop.adminserver.api.service.result; import com.gitee.easyopen.doc.annotation.ApiDocField; import lombok.Data; +import java.util.Map; + /** * @author tanghc */ @@ -35,6 +37,9 @@ public class ServiceInstanceVO { @ApiDocField(description = "parentId") private Integer parentId; + @ApiDocField(description = "metadata") + private Map metadata; + public String getIpPort() { return ip != null && port > 0 ? ip + ":" + port : ""; } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/MetadataEnum.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/MetadataEnum.java new file mode 100644 index 00000000..2eb5f25b --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/MetadataEnum.java @@ -0,0 +1,37 @@ +package com.gitee.sop.adminserver.bean; + +/** + * @author tanghc + */ +public enum MetadataEnum { + /** + * 预发布环境 + */ + ENV_PRE("env", "pre"), + + /** + * 上线环境 + */ + ENV_ONLINE("env", ""), + + /** + * 灰度环境 + */ + ENV_GRAY("env", "gray"), + ; + private String key,value; + + MetadataEnum(String key, String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + +} diff --git a/sop-admin/sop-admin-vue/src/views/service/serviceList.vue b/sop-admin/sop-admin-vue/src/views/service/serviceList.vue index 9572923c..4de2689c 100644 --- a/sop-admin/sop-admin-vue/src/views/service/serviceList.vue +++ b/sop-admin/sop-admin-vue/src/views/service/serviceList.vue @@ -28,16 +28,36 @@ label="IP端口" width="250" /> + + + + + + @@ -103,22 +126,46 @@ export default { onSearchTable: function() { this.loadTable() }, - onOffline: function(row) { - this.confirm('确定要下线【' + row.serviceId + '】吗?', function(done) { + onDisable: function(row) { + this.confirm('确定要禁用【' + row.serviceId + '】吗?', function(done) { this.post('service.instance.offline', row, function() { this.tip('下线成功') done() }) }) }, - onOnline: function(row) { - this.confirm('确定要上线【' + row.serviceId + '】吗?', function(done) { + onEnable: function(row) { + this.confirm('确定要启用【' + row.serviceId + '】吗?', function(done) { this.post('service.instance.online', row, function() { this.tip('上线成功') done() }) }) }, + onEnvOnline: function(row) { + this.confirm('确定要上线【' + row.serviceId + '】吗?', function(done) { + this.post('service.instance.env.online', row, function() { + this.tip('上线成功') + done() + }) + }) + }, + onEnvPre: function(row) { + this.confirm('确定要预发布【' + row.serviceId + '】吗?', function(done) { + this.post('service.instance.env.pre', row, function() { + this.tip('预发布成功') + done() + }) + }) + }, + onEnvGray: function(row) { + this.confirm('确定要灰度发布【' + row.serviceId + '】吗?', function(done) { + this.post('service.instance.env.gray', row, function() { + this.tip('灰度发布发成功') + done() + }) + }) + }, renderServiceName: function(row) { let instanceCount = '' if (row.children && row.children.length > 0) { @@ -128,6 +175,14 @@ export default { instanceCount = ` (${onlineCount}/${row.children.length})` } return row.serviceId + instanceCount + }, + renderMetadata: function(row) { + const metadata = row.metadata + const html = [] + for (const key in metadata) { + html.push(key + '=' + metadata[key]) + } + return html.join('
') } } } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java index 7ed69b01..4a3f5c99 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java @@ -54,4 +54,5 @@ public class SopConstants { public static final String UNKNOWN_SERVICE= "_sop_unknown_service_"; public static final String UNKNOWN_METHOD = "_sop_unknown_method_"; public static final String UNKNOWN_VERSION = "_sop_unknown_version_"; + } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/result/GatewayResultExecutor.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/result/GatewayResultExecutor.java index 884e013a..f7724b29 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/result/GatewayResultExecutor.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/result/GatewayResultExecutor.java @@ -69,7 +69,7 @@ public class GatewayResultExecutor extends BaseExecutorAdapterString solution = getErrorMessage(modulePrefix + code + UNDERLINE + subCode + "_solution", locale, params); error = new ErrorImpl(code, msg, subCode, subMsg, null); errorCache.put(key, error); diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/BaseParamBuilder.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/BaseParamBuilder.java index 36aa6458..fcb1849f 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/BaseParamBuilder.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/BaseParamBuilder.java @@ -51,7 +51,7 @@ public abstract class BaseParamBuilder implements ParamBuilder { RouteRepository routeRepository = RouteRepositoryContext.getRouteRepository(); if (routeRepository == null) { log.error("RouteRepositoryContext.setRouteRepository()方法未使用"); - throw ErrorEnum.AOP_UNKNOW_ERROR.getErrorMeta().getException(); + throw ErrorEnum.ISP_UNKNOWN_ERROR.getErrorMeta().getException(); } String nameVersion = Optional.ofNullable(apiParam.fetchNameVersion()).orElse(String.valueOf(System.currentTimeMillis())); diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java index 4307e7c6..14751f84 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java @@ -35,7 +35,7 @@ import java.util.Optional; @Slf4j public abstract class BaseExecutorAdapter implements ResultExecutor { private static final ErrorMeta SUCCESS_META = ErrorEnum.SUCCESS.getErrorMeta(); - private static final ErrorMeta ISP_UNKNOW_ERROR_META = ErrorEnum.ISP_UNKNOW_ERROR.getErrorMeta(); + private static final ErrorMeta ISP_UNKNOW_ERROR_META = ErrorEnum.ISP_UNKNOWN_ERROR.getErrorMeta(); private static final ErrorMeta ISP_BIZ_ERROR = ErrorEnum.BIZ_ERROR.getErrorMeta(); public static final String GATEWAY_CODE_NAME = "code"; diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/CustomDataNameBuilder.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/CustomDataNameBuilder.java index 5e710d1f..726db193 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/CustomDataNameBuilder.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/CustomDataNameBuilder.java @@ -6,7 +6,7 @@ package com.gitee.sop.gatewaycommon.result; * "result": { * "code": "20000", * "msg": "Service Currently Unavailable", - * "sub_code": "isp.unknow-error", + * "sub_code": "isp.unknown-error", * "sub_msg": "系统繁忙" * }, * "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE" diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/DefaultDataNameBuilder.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/DefaultDataNameBuilder.java index 987041ec..1cb5d0be 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/DefaultDataNameBuilder.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/DefaultDataNameBuilder.java @@ -8,7 +8,7 @@ package com.gitee.sop.gatewaycommon.result; * "alipay_trade_order_settle_response": { * "code": "20000", * "msg": "Service Currently Unavailable", - * "sub_code": "isp.unknow-error", + * "sub_code": "isp.unknown-error", * "sub_msg": "系统繁忙" * }, * "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE" diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutor.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutor.java index d20ff5ea..051b988b 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutor.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutor.java @@ -22,7 +22,7 @@ package com.gitee.sop.gatewaycommon.result; * "alipay_trade_fastpay_refund_query_response": { * "code": "20000", * "msg": "Service Currently Unavailable", - * "sub_code": "isp.unknow-error", + * "sub_code": "isp.unknown-error", * "sub_msg": "系统繁忙" * }, * "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE" diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/ApiSessionManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/ApiSessionManager.java index 5791ef38..19d2d742 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/ApiSessionManager.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/ApiSessionManager.java @@ -36,7 +36,7 @@ public class ApiSessionManager implements SessionManager { return cache.get(sessionId); } catch (Exception e) { logger.error(e.getMessage(), e); - throw ErrorEnum.AOP_UNKNOW_ERROR.getErrorMeta().getException(); + throw ErrorEnum.ISP_UNKNOWN_ERROR.getErrorMeta().getException(); } } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java new file mode 100644 index 00000000..bbda7bef --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java @@ -0,0 +1,72 @@ +package com.gitee.sop.gatewaycommon.zuul.loadbalancer; + +import com.google.common.base.Optional; +import com.netflix.loadbalancer.ILoadBalancer; +import com.netflix.loadbalancer.Server; +import com.netflix.loadbalancer.ZoneAvoidanceRule; +import com.netflix.zuul.context.RequestContext; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; + +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.List; + +/** + * 服务实例选择器 + * + * @author tanghc + */ +@Slf4j +public abstract class BaseServerChooser extends ZoneAvoidanceRule { + + /** + * 是否匹配对应的服务器,可在此判断是否是预发布,灰度环境 + * + * @param server 指定服务器 + * @return 返回true:是 + */ + protected abstract boolean match(Server server); + + /** + * 客户端能否够访问服务器 + * + * @param server 服务器实例 + * @param request request + * @return 返回true:能访问 + */ + protected abstract boolean canVisit(Server server, HttpServletRequest request); + + @Override + public Server choose(Object key) { + ILoadBalancer lb = getLoadBalancer(); + // 获取服务实例列表 + List allServers = new ArrayList<>(lb.getAllServers()); + int index = -1; + for (int i = 0; i < allServers.size(); i++) { + Server server = allServers.get(i); + if (match(server)) { + index = i; + if (canVisit(server, RequestContext.getCurrentContext().getRequest())) { + return server; + } + } + } + // 调用默认的算法 + // 如果选出了特殊环境服务器,需要移除命中的服务器 + if (index > -1) { + allServers.remove(index); + } + if (CollectionUtils.isEmpty(allServers)) { + log.error("无可用服务实例,key:", key); + return null; + } + Optional server = getPredicate().chooseRoundRobinAfterFiltering(allServers, key); + if (server.isPresent()) { + return server.get(); + } else { + return null; + } + } + +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java index aee316f7..526a90b0 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java @@ -76,7 +76,7 @@ public class ZuulResultExecutor extends BaseExecutorAdapter metadata; + public String fetchPort() { if (CollectionUtils.isEmpty(port)) { return ""; diff --git a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java index 8a229ca7..2a76893e 100644 --- a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java @@ -16,6 +16,10 @@ public enum EurekaUri { * 查询所有实例 Query for all instances */ QUERY_APPS("GET", "/apps"), + /** + * 查询一个实例 + */ + QUERY_INSTANCES("GET", "/instances/%s"), /** * 下线 Take instance out of service */ @@ -24,6 +28,12 @@ public enum EurekaUri { * 上线 Move instance back into service (remove override) */ ONLINE_SERVICE("DELETE", "/apps/%s/%s/status?value=UP"), + /** + * 设置metadata信息 + * + * /apps/{appID}/{instanceID}/metadata?key=value + */ + SET_METADATA("PUT", "/apps/%s/%s/metadata?%s=%s") ; public static final String URL_PREFIX = "/"; diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/HttpTool.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/HttpTool.java similarity index 94% rename from sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/HttpTool.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/HttpTool.java index 8e0cce0e..f323e0d7 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/HttpTool.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/HttpTool.java @@ -1,4 +1,4 @@ -package com.gitee.sop.websiteserver.bean; +package com.gitee.sop.registryapi.bean; import lombok.Data; import lombok.Getter; @@ -110,7 +110,7 @@ public class HttpTool { * @return * @throws IOException */ - public String request(String url, Map form, Map header, HTTPMethod method) throws IOException { + public String request(String url, Map form, Map header, HTTPMethod method) throws IOException { Request.Builder requestBuilder = buildRequestBuilder(url, form, method.value()); // 添加header addHeader(requestBuilder, header); @@ -153,7 +153,7 @@ public class HttpTool { } } - public static Request.Builder buildRequestBuilder(String url, Map form, String method) { + public static Request.Builder buildRequestBuilder(String url, Map form, String method) { switch (method) { case "get": return new Request.Builder() @@ -178,18 +178,18 @@ public class HttpTool { } } - public static HttpUrl buildHttpUrl(String url, Map form) { + public static HttpUrl buildHttpUrl(String url, Map form) { HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder(); - for (Map.Entry entry : form.entrySet()) { - urlBuilder.addQueryParameter(entry.getKey(), entry.getValue()); + for (Map.Entry entry : form.entrySet()) { + urlBuilder.addQueryParameter(entry.getKey(), String.valueOf(entry.getValue())); } return urlBuilder.build(); } - public static FormBody buildFormBody(Map form) { + public static FormBody buildFormBody(Map form) { FormBody.Builder paramBuilder = new FormBody.Builder(StandardCharsets.UTF_8); - for (Map.Entry entry : form.entrySet()) { - paramBuilder.add(entry.getKey(), entry.getValue()); + for (Map.Entry entry : form.entrySet()) { + paramBuilder.add(entry.getKey(), String.valueOf(entry.getValue())); } return paramBuilder.build(); } @@ -262,6 +262,9 @@ public class HttpTool { HEAD, DELETE; + private HTTPMethod() { + } + public String value() { return this.name(); } diff --git a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInstance.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInstance.java index 9025aa62..8e62edb7 100644 --- a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInstance.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInstance.java @@ -2,6 +2,9 @@ package com.gitee.sop.registryapi.bean; import lombok.Data; +import java.util.HashMap; +import java.util.Map; + /** * @author tanghc */ @@ -37,4 +40,9 @@ public class ServiceInstance { */ private String updateTime; + /** + * user extended attributes + */ + private Map metadata = new HashMap(); + } \ No newline at end of file diff --git a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/RegistryService.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/RegistryService.java index 829b9a5a..33988ca3 100644 --- a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/RegistryService.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/RegistryService.java @@ -38,4 +38,13 @@ public interface RegistryService { void offlineInstance(ServiceInstance serviceInstance) throws Exception; + /** + * 设置实例元数据 + * + * @param serviceInstance 实例 + * @param key key + * @param value 值 + * @throws Exception 设置实例元数据失败抛出异常 + */ + void setMetadata(ServiceInstance serviceInstance, String key, String value) throws Exception; } diff --git a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceEureka.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceEureka.java index f6a1c774..57793f3b 100644 --- a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceEureka.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceEureka.java @@ -60,6 +60,7 @@ public class RegistryServiceEureka implements RegistryService { serviceInstance.setStatus(eurekaInstance.getStatus()); Date updateTime = new Date(Long.valueOf(eurekaInstance.getLastUpdatedTimestamp())); serviceInstance.setUpdateTime(DateFormatUtils.format(updateTime, TIMESTAMP_PATTERN)); + serviceInstance.setMetadata(eurekaInstance.getMetadata()); serviceInfo.getInstances().add(serviceInstance); } } @@ -80,6 +81,11 @@ public class RegistryServiceEureka implements RegistryService { this.requestEurekaServer(EurekaUri.OFFLINE_SERVICE, serviceInstance.getServiceId(), serviceInstance.getInstanceId()); } + @Override + public void setMetadata(ServiceInstance serviceInstance, String key, String value) throws Exception { + this.requestEurekaServer(EurekaUri.SET_METADATA, serviceInstance.getServiceId(), serviceInstance.getInstanceId(), key, value); + } + private String requestEurekaServer(EurekaUri eurekaUri, String... args) throws IOException { Request request = eurekaUri.getRequest(this.eurekaUrl, args); Response response = client.newCall(request).execute(); diff --git a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java index 0a6cbcd8..8d24ad8a 100644 --- a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java @@ -1,17 +1,17 @@ package com.gitee.sop.registryapi.service.impl; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.naming.NamingFactory; import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.pojo.Instance; import com.alibaba.nacos.api.naming.pojo.ListView; +import com.gitee.sop.registryapi.bean.HttpTool; import com.gitee.sop.registryapi.bean.ServiceInfo; import com.gitee.sop.registryapi.bean.ServiceInstance; import com.gitee.sop.registryapi.service.RegistryService; -import okhttp3.FormBody; import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.CollectionUtils; @@ -24,13 +24,15 @@ import java.util.List; import java.util.Map; /** - * nacos接口实现 + * nacos接口实现, https://nacos.io/zh-cn/docs/open-api.html * @author tanghc */ public class RegistryServiceNacos implements RegistryService { OkHttpClient client = new OkHttpClient(); + static HttpTool httpTool = new HttpTool(); + @Value("${registry.nacos-server-addr:}") private String nacosAddr; @@ -63,6 +65,7 @@ public class RegistryServiceNacos implements RegistryService { boolean isOnline = instance.getWeight() > 0; String status = isOnline ? "UP" : "OUT_OF_SERVICE"; serviceInstance.setStatus(status); + serviceInstance.setMetadata(instance.getMetadata()); serviceInfo.getInstances().add(serviceInstance); } } @@ -73,34 +76,50 @@ public class RegistryServiceNacos implements RegistryService { @Override public void onlineInstance(ServiceInstance serviceInstance) throws Exception { - Map params = new HashMap<>(8); + // 查询实例 + Instance instance = this.getInstance(serviceInstance); // 上线,把权重设置成1 - params.put("weight", "1"); - this.updateInstance(serviceInstance, params); + instance.setWeight(1); + this.updateInstance(instance); } @Override public void offlineInstance(ServiceInstance serviceInstance) throws Exception { - Map params = new HashMap<>(8); + // 查询实例 + Instance instance = this.getInstance(serviceInstance); // 下线,把权重设置成0 - params.put("weight", "0"); - this.updateInstance(serviceInstance, params); + instance.setWeight(0); + this.updateInstance(instance); } - private Response updateInstance(ServiceInstance serviceInstance, Map params) throws IOException { - FormBody.Builder builder = new FormBody.Builder(); - for (Map.Entry entry : params.entrySet()) { - builder.add(entry.getKey(), String.valueOf(entry.getValue())); - } - builder.add("serviceName", serviceInstance.getServiceId()) - .add("ip", serviceInstance.getIp()) - .add("port", String.valueOf(serviceInstance.getPort())); - FormBody formBody = builder.build(); - final Request request = new Request.Builder() - .url("http://" + nacosAddr + "/nacos/v1/ns/instance") - .put(formBody) - .build(); + @Override + public void setMetadata(ServiceInstance serviceInstance, String key, String value) throws Exception { + // 查询实例 + Instance instance = this.getInstance(serviceInstance); + // 设置metadata + Map metadata = instance.getMetadata(); + metadata.put(key, value); + this.updateInstance(instance); + } - return client.newCall(request).execute(); + protected void updateInstance(Instance instance) throws IOException { + String json = JSON.toJSONString(instance); + JSONObject jsonObject = JSON.parseObject(json); + httpTool.request("http://" + nacosAddr + "/nacos/v1/ns/instance", jsonObject, null, HttpTool.HTTPMethod.PUT); + } + + /** + * 查询实例 + * @param serviceInstance 实例信息 + * @return 返回nacos实例 + * @throws IOException 查询异常 + */ + protected Instance getInstance(ServiceInstance serviceInstance) throws IOException { + Map params = new HashMap<>(8); + params.put("serviceName", serviceInstance.getServiceId()); + params.put("ip", serviceInstance.getIp()); + params.put("port", String.valueOf(serviceInstance.getPort())); + String instanceJson = httpTool.request("http://" + nacosAddr + "/nacos/v1/ns/instance", params, null, HttpTool.HTTPMethod.GET); + return JSON.parseObject(instanceJson, Instance.class); } } diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/message/ServiceErrorEnum.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/message/ServiceErrorEnum.java index 56244f9c..7bd28618 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/message/ServiceErrorEnum.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/message/ServiceErrorEnum.java @@ -5,7 +5,7 @@ package com.gitee.sop.servercommon.message; */ public enum ServiceErrorEnum { /** 系统繁忙 */ - ISP_UNKNOW_ERROR("isp.unknow-error"), + ISP_UNKNOW_ERROR("isp.unknown-error"), /** 参数错误 */ ISV_PARAM_ERROR("isv.invalid-parameter"), /** 通用错误 */ diff --git a/sop-common/sop-service-common/src/main/resources/i18n/isp/error_en.properties b/sop-common/sop-service-common/src/main/resources/i18n/isp/error_en.properties index 8560312c..9b36e636 100644 --- a/sop-common/sop-service-common/src/main/resources/i18n/isp/error_en.properties +++ b/sop-common/sop-service-common/src/main/resources/i18n/isp/error_en.properties @@ -1,4 +1,4 @@ # 错误配置 -isp.error_isp.unknow-error=Service is temporarily unavailable +isp.error_isp.unknown-error=Service is temporarily unavailable isp.error_isv.invalid-parameter=Invalid parameter \ No newline at end of file diff --git a/sop-common/sop-service-common/src/main/resources/i18n/isp/error_zh_CN.properties b/sop-common/sop-service-common/src/main/resources/i18n/isp/error_zh_CN.properties index 42616e36..48fc185c 100644 --- a/sop-common/sop-service-common/src/main/resources/i18n/isp/error_zh_CN.properties +++ b/sop-common/sop-service-common/src/main/resources/i18n/isp/error_zh_CN.properties @@ -1,5 +1,5 @@ # 错误配置 -isp.error_isp.unknow-error=\u670d\u52a1\u6682\u4e0d\u53ef\u7528 +isp.error_isp.unknown-error=\u670d\u52a1\u6682\u4e0d\u53ef\u7528 # 参数无效 isp.error_isv.invalid-parameter=\u53c2\u6570\u65e0\u6548 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 e87b22bf..3dfe7ba7 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 @@ -6,8 +6,11 @@ package com.gitee.sop.gateway.config; * 注意:下面两个只能使用一个 */ +import com.gitee.sop.gateway.loadbalancer.SopPropertiesFactory; import com.gitee.sop.gateway.manager.ManagerInitializer; import com.gitee.sop.gatewaycommon.zuul.configuration.AlipayZuulConfiguration; +import org.springframework.cloud.netflix.ribbon.PropertiesFactory; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** @@ -21,6 +24,11 @@ public class ZuulConfig extends AlipayZuulConfiguration { new ManagerInitializer(); } + @Bean + PropertiesFactory propertiesFactory() { + return new SopPropertiesFactory(); + } + } /** diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/loadbalancer/PreEnvironmentServerChooser.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/loadbalancer/PreEnvironmentServerChooser.java new file mode 100644 index 00000000..eb63135f --- /dev/null +++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/loadbalancer/PreEnvironmentServerChooser.java @@ -0,0 +1,55 @@ +package com.gitee.sop.gateway.loadbalancer; + +import com.gitee.sop.gatewaycommon.zuul.loadbalancer.BaseServerChooser; +import com.netflix.loadbalancer.Server; +import com.netflix.niws.loadbalancer.DiscoveryEnabledServer; +import org.apache.commons.lang3.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; +import java.util.Objects; + +/** + * 预发布环境选择,参考自:https://segmentfault.com/a/1190000017412946 + * + * @author tanghc + */ +public class PreEnvironmentServerChooser extends BaseServerChooser { + + private static final String MEDATA_KEY_ENV = "env"; + private static final String ENV_PRE_VALUE = "pre"; + + private static final String HOST_NAME = "localhost"; + + @Override + protected boolean match(Server server) { + // eureka存储的metadata + Map metadata = ((DiscoveryEnabledServer) server).getInstanceInfo().getMetadata(); + String env = metadata.get(MEDATA_KEY_ENV); + return StringUtils.isNotBlank(env); + } + + /** + * 这里判断客户端能否访问,可以根据ip地址,域名,header内容来决定是否可以访问预发布环境 + * @param server 服务器实例 + * @param request request + * @return + */ + @Override + protected boolean canVisit(Server server, HttpServletRequest request) { + // eureka存储的metadata + Map metadata = ((DiscoveryEnabledServer) server).getInstanceInfo().getMetadata(); + String env = metadata.get(MEDATA_KEY_ENV); + return Objects.equals(ENV_PRE_VALUE, env) && canClientVisit(request); + } + + /** + * 通过判断hostname来确定是否是预发布请求,如果需要通过其它条件判断,修改此方法 + * @param request request + * @return 返回true:可以进入到预发环境 + */ + protected boolean canClientVisit(HttpServletRequest request) { + String serverName = request.getServerName(); + return HOST_NAME.equals(serverName); + } +} diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/loadbalancer/SopPropertiesFactory.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/loadbalancer/SopPropertiesFactory.java new file mode 100644 index 00000000..2cda625a --- /dev/null +++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/loadbalancer/SopPropertiesFactory.java @@ -0,0 +1,39 @@ +package com.gitee.sop.gateway.loadbalancer; + +import com.netflix.loadbalancer.IRule; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.netflix.ribbon.PropertiesFactory; +import org.springframework.core.env.Environment; + +/** + * 自定义PropertiesFactory,用来动态添加LoadBalance规则 + * @author tanghc + */ +public class SopPropertiesFactory extends PropertiesFactory { + + /** + * 可在配置文件中设置zuul.custom-rule-classname=com.xx.ClassName指定负载均衡规则类 + * 默认使用com.gitee.sop.gateway.loadbalancer.PreEnvironmentServerChooser + */ + private static final String PROPERTIES_KEY = "zuul.custom-rule-classname"; + + private static final String CUSTOM_RULE_CLASSNAME = PreEnvironmentServerChooser.class.getName(); + + @Autowired + private Environment environment; + + /** + * 配置文件配置:.ribbon.NFLoadBalancerRuleClassName=com.gitee.sop.gateway.loadbalancer.PreEnvironmentServerChooser + * @param clazz + * @param name serviceId + * @return 返回class全限定名 + */ + @Override + public String getClassName(Class clazz, String name) { + if (clazz == IRule.class) { + return this.environment.getProperty(PROPERTIES_KEY, CUSTOM_RULE_CLASSNAME); + } else { + return super.getClassName(clazz, name); + } + } +} diff --git a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/common/CustomDataNameBuilder.java b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/common/CustomDataNameBuilder.java index f015a85c..ab54e4f5 100644 --- a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/common/CustomDataNameBuilder.java +++ b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/common/CustomDataNameBuilder.java @@ -6,7 +6,7 @@ package com.gitee.sop.sdk.common; * "result": { * "code": "20000", * "msg": "Service Currently Unavailable", - * "sub_code": "isp.unknow-error", + * "sub_code": "isp.unknown-error", * "sub_msg": "系统繁忙" * }, * "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE" diff --git a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/common/DefaultDataNameBuilder.java b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/common/DefaultDataNameBuilder.java index 31f97fa8..77d3a78b 100644 --- a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/common/DefaultDataNameBuilder.java +++ b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/common/DefaultDataNameBuilder.java @@ -8,7 +8,7 @@ package com.gitee.sop.sdk.common; * "alipay_trade_order_settle_response": { * "code": "20000", * "msg": "Service Currently Unavailable", - * "sub_code": "isp.unknow-error", + * "sub_code": "isp.unknown-error", * "sub_msg": "系统繁忙" * }, * "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE" diff --git a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/response/BaseResponse.java b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/response/BaseResponse.java index efc376fc..23bbf469 100644 --- a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/response/BaseResponse.java +++ b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/response/BaseResponse.java @@ -11,7 +11,7 @@ import lombok.Setter; * "alipay_trade_close_response": { * "code": "20000", * "msg": "Service Currently Unavailable", - * "sub_code": "isp.unknow-error", + * "sub_code": "isp.unknown-error", * "sub_msg": "系统繁忙" * }, * "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE" diff --git a/sop-test/src/main/java/com/gitee/sop/test/HttpTool.java b/sop-test/src/main/java/com/gitee/sop/test/HttpTool.java index 989382df..b7fa77ef 100644 --- a/sop-test/src/main/java/com/gitee/sop/test/HttpTool.java +++ b/sop-test/src/main/java/com/gitee/sop/test/HttpTool.java @@ -110,7 +110,7 @@ public class HttpTool { * @return * @throws IOException */ - public String request(String url, Map form, Map header, HTTPMethod method) throws IOException { + public String request(String url, Map form, Map header, HTTPMethod method) throws IOException { Request.Builder requestBuilder = buildRequestBuilder(url, form, method.value()); // 添加header addHeader(requestBuilder, header); @@ -153,7 +153,7 @@ public class HttpTool { } } - public static Request.Builder buildRequestBuilder(String url, Map form, String method) { + public static Request.Builder buildRequestBuilder(String url, Map form, String method) { switch (method) { case "get": return new Request.Builder() @@ -178,18 +178,18 @@ public class HttpTool { } } - public static HttpUrl buildHttpUrl(String url, Map form) { + public static HttpUrl buildHttpUrl(String url, Map form) { HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder(); - for (Map.Entry entry : form.entrySet()) { - urlBuilder.addQueryParameter(entry.getKey(), entry.getValue()); + for (Map.Entry entry : form.entrySet()) { + urlBuilder.addQueryParameter(entry.getKey(), String.valueOf(entry.getValue())); } return urlBuilder.build(); } - public static FormBody buildFormBody(Map form) { + public static FormBody buildFormBody(Map form) { FormBody.Builder paramBuilder = new FormBody.Builder(StandardCharsets.UTF_8); - for (Map.Entry entry : form.entrySet()) { - paramBuilder.add(entry.getKey(), entry.getValue()); + for (Map.Entry entry : form.entrySet()) { + paramBuilder.add(entry.getKey(), String.valueOf(entry.getValue())); } return paramBuilder.build(); } diff --git a/sop-website/website-front/pages/doc/code.html b/sop-website/website-front/pages/doc/code.html index 5d7d8bf6..9fecb963 100644 --- a/sop-website/website-front/pages/doc/code.html +++ b/sop-website/website-front/pages/doc/code.html @@ -141,7 +141,7 @@
服务不可用
-
isp.unknow-error
+
isp.unknown-error
服务暂不可用(业务系统不可用)
diff --git a/sop-website/website-front/pages/doc/docEvent.js b/sop-website/website-front/pages/doc/docEvent.js index e3aee12f..5f58b327 100644 --- a/sop-website/website-front/pages/doc/docEvent.js +++ b/sop-website/website-front/pages/doc/docEvent.js @@ -93,7 +93,7 @@ function createResponseCode(docItem) { ' "'+method+'_response": {\n' + ' "code": "20000",\n' + ' "msg": "Service is temporarily unavailable",\n' + - ' "sub_code": "isp.unknow-error",\n' + + ' "sub_code": "isp.unknown-error",\n' + ' "sub_msg": "服务暂不可用"\n' + ' }' + '}'; diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java index 5bfd6aa0..794770d4 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java @@ -1,7 +1,7 @@ package com.gitee.sop.websiteserver.controller; -import com.gitee.sop.websiteserver.bean.HttpTool; -import com.gitee.sop.websiteserver.bean.HttpTool.*; +import com.gitee.sop.registryapi.bean.HttpTool; +import com.gitee.sop.registryapi.bean.HttpTool.*; import com.gitee.sop.websiteserver.sign.AlipayApiException; import com.gitee.sop.websiteserver.sign.AlipaySignature; import com.gitee.sop.websiteserver.util.UploadUtil;