From 3531d0963d1428f8013d3afb54beb407f031c1f2 Mon Sep 17 00:00:00 2001 From: Redkale <22250530@qq.com> Date: Fri, 17 Mar 2017 17:57:24 +0800 Subject: [PATCH] --- src/org/redkale/convert/MapDecoder.java | 8 ++- src/org/redkale/net/http/Rest.java | 57 ++++++++++++++++--- test/org/redkale/test/rest/HelloService.java | 11 +++- .../test/rest/_DynHelloRestServlet1.java | 3 + 4 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/org/redkale/convert/MapDecoder.java b/src/org/redkale/convert/MapDecoder.java index 1caa2289f..bf9e4d7fb 100644 --- a/src/org/redkale/convert/MapDecoder.java +++ b/src/org/redkale/convert/MapDecoder.java @@ -5,13 +5,15 @@ */ package org.redkale.convert; +import java.io.Serializable; import org.redkale.util.Creator; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Map; /** - * Map的反序列化操作类 + * Map的反序列化操作类
+ * key、value的类型如果是Serializable, 会自动转换成String * *

* 详情见: https://redkale.org @@ -48,8 +50,8 @@ public final class MapDecoder implements Decodeable> { this.valueType = pt.getActualTypeArguments()[1]; this.creator = factory.loadCreator((Class) pt.getRawType()); factory.register(type, this); - this.keyDecoder = factory.loadDecoder(this.keyType); - this.valueDecoder = factory.loadDecoder(this.valueType); + this.keyDecoder = factory.loadDecoder(this.keyType == Serializable.class ? String.class : this.keyType); + this.valueDecoder = factory.loadDecoder(this.valueType == Serializable.class ? String.class : this.valueType); } else { throw new ConvertException("mapdecoder not support the type (" + type + ")"); } diff --git a/src/org/redkale/net/http/Rest.java b/src/org/redkale/net/http/Rest.java index d24deee50..6f71551cb 100644 --- a/src/org/redkale/net/http/Rest.java +++ b/src/org/redkale/net/http/Rest.java @@ -36,6 +36,8 @@ public final class Rest { static final String REST_SERVICEMAP_FIELD_NAME = "_servicemap"; //如果只有name=""的Service资源,则实例中_servicemap必须为null + private static final String REST_PARAMTYPES_FIELD_NAME = "_paramtypes"; //存在泛型的参数数组 Type[][] 第1维度是方法的下标, 第二维度是参数的下标 + private static final Set EXCLUDERMETHODS = new HashSet<>(); static { @@ -99,10 +101,7 @@ public final class Rest { if (controller != null && controller.ignore()) return null; //标记为ignore=true不创建Servlet ClassLoader loader = Sncp.class.getClassLoader(); String newDynName = serviceTypeInternalName.substring(0, serviceTypeInternalName.lastIndexOf('/') + 1) + "_Dyn" + serviceType.getSimpleName().replaceAll("Service.*$", "") + "RestServlet"; - try { - return ((Class) Class.forName(newDynName.replace('/', '.'))).newInstance(); - } catch (Exception ex) { - } + Method currentUserMethod = null; try { currentUserMethod = baseServletClass.getDeclaredMethod("currentUser", HttpRequest.class); @@ -163,6 +162,10 @@ public final class Rest { fv = cw.visitField(ACC_PRIVATE, REST_SERVICEMAP_FIELD_NAME, "Ljava/util/Map;", "Ljava/util/Map;", null); fv.visitEnd(); } + { //_paramtypes字段 java.lang.reflect.Type[][] + fv = cw.visitField(ACC_PRIVATE, REST_PARAMTYPES_FIELD_NAME, "[[Ljava/lang/reflect/Type;", null, null); + fv.visitEnd(); + } { //构造函数 mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "", "()V", null, null)); //mv.setDebug(true); @@ -176,6 +179,8 @@ public final class Rest { final List entrys = new ArrayList<>(); final Map restAttributes = new LinkedHashMap<>(); //获取所有可以转换成WebMapping的方法 + int methodidex = 0; + final List paramtypes = new ArrayList<>(); for (final Method method : serviceType.getMethods()) { if (Modifier.isStatic(method.getModifiers())) continue; Class[] extypes = method.getExceptionTypes(); @@ -195,17 +200,19 @@ public final class Rest { } } if (ignore) continue; + paramtypes.add(method.getGenericParameterTypes()); if (mappings.length == 0) { //没有Mapping,设置一个默认值 - MappingEntry entry = new MappingEntry(null, defmodulename, method); + MappingEntry entry = new MappingEntry(methodidex, null, defmodulename, method); if (entrys.contains(entry)) throw new RuntimeException(serviceType.getName() + " on " + method.getName() + " 's mapping(" + entry.name + ") is repeat"); entrys.add(entry); } else { for (RestMapping mapping : mappings) { - MappingEntry entry = new MappingEntry(mapping, defmodulename, method); + MappingEntry entry = new MappingEntry(methodidex, mapping, defmodulename, method); if (entrys.contains(entry)) throw new RuntimeException(serviceType.getName() + " on " + method.getName() + " 's mapping(" + entry.name + ") is repeat"); entrys.add(entry); } } + methodidex++; } if (entrys.isEmpty()) return null; //没有可WebMapping的方法 @@ -380,6 +387,7 @@ public final class Rest { boolean hasAsyncHandler = false; for (Object[] ps : paramlist) { Map paramMap = new LinkedHashMap<>(); + final Parameter param = (Parameter) ps[0]; //参数类型 String pname = (String) ps[1]; //参数名 Class ptype = (Class) ps[2]; //参数类型 int radix = (Integer) ps[3]; @@ -644,7 +652,31 @@ public final class Rest { varInsns.add(new int[]{ALOAD, maxLocals}); } else { //其他Json对象 mv.visitVarInsn(ALOAD, 1); - mv.visitLdcInsn(Type.getType(Type.getDescriptor(ptype))); + if (param.getType() == param.getParameterizedType()) { + mv.visitLdcInsn(Type.getType(Type.getDescriptor(ptype))); + } else { + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, newDynName, REST_PARAMTYPES_FIELD_NAME, "[[Ljava/lang/reflect/Type;"); + if (entry.methodidx <= 5) { //方法下标 + mv.visitInsn(ICONST_0 + entry.methodidx); + } else { + mv.visitIntInsn(BIPUSH, entry.methodidx); + } + mv.visitInsn(AALOAD); + int paramidx = 0; + for (int i = 0; i < params.length; i++) { + if (params[i] == param) { + paramidx = i; + break; + } + } + if (paramidx <= 5) { //参数下标 + mv.visitInsn(ICONST_0 + paramidx); + } else { + mv.visitIntInsn(BIPUSH, paramidx); + } + mv.visitInsn(AALOAD); + } mv.visitLdcInsn(pname); mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getJsonHeader" : "getJsonParameter", "(Ljava/lang/reflect/Type;Ljava/lang/String;)Ljava/lang/Object;", false); mv.visitTypeInsn(CHECKCAST, ptype.getName().replace('.', '/')); @@ -885,6 +917,12 @@ public final class Rest { attrField.setAccessible(true); attrField.set(obj, en.getValue()); } + Field typesfield = newClazz.getDeclaredField(REST_PARAMTYPES_FIELD_NAME); + typesfield.setAccessible(true); + java.lang.reflect.Type[][] paramtypeArray = new java.lang.reflect.Type[paramtypes.size()][]; + paramtypeArray = paramtypes.toArray(paramtypeArray); + typesfield.set(obj, paramtypeArray); + return obj; } catch (Exception e) { throw new RuntimeException(e); @@ -916,8 +954,9 @@ public final class Rest { } } - public MappingEntry(RestMapping mapping, final String defmodulename, Method method) { + public MappingEntry(int methodidx, RestMapping mapping, final String defmodulename, Method method) { if (mapping == null) mapping = DEFAULT__MAPPING; + this.methodidx = methodidx; this.ignore = mapping.ignore(); String n = mapping.name().toLowerCase(); if (n.isEmpty()) n = method.getName().toLowerCase().replace(defmodulename.toLowerCase(), ""); @@ -930,6 +969,8 @@ public final class Rest { this.comment = mapping.comment(); } + public final int methodidx; // _paramtypes 的下标,从0开始 + public final Method mappingMethod; public final boolean ignore; diff --git a/test/org/redkale/test/rest/HelloService.java b/test/org/redkale/test/rest/HelloService.java index 2e1fac4a1..84bd31cbd 100644 --- a/test/org/redkale/test/rest/HelloService.java +++ b/test/org/redkale/test/rest/HelloService.java @@ -1,6 +1,7 @@ package org.redkale.test.rest; -import java.util.List; +import java.io.Serializable; +import java.util.*; import javax.annotation.Resource; import org.redkale.net.http.*; @@ -70,6 +71,14 @@ public class HelloService implements Service { return source.queryList(HelloEntity.class, bean); } + //查询List列表 + @RestMapping(name = "listmap") + public List queryHello(HelloBean bean, @RestParam(name = "map") Map map) { //通过 /pipes/hello/list?bean={...} 查询List列表 + System.out.println("map参数: " + map); + if (source != null) return source.queryList(HelloEntity.class, bean); + return null; + } + //查询单个 @RestMapping(name = "find") public HelloEntity findHello(@RestParam(name = "#") int id) { //通过 /pipes/hello/find/1234、/pipes/hello/jsfind/1234 查询对象 diff --git a/test/org/redkale/test/rest/_DynHelloRestServlet1.java b/test/org/redkale/test/rest/_DynHelloRestServlet1.java index 72797439f..b21887d58 100644 --- a/test/org/redkale/test/rest/_DynHelloRestServlet1.java +++ b/test/org/redkale/test/rest/_DynHelloRestServlet1.java @@ -41,6 +41,9 @@ public class _DynHelloRestServlet1 extends SimpleRestServlet { url = "http://127.0.0.1:" + port + "/pipes/hello/asyncfind/1234"; System.out.println(Utility.postHttpContent(url, headers, null)); + + url = "http://127.0.0.1:" + port + "/pipes/hello/listmap?map={'a':5}"; + System.out.println(Utility.postHttpContent(url, headers, null)); }