This commit is contained in:
六如
2024-09-14 10:33:43 +08:00
parent 95072a02f6
commit a14ac9e3c9
237 changed files with 1078 additions and 694 deletions

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-service-support</artifactId>
<version>5.0.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.2.10</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,39 @@
package com.gitee.sop.support.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author tanghc
*/
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Open {
/**
* 接口名member.user.get
*/
String value();
/**
* 版本号,默认版本号是"1.0"
*/
String version() default "1.0";
/**
* 指定接口是否需要授权才能访问可在admin中进行修改
*/
boolean permission() default false;
/**
* 是否需要appAuthToken设置为true网关端会校验token是否存在
*/
boolean needToken() default false;
}

View File

@@ -0,0 +1,68 @@
package com.gitee.sop.support.context;
import org.apache.dubbo.rpc.RpcContext;
/**
* @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);
}
/**
* 获取apiName
*/
public static String getApiName() {
return RpcContext.getServerAttachment().getAttachment(API_NAME);
}
/**
* 获取version
*/
public static String getVersion() {
return RpcContext.getServerAttachment().getAttachment(VERSION_NAME);
}
/**
* 获取token,没有返回null
*/
public static String getAppAuthToken() {
return RpcContext.getServerAttachment().getAttachment(APP_AUTH_TOKEN_NAME);
}
/**
* 获取客户端ip
*/
public static String getClientIp() {
return RpcContext.getServerAttachment().getAttachment(CLIENT_IP);
}
/**
* 获取回调地址
*/
public static String getNotifyUrl() {
return RpcContext.getServerAttachment().getAttachment(NOTIFY_URL_NAME);
}
public static String getTraceId() {
return RpcContext.getServerAttachment().getAttachment(TRACE_ID);
}
}

View File

@@ -0,0 +1,145 @@
package com.gitee.sop.support.register;
import com.alibaba.fastjson2.JSON;
import com.gitee.sop.support.annotation.Open;
import com.gitee.sop.support.service.ApiRegisterService;
import com.gitee.sop.support.service.dto.RegisterDTO;
import lombok.Data;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.dubbo.config.annotation.DubboService;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author 六如
*/
public class ApiRegister {
private static final Log LOG = LogFactory.getLog(ApiRegister.class);
private final ApiRegisterService apiRegisterService;
public ApiRegister(ApiRegisterService apiRegisterService) {
this.apiRegisterService = apiRegisterService;
}
public void reg(String appName, Collection<Object> objects) {
if (objects == null || objects.isEmpty()) {
return;
}
for (Object serviceObj : objects) {
Class<?> objClass = serviceObj.getClass();
if (objClass.getAnnotation(DubboService.class) == null) {
continue;
}
checkClass(objClass);
doWithMethod(objClass, (interfaceClass, method, open) ->
this.regApi(appName, interfaceClass, method, open));
}
}
protected void doWithMethod(Class<?> objClass, RegisterCallback callback) {
for (Method method : objClass.getMethods()) {
Class<?> declaringClass = method.getDeclaringClass();
if (declaringClass == Object.class) {
continue;
}
for (Class<?> anInterface : declaringClass.getInterfaces()) {
try {
Method parentMethod = anInterface.getMethod(method.getName(), method.getParameterTypes());
Open open = method.getAnnotation(Open.class);
if (open == null) {
open = parentMethod.getAnnotation(Open.class);
}
if (open != null) {
callback.callback(anInterface, parentMethod, open);
}
} catch (NoSuchMethodException e) {
// ignore
}
}
}
}
private void regApi(String appName, Class<?> interfaceClass, Method method, Open open) {
List<ParamInfo> paramInfos = buildParamInfo(method);
RegisterDTO registerDTO = new RegisterDTO();
registerDTO.setApplication(appName);
registerDTO.setApiName(open.value());
registerDTO.setApiVersion(open.version());
registerDTO.setInterfaceClassName(interfaceClass.getName());
registerDTO.setMethodName(method.getName());
registerDTO.setParamInfo(JSON.toJSONString(paramInfos));
registerDTO.setIsPermission(parseBoolean(open.permission()));
registerDTO.setIsNeedToken(parseBoolean(open.needToken()));
LOG.info("注册开放接口, apiInfo=" + registerDTO);
try {
apiRegisterService.register(registerDTO);
} catch (Exception e) {
LOG.error("接口注册失败, registerDTO=" + registerDTO + ", method=" + method, e);
}
}
private List<ParamInfo> buildParamInfo(Method method) {
Parameter[] parameters = method.getParameters();
if (parameters.length == 0) {
return Collections.emptyList();
}
return Stream.of(parameters)
.map(parameter -> {
ParamInfo paramInfo = new ParamInfo();
paramInfo.setName(parameter.getName());
paramInfo.setType(parameter.getType().getName());
Type parameterizedType = parameter.getParameterizedType();
// 如果是集合
if (parameterizedType instanceof ParameterizedType) {
if (!Collection.class.isAssignableFrom(parameter.getType())) {
throw new IllegalArgumentException("开放接口参数不正确,只支持集合泛型, method={}" + method);
}
ParameterizedType genericType = (ParameterizedType) parameterizedType;
Type[] actualTypeArguments = genericType.getActualTypeArguments();
Type actualTypeArgument = actualTypeArguments[0];
paramInfo.setActualType(actualTypeArgument.getTypeName());
}
return paramInfo;
})
.collect(Collectors.toList());
}
private int parseBoolean(boolean b) {
return b ? 1 : 0;
}
private void checkClass(Class<?> objClass) {
Class<?>[] interfaces = objClass.getInterfaces();
if (interfaces.length == 0) {
throw new RuntimeException("Dubbo接口必须要实现接口, class=" + objClass.getName());
}
}
@Data
private static class ParamInfo implements Serializable {
private static final long serialVersionUID = -404173450677698875L;
private String name;
private String type;
private String actualType;
}
}

View File

@@ -0,0 +1,10 @@
package com.gitee.sop.support.register;
import com.gitee.sop.support.annotation.Open;
import java.lang.reflect.Method;
@FunctionalInterface
public interface RegisterCallback {
void callback(Class<?> interfaceClass, Method method, Open open);
}

View File

@@ -0,0 +1,64 @@
package com.gitee.sop.support.request;
import lombok.Setter;
import java.io.Serializable;
/**
* @author 六如
*/
@Setter
public class CommonFileData implements FileData, Serializable {
private static final long serialVersionUID = -7737314661756983260L;
/**
* 上传文件表单名称
*/
private String name;
/**
* 原始文件名称,可能为null
*/
private String originalFilename;
/**
* 文件的contentType,可能为null
*/
private String contentType;
/**
* 文件内容
*/
private byte[] data;
@Override
public String getName() {
return name;
}
@Override
public String getOriginalFilename() {
return originalFilename;
}
@Override
public String getContentType() {
return contentType;
}
@Override
public boolean isEmpty() {
return data == null || data.length == 0;
}
@Override
public long getSize() {
return data == null ? 0 : data.length;
}
@Override
public byte[] getBytes() {
return data;
}
}

View File

@@ -0,0 +1,48 @@
package com.gitee.sop.support.request;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
/**
* @author 六如
*/
public interface FileData {
/**
* 返回表单字段名
*/
String getName();
/**
* 返回文件原始名称.
*/
String getOriginalFilename();
/**
* 返回文件Content type,没有指定返回null
*/
String getContentType();
/**
* 文件内容是否为空
*/
boolean isEmpty();
/**
* 返回文件内容大小单位byte,没有返回0
*/
long getSize();
/**
* 返回文字字节内容
*/
byte[] getBytes();
/**
* 返回文件流
*/
default InputStream getInputStream() {
return new ByteArrayInputStream(getBytes());
}
}

View File

@@ -0,0 +1,15 @@
package com.gitee.sop.support.service;
import com.gitee.sop.support.service.dto.RegisterDTO;
/**
* @author 六如
*/
public interface ApiRegisterService {
/**
* 接口注册
*
* @param registerDTO 接口信息
*/
void register(RegisterDTO registerDTO);
}

View File

@@ -0,0 +1,8 @@
package com.gitee.sop.support.service;
/**
* @author 六如
*/
public interface IsvService {
void refresh(String appId);
}

View File

@@ -0,0 +1,36 @@
package com.gitee.sop.support.service.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @author 六如
*/
@Data
public class RegisterDTO implements Serializable {
private static final long serialVersionUID = 2183251167679411550L;
private String application;
private String apiName;
private String apiVersion;
private String interfaceClassName;
private String methodName;
/**
* 字段信息
*
* [{"name":"id": "type":"java.lang.Integer"}]
*/
private String paramInfo;
private Integer isPermission;
private Integer isNeedToken;
}

View File

@@ -0,0 +1 @@
com.gitee.sop.support.request.CommonFileData

View File

@@ -0,0 +1,84 @@
package com.gitee.sop.support;
import junit.framework.TestCase;
import org.junit.Test;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
/**
* @author 六如
*/
public class FindTest extends TestCase {
@Test
public void testFind() {
ServiceImpl service = new ServiceImpl();
Class<?> aClass = service.getClass();
for (Method method : aClass.getMethods()) {
Class<?> declaringClass = method.getDeclaringClass();
if (declaringClass == Object.class) {
continue;
}
//System.out.println(method);
// System.out.println(method.getDeclaringClass().isInterface());
for (Class<?> anInterface : declaringClass.getInterfaces()) {
try {
Method parentMethod = anInterface.getMethod(method.getName(), method.getParameterTypes());
if (method.getName().equals(parentMethod.getName())) {
System.out.println("same:" + method);
}
} catch (NoSuchMethodException e) {
// ignore
}
}
}
}
interface Service {
void h();
String say();
void hello(int i);
String hello2(int i, List list);
String hello3(int i, int... j);
}
static class ServiceImpl implements Service {
@Override
public void h() {
}
@Override
public String say() {
return "";
}
@Override
public void hello(int i) {
}
@Override
public String hello2(int i, List list) {
return "";
}
@Override
public String hello3(int i, int... j) {
return "";
}
public int add() {
return 0;
}
}
}