diff --git a/sop-example/example-story/pom.xml b/sop-example/example-story/pom.xml index 2aead720..d52fb69b 100644 --- a/sop-example/example-story/pom.xml +++ b/sop-example/example-story/pom.xml @@ -49,7 +49,7 @@ org.apache.dubbo dubbo-dependencies-zookeeper-curator5 - ${dubbo.version} + 3.2.10 pom provided diff --git a/sop-example/example-story/src/main/java/com/gitee/sop/storyweb/impl/OpenStoryImpl.java b/sop-example/example-story/src/main/java/com/gitee/sop/storyweb/impl/OpenStoryImpl.java index 6ba3f180..89deb2c0 100644 --- a/sop-example/example-story/src/main/java/com/gitee/sop/storyweb/impl/OpenStoryImpl.java +++ b/sop-example/example-story/src/main/java/com/gitee/sop/storyweb/impl/OpenStoryImpl.java @@ -7,6 +7,7 @@ import com.gitee.sop.storyweb.open.resp.StoryResponse; import com.gitee.sop.support.context.OpenContext; import com.gitee.sop.support.dto.CommonFileData; import com.gitee.sop.support.dto.FileData; +import com.gitee.sop.support.dto.OpenRequest; import com.gitee.sop.support.exception.OpenException; import org.apache.commons.io.IOUtils; import org.apache.dubbo.config.annotation.DubboService; @@ -17,6 +18,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; /** @@ -37,12 +39,15 @@ public class OpenStoryImpl implements OpenStory { System.out.println("token:" + OpenContext.getAppAuthToken()); System.out.println("ip:" + OpenContext.getClientIp()); System.out.println("traceId:" + OpenContext.getTraceId()); + System.out.println("locale:" + OpenContext.getLocale()); + System.out.println("notifyUrl:" + OpenContext.getNotifyUrl()); Assert.notNull(OpenContext.getAppId()); Assert.notNull(OpenContext.getApiName()); Assert.notNull(OpenContext.getVersion()); Assert.notNull(OpenContext.getClientIp()); Assert.notNull(OpenContext.getTraceId()); + Assert.notNull(OpenContext.getLocale()); return 1; } @@ -80,6 +85,23 @@ public class OpenStoryImpl implements OpenStory { return storyResponse; } + // 演示获取上下文 + @Override + public StoryResponse getByIdV3(Long id, OpenRequest request) { + StoryResponse storyResponse = new StoryResponse(); + storyResponse.setId(3); + storyResponse.setName(request.toString()); + + String notifyUrl = request.getNotifyUrl(); + System.out.println(notifyUrl); + // 方式2 + String notifyUrl2 = OpenContext.getNotifyUrl(); + System.out.println(notifyUrl2); + + System.out.println(Objects.equals(notifyUrl2, notifyUrl)); + + return storyResponse; + } @Override public StoryResponse upload(StorySaveDTO storySaveDTO, FileData file) { diff --git a/sop-example/example-story/src/main/java/com/gitee/sop/storyweb/open/OpenStory.java b/sop-example/example-story/src/main/java/com/gitee/sop/storyweb/open/OpenStory.java index 66dac0c3..1512b47e 100644 --- a/sop-example/example-story/src/main/java/com/gitee/sop/storyweb/open/OpenStory.java +++ b/sop-example/example-story/src/main/java/com/gitee/sop/storyweb/open/OpenStory.java @@ -4,6 +4,7 @@ import com.gitee.sop.storyweb.open.req.StorySaveDTO; import com.gitee.sop.storyweb.open.resp.StoryResponse; import com.gitee.sop.support.annotation.Open; import com.gitee.sop.support.dto.FileData; +import com.gitee.sop.support.dto.OpenRequest; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; @@ -32,6 +33,9 @@ public interface OpenStory { @Open(value = "story.get", version = "2.0") StoryResponse getByIdV2(Long id); + @Open(value = "story.get", version = "3.0") + StoryResponse getByIdV3(Long id, OpenRequest request); + // 默认方法,注解放在这里也有效 @Open("story.find") diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/common/AttachmentNames.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/common/AttachmentNames.java deleted file mode 100644 index c599582a..00000000 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/common/AttachmentNames.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.gitee.sop.gateway.common; - -/** - * @author 六如 - */ -public class AttachmentNames { - - /** 分配给开发者的应用ID */ - public static final String APP_ID_NAME = "client.app_id"; - /** 接口名称 */ - public static final String API_NAME = "client.method"; - /** 调用的接口版本 */ - public static final String VERSION_NAME = "client.version"; - /** 开放平台主动通知商户服务器里指定的页面http/https路径 */ - public static final String NOTIFY_URL_NAME = "client.notify_url"; - /** OAuth 2.0授权token */ - public static final String APP_AUTH_TOKEN_NAME = "client.app_auth_token"; - public static final String CLIENT_IP = "client.ip"; - public static final String TRACE_ID = "client.trace_id"; - -} diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/service/RouteServiceImpl.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/service/RouteServiceImpl.java index 913e37fe..dfcfa09e 100644 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/service/RouteServiceImpl.java +++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/service/RouteServiceImpl.java @@ -3,7 +3,6 @@ package com.gitee.sop.gateway.service; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.gitee.sop.gateway.common.ApiInfoDTO; -import com.gitee.sop.gateway.common.AttachmentNames; import com.gitee.sop.gateway.common.ParamInfoDTO; import com.gitee.sop.gateway.exception.ApiException; import com.gitee.sop.gateway.exception.ExceptionExecutor; @@ -16,8 +15,19 @@ import com.gitee.sop.gateway.response.Response; import com.gitee.sop.gateway.service.interceptor.RouteInterceptor; import com.gitee.sop.gateway.service.validate.Validator; import com.gitee.sop.gateway.util.ClassUtil; +import com.gitee.sop.support.constants.AttachmentNames; import com.gitee.sop.support.dto.CommonFileData; +import com.gitee.sop.support.dto.DefaultOpenRequest; import com.gitee.sop.support.dto.FileData; +import com.gitee.sop.support.dto.OpenRequest; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import javax.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.rpc.RpcContext; @@ -26,14 +36,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.ObjectUtils; import org.springframework.web.multipart.MultipartFile; -import javax.annotation.PostConstruct; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; -import java.util.Optional; /** @@ -93,13 +95,14 @@ public class RouteServiceImpl implements RouteService { protected void setAttachment(ApiRequestContext apiRequestContext) { ApiRequest apiRequest = apiRequestContext.getApiRequest(); RpcContextAttachment clientAttachment = RpcContext.getClientAttachment(); - clientAttachment.setAttachment(AttachmentNames.APP_ID_NAME, apiRequest.getAppId()); + clientAttachment.setAttachment(AttachmentNames.APP_ID, apiRequest.getAppId()); clientAttachment.setAttachment(AttachmentNames.API_NAME, apiRequest.getMethod()); - clientAttachment.setAttachment(AttachmentNames.VERSION_NAME, apiRequest.getVersion()); - clientAttachment.setAttachment(AttachmentNames.APP_AUTH_TOKEN_NAME, apiRequest.getAppAuthToken()); - clientAttachment.setAttachment(AttachmentNames.NOTIFY_URL_NAME, apiRequest.getNotifyUrl()); + clientAttachment.setAttachment(AttachmentNames.VERSION, apiRequest.getVersion()); + clientAttachment.setAttachment(AttachmentNames.APP_AUTH_TOKEN, apiRequest.getAppAuthToken()); + clientAttachment.setAttachment(AttachmentNames.NOTIFY_URL, apiRequest.getNotifyUrl()); clientAttachment.setAttachment(AttachmentNames.CLIENT_IP, apiRequestContext.getIp()); clientAttachment.setAttachment(AttachmentNames.TRACE_ID, apiRequestContext.getTraceId()); + clientAttachment.setAttachment(AttachmentNames.LOCALE, apiRequestContext.getLocale().toLanguageTag()); } protected void doPreRoute(ApiRequestContext apiRequestContext, ApiInfoDTO apiInfoDTO) { @@ -136,8 +139,13 @@ public class RouteServiceImpl implements RouteService { for (ParamInfoDTO paramInfoDTO : paramInfoList) { String type = paramInfoDTO.getType(); String actualType = paramInfoDTO.getActualType(); - // 处理文件上传 - if (Objects.equals(type, FileData.class.getName()) || Objects.equals(actualType, FileData.class.getName())) { + + // 上下文 + if (Objects.equals(type, OpenRequest.class.getName())) { + OpenRequest openRequest = buildOpenRequest(apiRequestContext); + params.add(openRequest); + } else if (Objects.equals(type, FileData.class.getName()) || Objects.equals(actualType, FileData.class.getName())) { + // 处理文件上传 Optional fileParam = buildFileParam(apiRequestContext, paramInfoDTO); if (!fileParam.isPresent()) { continue; @@ -163,6 +171,20 @@ public class RouteServiceImpl implements RouteService { return params.toArray(new Object[0]); } + protected OpenRequest buildOpenRequest(ApiRequestContext apiRequestContext) { + ApiRequest apiRequest = apiRequestContext.getApiRequest(); + DefaultOpenRequest defaultOpenRequest = new DefaultOpenRequest(); + defaultOpenRequest.setAppId(apiRequest.getAppId()); + defaultOpenRequest.setApiName(apiRequest.getMethod()); + defaultOpenRequest.setVersion(apiRequest.getVersion()); + defaultOpenRequest.setAppAuthToken(apiRequest.getAppAuthToken()); + defaultOpenRequest.setClientIp(apiRequestContext.getIp()); + defaultOpenRequest.setNotifyUrl(apiRequest.getNotifyUrl()); + defaultOpenRequest.setTraceId(apiRequestContext.getTraceId()); + defaultOpenRequest.setLocale(apiRequestContext.getLocale()); + return defaultOpenRequest; + } + protected Optional buildFileParam(ApiRequestContext apiRequestContext, ParamInfoDTO paramInfoDTO) { UploadContext uploadContext = apiRequestContext.getUploadContext(); if (uploadContext == null) { diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/service/interceptor/internal/ResultRouteInterceptor.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/service/interceptor/internal/ResultRouteInterceptor.java index dc77ffbe..af6489ca 100644 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/service/interceptor/internal/ResultRouteInterceptor.java +++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/service/interceptor/internal/ResultRouteInterceptor.java @@ -48,12 +48,12 @@ public class ResultRouteInterceptor implements RouteInterceptor { "originalFilename": "application.properties", "empty": false */ - CommonFileData commonFileData = new CommonFileData(); - commonFileData.setName(String.valueOf(map.get(KEY_NAME))); - commonFileData.setOriginalFilename(String.valueOf(map.get(KEY_ORIGINAL_FILENAME))); - commonFileData.setContentType(String.valueOf(map.get(KEY_CONTENT_TYPE))); - commonFileData.setData((byte[]) map.get(KEY_BYTES)); - return commonFileData; + CommonFileData fileData = new CommonFileData(); + fileData.setName(String.valueOf(map.get(KEY_NAME))); + fileData.setOriginalFilename(String.valueOf(map.get(KEY_ORIGINAL_FILENAME))); + fileData.setContentType(String.valueOf(map.get(KEY_CONTENT_TYPE))); + fileData.setData((byte[]) map.get(KEY_BYTES)); + return fileData; } } diff --git a/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/constants/AttachmentNames.java b/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/constants/AttachmentNames.java new file mode 100644 index 00000000..acce9f61 --- /dev/null +++ b/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/constants/AttachmentNames.java @@ -0,0 +1,43 @@ +package com.gitee.sop.support.constants; + +/** + * RPC附件name + * + * @author 六如 + */ +public class AttachmentNames { + + /** + * 分配给开发者的应用ID + */ + public static final String APP_ID = "client.app_id"; + /** + * 接口名称 + */ + public static final String API_NAME = "client.method"; + /** + * 调用的接口版本 + */ + public static final String VERSION = "client.version"; + /** + * 开放平台主动通知商户服务器里指定的页面http/https路径 + */ + public static final String NOTIFY_URL = "client.notify_url"; + /** + * OAuth 2.0授权token + */ + public static final String APP_AUTH_TOKEN = "client.app_auth_token"; + /** + * 请求id + */ + public static final String CLIENT_IP = "client.ip"; + /** + * 请求traceId + */ + public static final String TRACE_ID = "client.trace_id"; + /** + * 请求locale + */ + public static final String LOCALE = "client.locale"; + +} diff --git a/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/context/OpenContext.java b/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/context/OpenContext.java index 2da36768..d600c606 100644 --- a/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/context/OpenContext.java +++ b/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/context/OpenContext.java @@ -1,70 +1,77 @@ package com.gitee.sop.support.context; +import com.gitee.sop.support.constants.AttachmentNames; import org.apache.dubbo.rpc.RpcContext; +import java.util.Locale; + /** * @author 六如 */ public class OpenContext { - /** 分配给开发者的应用ID */ - private static final String APP_ID_NAME = "client.app_id"; - /** 接口名称 */ - private static final String API_NAME = "client.method"; - /** 调用的接口版本 */ - private static final String VERSION_NAME = "client.version"; - /** 开放平台主动通知商户服务器里指定的页面http/https路径 */ - private static final String NOTIFY_URL_NAME = "client.notify_url"; - /** OAuth 2.0授权token */ - private static final String APP_AUTH_TOKEN_NAME = "client.app_auth_token"; - private static final String CLIENT_IP = "client.ip"; - private static final String TRACE_ID = "client.trace_id"; - - /** * 获取appId */ public static String getAppId() { - return RpcContext.getServerAttachment().getAttachment(APP_ID_NAME); + return getAttachment(AttachmentNames.APP_ID); } /** * 获取apiName */ public static String getApiName() { - return RpcContext.getServerAttachment().getAttachment(API_NAME); + return getAttachment(AttachmentNames.API_NAME); } /** * 获取version */ public static String getVersion() { - return RpcContext.getServerAttachment().getAttachment(VERSION_NAME); + return getAttachment(AttachmentNames.VERSION); } /** * 获取token,没有返回null */ public static String getAppAuthToken() { - return RpcContext.getServerAttachment().getAttachment(APP_AUTH_TOKEN_NAME); + return getAttachment(AttachmentNames.APP_AUTH_TOKEN); } /** * 获取客户端ip */ public static String getClientIp() { - return RpcContext.getServerAttachment().getAttachment(CLIENT_IP); + return getAttachment(AttachmentNames.CLIENT_IP); } /** * 获取回调地址 */ public static String getNotifyUrl() { - return RpcContext.getServerAttachment().getAttachment(NOTIFY_URL_NAME); + return getAttachment(AttachmentNames.NOTIFY_URL); } + /** + * 获取唯一请求id + */ public static String getTraceId() { - return RpcContext.getServerAttachment().getAttachment(TRACE_ID); + return getAttachment(AttachmentNames.TRACE_ID); + } + + /** + * 获取locale + */ + public static Locale getLocale() { + String langTag = getAttachment(AttachmentNames.LOCALE); + if (langTag == null) { + return Locale.SIMPLIFIED_CHINESE; + } + return Locale.forLanguageTag(langTag); + } + + private static String getAttachment(String key) { + return RpcContext.getServerAttachment().getAttachment(key); } } diff --git a/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/dto/DefaultOpenRequest.java b/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/dto/DefaultOpenRequest.java new file mode 100644 index 00000000..6600430a --- /dev/null +++ b/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/dto/DefaultOpenRequest.java @@ -0,0 +1,54 @@ +package com.gitee.sop.support.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Locale; + +/** + * @author 六如 + */ +@Data +public class DefaultOpenRequest implements OpenRequest, Serializable { + private static final long serialVersionUID = -3218354527911979685L; + + /** + * appId + */ + private String appId; + + /** + * apiName + */ + private String apiName; + + /** + * version + */ + private String version; + + /** + * token,没有返回null + */ + private String appAuthToken; + + /** + * 客户端ip + */ + private String clientIp; + + /** + * 回调地址 + */ + private String notifyUrl; + + /** + * 唯一请求id + */ + private String traceId; + + /** + * locale + */ + private Locale locale; +} diff --git a/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/dto/OpenRequest.java b/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/dto/OpenRequest.java new file mode 100644 index 00000000..74fb2d55 --- /dev/null +++ b/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/dto/OpenRequest.java @@ -0,0 +1,50 @@ +package com.gitee.sop.support.dto; + +import java.util.Locale; + +/** + * @author 六如 + */ +public interface OpenRequest { + + /** + * 获取appId + */ + String getAppId(); + + /** + * 获取apiName + */ + String getApiName(); + + /** + * 获取version + */ + String getVersion(); + + /** + * 获取token,没有返回null + */ + String getAppAuthToken(); + + /** + * 获取客户端ip + */ + String getClientIp(); + + /** + * 获取回调地址 + */ + String getNotifyUrl(); + + /** + * 获取唯一请求id + */ + String getTraceId(); + + /** + * 获取locale + */ + Locale getLocale(); + +} diff --git a/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/exception/OpenException.java b/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/exception/OpenException.java index 72f48272..25960c47 100644 --- a/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/exception/OpenException.java +++ b/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/exception/OpenException.java @@ -1,5 +1,6 @@ package com.gitee.sop.support.exception; +import com.gitee.sop.support.context.OpenContext; import com.gitee.sop.support.message.OpenError; import com.gitee.sop.support.message.OpenMessage; import com.gitee.sop.support.message.OpenMessageFactory; @@ -30,7 +31,7 @@ public class OpenException extends RuntimeException { } public OpenException(OpenError openError, Object... params) { - this(openError, Locale.SIMPLIFIED_CHINESE, params); + this(openError, OpenContext.getLocale(), params); } @Override diff --git a/sop-support/sop-service-support/src/main/resources/security/serialize.allowlist b/sop-support/sop-service-support/src/main/resources/security/serialize.allowlist index 2bcb4f4d..5cbd2fc6 100644 --- a/sop-support/sop-service-support/src/main/resources/security/serialize.allowlist +++ b/sop-support/sop-service-support/src/main/resources/security/serialize.allowlist @@ -1 +1,2 @@ com.gitee.sop.support.dto.CommonFileData +com.gitee.sop.support.dto.DefaultOpenRequest diff --git a/sop-test/src/main/java/com/gitee/sop/test/Client.java b/sop-test/src/main/java/com/gitee/sop/test/Client.java index d0e45cfa..7cb2d014 100644 --- a/sop-test/src/main/java/com/gitee/sop/test/Client.java +++ b/sop-test/src/main/java/com/gitee/sop/test/Client.java @@ -179,6 +179,10 @@ public class Client { private String url; private String method; private String version = DEFAULT_VERSION; + /** + * 回调地址 + */ + private String notifyUrl; private Map bizContent; private HttpTool.HTTPMethod httpMethod; private Map header; @@ -221,6 +225,17 @@ public class Client { return this; } + /** + * 设置notifyUrl + * + * @param notifyUrl notifyUrl + * @return 返回RequestBuilder + */ + public RequestBuilder notifyUrl(String notifyUrl) { + this.notifyUrl = notifyUrl; + return this; + } + /** * 设置业务参数 * @@ -392,6 +407,9 @@ public class Client { params.put("charset", "utf-8"); params.put("sign_type", "RSA2"); params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); + if (notifyUrl != null) { + params.put("notify_url", notifyUrl); + } if (systemParam != null) { params.putAll(systemParam); } diff --git a/sop-test/src/test/java/com/gitee/sop/test/AllInOneTest.java b/sop-test/src/test/java/com/gitee/sop/test/AllInOneTest.java index 0447421c..bf9d5fb0 100644 --- a/sop-test/src/test/java/com/gitee/sop/test/AllInOneTest.java +++ b/sop-test/src/test/java/com/gitee/sop/test/AllInOneTest.java @@ -107,6 +107,25 @@ public class AllInOneTest extends TestBase { client.execute(requestBuilder); } + /** + * 多版本2.0 + */ + public void testGet_v3() { + Client.RequestBuilder requestBuilder = new Client.RequestBuilder() + .method("story.get") + .version("3.0") + .notifyUrl("http://www.baidu.com") + .bizContent(new BizContent().add("id", "2").add("name", "葫芦娃2")) + .httpMethod(HttpTool.HTTPMethod.GET) + .callback((requestInfo, responseData) -> { + System.out.println(responseData); + JSONObject jsonObject = JSON.parseObject(responseData); + Assert.assertEquals("0", jsonObject.getString("code")); + }); + + client.execute(requestBuilder); + } + /** * 测试是否有权限访问,可在sop-admin中设置权限