From fdb7ca29bcfcf468cc824b89b0c3d1437cfe191b Mon Sep 17 00:00:00 2001 From: Redkale <22250530@qq.com> Date: Thu, 8 Feb 2018 10:44:38 +0800 Subject: [PATCH] =?UTF-8?q?SNCP=E3=80=81REST=E6=94=AF=E6=8C=81=E9=83=A8?= =?UTF-8?q?=E5=88=86=E5=90=AB=E6=B3=9B=E5=9E=8B=E7=BB=A7=E6=89=BF=E7=9A=84?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/org/redkale/net/http/Rest.java | 27 +++++++++-------- .../redkale/net/http/WebSocketServlet.java | 2 +- src/org/redkale/net/sncp/SncpClient.java | 4 +-- src/org/redkale/net/sncp/SncpDynServlet.java | 4 +-- src/org/redkale/util/TypeToken.java | 29 +++++++++++++++++++ 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/org/redkale/net/http/Rest.java b/src/org/redkale/net/http/Rest.java index 21df3dc3f..ae1b8b1c9 100644 --- a/src/org/redkale/net/http/Rest.java +++ b/src/org/redkale/net/http/Rest.java @@ -79,7 +79,7 @@ public final class Rest { private Rest() { } - public static class MethodParamClassVisitor extends ClassVisitor { + static class MethodParamClassVisitor extends ClassVisitor { private final Map> 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 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> getMethodParamNames(Class clazz) { + public static Map> getMethodParamNames(Map> map, Class clazz) { String n = clazz.getName(); InputStream in = clazz.getResourceAsStream(n.substring(n.lastIndexOf('.') + 1) + ".class"); - Map> 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 createRestWebSocketServlet(final ClassLoader classLoader, final Class webSocketType) { + public static T createRestWebSocketServlet(final ClassLoader classLoader, final Class 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> asmParamMap = MethodParamClassVisitor.getMethodParamNames(webSocketType); + final Map> asmParamMap = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), webSocketType); final Set messageNames = new HashSet<>(); final List messageMethods = new ArrayList<>(); for (Method method : webSocketType.getMethods()) { @@ -640,7 +643,7 @@ public final class Rest { } } - static T createRestServlet(final ClassLoader classLoader, final Class userType0, final Class baseServletType, final Class serviceType) { + public static T createRestServlet(final ClassLoader classLoader, final Class userType0, final Class baseServletType, final Class 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> asmParamMap = MethodParamClassVisitor.getMethodParamNames(serviceType); + final Map> asmParamMap = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), serviceType); final Map bodyTypes = new HashMap<>(); final List 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(); diff --git a/src/org/redkale/net/http/WebSocketServlet.java b/src/org/redkale/net/http/WebSocketServlet.java index 1775a8ea1..ccd36e2e0 100644 --- a/src/org/redkale/net/http/WebSocketServlet.java +++ b/src/org/redkale/net/http/WebSocketServlet.java @@ -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]; } diff --git a/src/org/redkale/net/sncp/SncpClient.java b/src/org/redkale/net/sncp/SncpClient.java index 2ebb20f06..fc8512ac0 100644 --- a/src/org/redkale/net/sncp/SncpClient.java +++ b/src/org/redkale/net/sncp/SncpClient.java @@ -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) 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(); diff --git a/src/org/redkale/net/sncp/SncpDynServlet.java b/src/org/redkale/net/sncp/SncpDynServlet.java index 61ffdc913..5752c29f0 100644 --- a/src/org/redkale/net/sncp/SncpDynServlet.java +++ b/src/org/redkale/net/sncp/SncpDynServlet.java @@ -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]; diff --git a/src/org/redkale/util/TypeToken.java b/src/org/redkale/util/TypeToken.java index 2638c8d9d..a734e283b 100644 --- a/src/org/redkale/util/TypeToken.java +++ b/src/org/redkale/util/TypeToken.java @@ -56,6 +56,35 @@ public abstract class TypeToken { 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 *