SNCP、REST支持部分含泛型继承的类

This commit is contained in:
Redkale
2018-02-08 10:44:38 +08:00
parent 722ab55591
commit fdb7ca29bc
5 changed files with 49 additions and 17 deletions

View File

@@ -79,7 +79,7 @@ public final class Rest {
private Rest() {
}
public static class MethodParamClassVisitor extends ClassVisitor {
static class MethodParamClassVisitor extends ClassVisitor {
private final Map<String, List<String>> fieldmap;
@@ -92,7 +92,9 @@ public final class Rest {
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (java.lang.reflect.Modifier.isStatic(access)) return null;
List<String> fieldnames = new ArrayList<>();
fieldmap.put(name + ":" + desc, fieldnames);
String key = name + ":" + desc;
if (fieldmap.containsKey(key)) return null;
fieldmap.put(key, fieldnames);
return new MethodVisitor(Opcodes.ASM5) {
@Override
public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) {
@@ -111,16 +113,17 @@ public final class Rest {
}
//返回的List中参数列表可能会比方法参数量多因为方法内的临时变量也会存入list中 所以需要list的元素集合比方法的参数多
public static Map<String, List<String>> getMethodParamNames(Class clazz) {
public static Map<String, List<String>> getMethodParamNames(Map<String, List<String>> map, Class clazz) {
String n = clazz.getName();
InputStream in = clazz.getResourceAsStream(n.substring(n.lastIndexOf('.') + 1) + ".class");
Map<String, List<String>> map = new HashMap<>();
if (in == null) return map;
try {
new ClassReader(Utility.readBytesThenClose(in)).accept(new MethodParamClassVisitor(Opcodes.ASM5, map), 0);
} catch (Exception e) { //无需理会
} catch (Exception e) { //无需理会
}
return map;
Class superClass = clazz.getSuperclass();
if (superClass == Object.class) return map;
return getMethodParamNames(map, superClass);
}
}
@@ -184,7 +187,7 @@ public final class Rest {
}
}
static <T extends HttpServlet> T createRestWebSocketServlet(final ClassLoader classLoader, final Class<? extends WebSocket> webSocketType) {
public static <T extends HttpServlet> T createRestWebSocketServlet(final ClassLoader classLoader, final Class<? extends WebSocket> webSocketType) {
if (webSocketType == null) throw new RuntimeException("Rest WebSocket Class is null on createRestWebSocketServlet");
if (Modifier.isAbstract(webSocketType.getModifiers())) throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") cannot abstract on createRestWebSocketServlet");
if (Modifier.isFinal(webSocketType.getModifiers())) throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") cannot final on createRestWebSocketServlet");
@@ -233,7 +236,7 @@ public final class Rest {
final String resourceGenericDescriptor = sb1.length() == sb2.length() ? null : sb2.toString();
//----------------------------------------------------------------------------------------
final Map<String, List<String>> asmParamMap = MethodParamClassVisitor.getMethodParamNames(webSocketType);
final Map<String, List<String>> asmParamMap = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), webSocketType);
final Set<String> messageNames = new HashSet<>();
final List<Method> messageMethods = new ArrayList<>();
for (Method method : webSocketType.getMethods()) {
@@ -640,7 +643,7 @@ public final class Rest {
}
}
static <T extends HttpServlet> T createRestServlet(final ClassLoader classLoader, final Class userType0, final Class<T> baseServletType, final Class<? extends Service> serviceType) {
public static <T extends HttpServlet> T createRestServlet(final ClassLoader classLoader, final Class userType0, final Class<T> baseServletType, final Class<? extends Service> serviceType) {
if (baseServletType == null || serviceType == null) throw new RuntimeException(" Servlet or Service is null Class on createRestServlet");
if (!HttpServlet.class.isAssignableFrom(baseServletType)) throw new RuntimeException(baseServletType + " is not HttpServlet Class on createRestServlet");
int mod = baseServletType.getModifiers();
@@ -782,7 +785,7 @@ public final class Rest {
}
}
if (ignore) continue;
paramtypes.add(method.getGenericParameterTypes());
paramtypes.add(TypeToken.getGenericType(method.getGenericParameterTypes(), serviceType));
if (mappings.length == 0) { //没有Mapping设置一个默认值
MappingEntry entry = new MappingEntry(methodidex, null, bigmodulename, method);
if (entrys.contains(entry)) throw new RuntimeException(serviceType.getName() + " on " + method.getName() + " 's mapping(" + entry.name + ") is repeat");
@@ -798,7 +801,7 @@ public final class Rest {
}
if (entrys.isEmpty()) return null; //没有可HttpMapping的方法
//将每个Service可转换的方法生成HttpServlet对应的HttpMapping方法
final Map<String, List<String>> asmParamMap = MethodParamClassVisitor.getMethodParamNames(serviceType);
final Map<String, List<String>> asmParamMap = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), serviceType);
final Map<String, java.lang.reflect.Type> bodyTypes = new HashMap<>();
final List<RestConvert[]> restConverts = new ArrayList<>();
@@ -986,7 +989,7 @@ public final class Rest {
}
av1.visitEnd();
java.lang.reflect.Type grt = method.getGenericReturnType();
java.lang.reflect.Type grt = TypeToken.getGenericType(method.getGenericReturnType(), serviceType);
av0.visit("result", grt == returnType ? returnType.getName() : String.valueOf(grt));
av0.visitEnd();

View File

@@ -99,7 +99,7 @@ public abstract class WebSocketServlet extends HttpServlet implements Resourcabl
for (Method method : this.getClass().getDeclaredMethods()) {
if (!method.getName().equals("createWebSocket")) continue;
if (method.getParameterCount() > 0) continue;
Type rt = method.getGenericReturnType();
Type rt = TypeToken.getGenericType(method.getGenericReturnType(), this.getClass());
if (rt instanceof ParameterizedType) {
msgtype = ((ParameterizedType) rt).getActualTypeArguments()[1];
}

View File

@@ -550,7 +550,7 @@ public final class SncpClient {
public SncpAction(final Class clazz, Method method, DLong actionid) {
this.actionid = actionid == null ? Sncp.hash(method) : actionid;
Type rt = method.getGenericReturnType();
Type rt = TypeToken.getGenericType(method.getGenericReturnType(), clazz);
if (rt instanceof TypeVariable) {
TypeVariable tv = (TypeVariable) rt;
if (tv.getBounds().length == 1) rt = tv.getBounds()[0];
@@ -558,7 +558,7 @@ public final class SncpClient {
this.resultTypes = rt == void.class ? null : rt;
this.boolReturnTypeFuture = CompletableFuture.class.isAssignableFrom(method.getReturnType());
this.futureCreator = boolReturnTypeFuture ? Creator.create((Class<? extends CompletableFuture>) method.getReturnType()) : null;
this.paramTypes = method.getGenericParameterTypes();
this.paramTypes = TypeToken.getGenericType(method.getGenericParameterTypes(), clazz);
this.paramClass = method.getParameterTypes();
this.method = method;
Annotation[][] anns = method.getParameterAnnotations();

View File

@@ -588,9 +588,9 @@ public final class SncpDynServlet extends SncpServlet {
try {
SncpServletAction instance = (SncpServletAction) newClazz.newInstance();
instance.method = method;
java.lang.reflect.Type[] ptypes = method.getGenericParameterTypes();
java.lang.reflect.Type[] ptypes = TypeToken.getGenericType(method.getGenericParameterTypes(), newClazz);
java.lang.reflect.Type[] types = new java.lang.reflect.Type[ptypes.length + 1];
java.lang.reflect.Type rt = method.getGenericReturnType();
java.lang.reflect.Type rt = TypeToken.getGenericType(method.getGenericReturnType(), newClazz);
if (rt instanceof TypeVariable) {
TypeVariable tv = (TypeVariable) rt;
if (tv.getBounds().length == 1) rt = tv.getBounds()[0];

View File

@@ -56,6 +56,35 @@ public abstract class TypeToken<T> {
return true;
}
public static Type[] getGenericType(final Type[] types, final Type declaringClass) {
Type[] newTypes = new Type[types.length];
for (int i = 0; i < newTypes.length; i++) {
newTypes[i] = getGenericType(types[i], declaringClass);
}
return newTypes;
}
public static Type getGenericType(final Type type, final Type declaringClass) {
if (declaringClass == null) return type;
if (type instanceof TypeVariable) {
if (declaringClass instanceof Class) {
final Class declaringClass0 = (Class) declaringClass;
final Type superType = declaringClass0.getGenericSuperclass();
if (superType instanceof ParameterizedType) {
ParameterizedType superPT = (ParameterizedType) superType;
Type[] atas = superPT.getActualTypeArguments();
TypeVariable[] asts = declaringClass0.getSuperclass().getTypeParameters();
if (atas.length == asts.length) {
for (int i = 0; i < asts.length; i++) {
if (asts[i] == type) return atas[i];
}
}
}
}
}
return type;
}
/**
* 动态创建类型为ParameterizedType或Class的Type
*