This commit is contained in:
六如
2024-11-04 14:37:54 +08:00
parent d9a257ff23
commit 53a40a1cb4
14 changed files with 285 additions and 65 deletions

View File

@@ -49,7 +49,7 @@
<dependency> <dependency>
<groupId>org.apache.dubbo</groupId> <groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper-curator5</artifactId> <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
<version>${dubbo.version}</version> <version>3.2.10</version>
<type>pom</type> <type>pom</type>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>

View File

@@ -7,6 +7,7 @@ import com.gitee.sop.storyweb.open.resp.StoryResponse;
import com.gitee.sop.support.context.OpenContext; import com.gitee.sop.support.context.OpenContext;
import com.gitee.sop.support.dto.CommonFileData; import com.gitee.sop.support.dto.CommonFileData;
import com.gitee.sop.support.dto.FileData; import com.gitee.sop.support.dto.FileData;
import com.gitee.sop.support.dto.OpenRequest;
import com.gitee.sop.support.exception.OpenException; import com.gitee.sop.support.exception.OpenException;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.dubbo.config.annotation.DubboService; import org.apache.dubbo.config.annotation.DubboService;
@@ -17,6 +18,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; 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("token:" + OpenContext.getAppAuthToken());
System.out.println("ip:" + OpenContext.getClientIp()); System.out.println("ip:" + OpenContext.getClientIp());
System.out.println("traceId:" + OpenContext.getTraceId()); 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.getAppId());
Assert.notNull(OpenContext.getApiName()); Assert.notNull(OpenContext.getApiName());
Assert.notNull(OpenContext.getVersion()); Assert.notNull(OpenContext.getVersion());
Assert.notNull(OpenContext.getClientIp()); Assert.notNull(OpenContext.getClientIp());
Assert.notNull(OpenContext.getTraceId()); Assert.notNull(OpenContext.getTraceId());
Assert.notNull(OpenContext.getLocale());
return 1; return 1;
} }
@@ -80,6 +85,23 @@ public class OpenStoryImpl implements OpenStory {
return storyResponse; 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 @Override
public StoryResponse upload(StorySaveDTO storySaveDTO, FileData file) { public StoryResponse upload(StorySaveDTO storySaveDTO, FileData file) {

View File

@@ -4,6 +4,7 @@ import com.gitee.sop.storyweb.open.req.StorySaveDTO;
import com.gitee.sop.storyweb.open.resp.StoryResponse; import com.gitee.sop.storyweb.open.resp.StoryResponse;
import com.gitee.sop.support.annotation.Open; import com.gitee.sop.support.annotation.Open;
import com.gitee.sop.support.dto.FileData; import com.gitee.sop.support.dto.FileData;
import com.gitee.sop.support.dto.OpenRequest;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
@@ -32,6 +33,9 @@ public interface OpenStory {
@Open(value = "story.get", version = "2.0") @Open(value = "story.get", version = "2.0")
StoryResponse getByIdV2(Long id); StoryResponse getByIdV2(Long id);
@Open(value = "story.get", version = "3.0")
StoryResponse getByIdV3(Long id, OpenRequest request);
// 默认方法,注解放在这里也有效 // 默认方法,注解放在这里也有效
@Open("story.find") @Open("story.find")

View File

@@ -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";
}

View File

@@ -3,7 +3,6 @@ package com.gitee.sop.gateway.service;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.gitee.sop.gateway.common.ApiInfoDTO; 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.common.ParamInfoDTO;
import com.gitee.sop.gateway.exception.ApiException; import com.gitee.sop.gateway.exception.ApiException;
import com.gitee.sop.gateway.exception.ExceptionExecutor; 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.interceptor.RouteInterceptor;
import com.gitee.sop.gateway.service.validate.Validator; import com.gitee.sop.gateway.service.validate.Validator;
import com.gitee.sop.gateway.util.ClassUtil; 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.CommonFileData;
import com.gitee.sop.support.dto.DefaultOpenRequest;
import com.gitee.sop.support.dto.FileData; 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 lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.rpc.RpcContext; 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.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile; 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) { protected void setAttachment(ApiRequestContext apiRequestContext) {
ApiRequest apiRequest = apiRequestContext.getApiRequest(); ApiRequest apiRequest = apiRequestContext.getApiRequest();
RpcContextAttachment clientAttachment = RpcContext.getClientAttachment(); 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.API_NAME, apiRequest.getMethod());
clientAttachment.setAttachment(AttachmentNames.VERSION_NAME, apiRequest.getVersion()); clientAttachment.setAttachment(AttachmentNames.VERSION, apiRequest.getVersion());
clientAttachment.setAttachment(AttachmentNames.APP_AUTH_TOKEN_NAME, apiRequest.getAppAuthToken()); clientAttachment.setAttachment(AttachmentNames.APP_AUTH_TOKEN, apiRequest.getAppAuthToken());
clientAttachment.setAttachment(AttachmentNames.NOTIFY_URL_NAME, apiRequest.getNotifyUrl()); clientAttachment.setAttachment(AttachmentNames.NOTIFY_URL, apiRequest.getNotifyUrl());
clientAttachment.setAttachment(AttachmentNames.CLIENT_IP, apiRequestContext.getIp()); clientAttachment.setAttachment(AttachmentNames.CLIENT_IP, apiRequestContext.getIp());
clientAttachment.setAttachment(AttachmentNames.TRACE_ID, apiRequestContext.getTraceId()); clientAttachment.setAttachment(AttachmentNames.TRACE_ID, apiRequestContext.getTraceId());
clientAttachment.setAttachment(AttachmentNames.LOCALE, apiRequestContext.getLocale().toLanguageTag());
} }
protected void doPreRoute(ApiRequestContext apiRequestContext, ApiInfoDTO apiInfoDTO) { protected void doPreRoute(ApiRequestContext apiRequestContext, ApiInfoDTO apiInfoDTO) {
@@ -136,8 +139,13 @@ public class RouteServiceImpl implements RouteService {
for (ParamInfoDTO paramInfoDTO : paramInfoList) { for (ParamInfoDTO paramInfoDTO : paramInfoList) {
String type = paramInfoDTO.getType(); String type = paramInfoDTO.getType();
String actualType = paramInfoDTO.getActualType(); 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<Object> fileParam = buildFileParam(apiRequestContext, paramInfoDTO); Optional<Object> fileParam = buildFileParam(apiRequestContext, paramInfoDTO);
if (!fileParam.isPresent()) { if (!fileParam.isPresent()) {
continue; continue;
@@ -163,6 +171,20 @@ public class RouteServiceImpl implements RouteService {
return params.toArray(new Object[0]); 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<Object> buildFileParam(ApiRequestContext apiRequestContext, ParamInfoDTO paramInfoDTO) { protected Optional<Object> buildFileParam(ApiRequestContext apiRequestContext, ParamInfoDTO paramInfoDTO) {
UploadContext uploadContext = apiRequestContext.getUploadContext(); UploadContext uploadContext = apiRequestContext.getUploadContext();
if (uploadContext == null) { if (uploadContext == null) {

View File

@@ -48,12 +48,12 @@ public class ResultRouteInterceptor implements RouteInterceptor {
"originalFilename": "application.properties", "originalFilename": "application.properties",
"empty": false "empty": false
*/ */
CommonFileData commonFileData = new CommonFileData(); CommonFileData fileData = new CommonFileData();
commonFileData.setName(String.valueOf(map.get(KEY_NAME))); fileData.setName(String.valueOf(map.get(KEY_NAME)));
commonFileData.setOriginalFilename(String.valueOf(map.get(KEY_ORIGINAL_FILENAME))); fileData.setOriginalFilename(String.valueOf(map.get(KEY_ORIGINAL_FILENAME)));
commonFileData.setContentType(String.valueOf(map.get(KEY_CONTENT_TYPE))); fileData.setContentType(String.valueOf(map.get(KEY_CONTENT_TYPE)));
commonFileData.setData((byte[]) map.get(KEY_BYTES)); fileData.setData((byte[]) map.get(KEY_BYTES));
return commonFileData; return fileData;
} }
} }

View File

@@ -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";
}

View File

@@ -1,70 +1,77 @@
package com.gitee.sop.support.context; package com.gitee.sop.support.context;
import com.gitee.sop.support.constants.AttachmentNames;
import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcContext;
import java.util.Locale;
/** /**
* @author 六如 * @author 六如
*/ */
public class OpenContext { 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 * 获取appId
*/ */
public static String getAppId() { public static String getAppId() {
return RpcContext.getServerAttachment().getAttachment(APP_ID_NAME); return getAttachment(AttachmentNames.APP_ID);
} }
/** /**
* 获取apiName * 获取apiName
*/ */
public static String getApiName() { public static String getApiName() {
return RpcContext.getServerAttachment().getAttachment(API_NAME); return getAttachment(AttachmentNames.API_NAME);
} }
/** /**
* 获取version * 获取version
*/ */
public static String getVersion() { public static String getVersion() {
return RpcContext.getServerAttachment().getAttachment(VERSION_NAME); return getAttachment(AttachmentNames.VERSION);
} }
/** /**
* 获取token,没有返回null * 获取token,没有返回null
*/ */
public static String getAppAuthToken() { public static String getAppAuthToken() {
return RpcContext.getServerAttachment().getAttachment(APP_AUTH_TOKEN_NAME); return getAttachment(AttachmentNames.APP_AUTH_TOKEN);
} }
/** /**
* 获取客户端ip * 获取客户端ip
*/ */
public static String getClientIp() { public static String getClientIp() {
return RpcContext.getServerAttachment().getAttachment(CLIENT_IP); return getAttachment(AttachmentNames.CLIENT_IP);
} }
/** /**
* 获取回调地址 * 获取回调地址
*/ */
public static String getNotifyUrl() { public static String getNotifyUrl() {
return RpcContext.getServerAttachment().getAttachment(NOTIFY_URL_NAME); return getAttachment(AttachmentNames.NOTIFY_URL);
} }
/**
* 获取唯一请求id
*/
public static String getTraceId() { 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);
} }
} }

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -1,5 +1,6 @@
package com.gitee.sop.support.exception; 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.OpenError;
import com.gitee.sop.support.message.OpenMessage; import com.gitee.sop.support.message.OpenMessage;
import com.gitee.sop.support.message.OpenMessageFactory; import com.gitee.sop.support.message.OpenMessageFactory;
@@ -30,7 +31,7 @@ public class OpenException extends RuntimeException {
} }
public OpenException(OpenError openError, Object... params) { public OpenException(OpenError openError, Object... params) {
this(openError, Locale.SIMPLIFIED_CHINESE, params); this(openError, OpenContext.getLocale(), params);
} }
@Override @Override

View File

@@ -1 +1,2 @@
com.gitee.sop.support.dto.CommonFileData com.gitee.sop.support.dto.CommonFileData
com.gitee.sop.support.dto.DefaultOpenRequest

View File

@@ -179,6 +179,10 @@ public class Client {
private String url; private String url;
private String method; private String method;
private String version = DEFAULT_VERSION; private String version = DEFAULT_VERSION;
/**
* 回调地址
*/
private String notifyUrl;
private Map<String, Object> bizContent; private Map<String, Object> bizContent;
private HttpTool.HTTPMethod httpMethod; private HttpTool.HTTPMethod httpMethod;
private Map<String, String> header; private Map<String, String> header;
@@ -221,6 +225,17 @@ public class Client {
return this; 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("charset", "utf-8");
params.put("sign_type", "RSA2"); params.put("sign_type", "RSA2");
params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); 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) { if (systemParam != null) {
params.putAll(systemParam); params.putAll(systemParam);
} }

View File

@@ -107,6 +107,25 @@ public class AllInOneTest extends TestBase {
client.execute(requestBuilder); 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中设置权限 * 测试是否有权限访问可在sop-admin中设置权限