From c7dbd039afd6b84013f011fe814ae234c774e468 Mon Sep 17 00:00:00 2001 From: kamhung <22250530@qq.com> Date: Tue, 8 Dec 2015 15:21:31 +0800 Subject: [PATCH] --- src/com/wentch/redkale/net/sncp/SncpCall.java | 2 +- .../wentch/redkale/net/sncp/SncpClient.java | 49 ++++++++-- .../redkale/net/sncp/SncpDynServlet.java | 93 +++++++++++++++++-- .../redkale/source/EntityCallAttribute.java | 3 +- 4 files changed, 127 insertions(+), 20 deletions(-) diff --git a/src/com/wentch/redkale/net/sncp/SncpCall.java b/src/com/wentch/redkale/net/sncp/SncpCall.java index 9dd31bb1e..eb745eb3d 100644 --- a/src/com/wentch/redkale/net/sncp/SncpCall.java +++ b/src/com/wentch/redkale/net/sncp/SncpCall.java @@ -10,7 +10,7 @@ import java.lang.annotation.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** - * 参数回写 + * 参数回写, 当Service的方法需要更改参数对象内部的数据时,需要使用SncpCall * * @author zhangjx */ diff --git a/src/com/wentch/redkale/net/sncp/SncpClient.java b/src/com/wentch/redkale/net/sncp/SncpClient.java index fd63071da..2ec6e38a2 100644 --- a/src/com/wentch/redkale/net/sncp/SncpClient.java +++ b/src/com/wentch/redkale/net/sncp/SncpClient.java @@ -36,6 +36,8 @@ public final class SncpClient { protected final Type[] paramTypes; + protected final Attribute[] paramAttrs; // 为null表示无SncpCall处理,index=0固定为null, 其他为参数标记的SncpCall回调方法 + protected final int addressParamIndex; public SncpAction(Method method, DLong actionid) { @@ -50,6 +52,8 @@ public final class SncpClient { this.method = method; Annotation[][] anns = method.getParameterAnnotations(); int addrIndex = -1; + boolean hasattr = false; + Attribute[] atts = new Attribute[paramTypes.length + 1]; if (anns.length > 0) { Class[] params = method.getParameterTypes(); for (int i = 0; i < anns.length; i++) { @@ -60,10 +64,22 @@ public final class SncpClient { break; } } + for (Annotation ann : anns[i]) { + if (ann.annotationType() == SncpCall.class) { + try { + atts[i + 1] = ((SncpCall) ann).value().newInstance(); + hasattr = true; + } catch (Exception e) { + logger.log(Level.SEVERE, SncpCall.class.getSimpleName() + ".attribute cannot a newInstance for" + method); + } + break; + } + } } } } this.addressParamIndex = addrIndex; + this.paramAttrs = hasattr ? atts : null; } @Override @@ -72,7 +88,7 @@ public final class SncpClient { } } - private final Logger logger = Logger.getLogger(SncpClient.class.getSimpleName()); + private static final Logger logger = Logger.getLogger(SncpClient.class.getSimpleName()); private final boolean finest = logger.isLoggable(Level.FINEST); @@ -182,32 +198,45 @@ public final class SncpClient { public T remote(final BsonConvert convert, Transport transport, final int index, final Object... params) { Future future = remote(convert, transport, actions[index], params); + final BsonReader in = convert.pollBsonReader(); try { - return convert.convertFrom(actions[index].resultTypes, future.get(5, TimeUnit.SECONDS)); + final SncpAction action = actions[index]; + in.setBytes(future.get(5, TimeUnit.SECONDS)); + byte i = 0; + while ((i = in.readByte()) != 0) { + final Attribute attr = action.paramAttrs[i]; + attr.set(params[i - 1], convert.convertFrom(in, attr.type())); + } + return convert.convertFrom(in, action.resultTypes); } catch (InterruptedException | ExecutionException | TimeoutException e) { logger.log(Level.SEVERE, actions[index].method + " sncp (params: " + jsonConvert.convertTo(params) + ") remote error", e); throw new RuntimeException(actions[index].method + " sncp remote error", e); + } finally { + convert.offerBsonReader(in); } } public void remote(final BsonConvert convert, Transport[] transports, boolean run, final int index, final Object... params) { - if (!run) return; - for (Transport transport : transports) { - remote(convert, transport, actions[index], params); + if (!run || transports == null || transports.length < 1) return; + remote(convert, transports[0], index, params); + for (int i = 1; i < transports.length; i++) { + remote(convert, transports[i], actions[index], params); } } public void asyncRemote(final BsonConvert convert, Transport[] transports, boolean run, final int index, final Object... params) { - if (!run) return; + if (!run || transports == null || transports.length < 1) return; if (executor != null) { executor.accept(() -> { - for (Transport transport : transports) { - remote(convert, transport, actions[index], params); + remote(convert, transports[0], index, params); + for (int i = 1; i < transports.length; i++) { + remote(convert, transports[i], actions[index], params); } }); } else { - for (Transport transport : transports) { - remote(convert, transport, actions[index], params); + remote(convert, transports[0], index, params); + for (int i = 1; i < transports.length; i++) { + remote(convert, transports[i], actions[index], params); } } } diff --git a/src/com/wentch/redkale/net/sncp/SncpDynServlet.java b/src/com/wentch/redkale/net/sncp/SncpDynServlet.java index 47e08a2d9..5befa0a7a 100644 --- a/src/com/wentch/redkale/net/sncp/SncpDynServlet.java +++ b/src/com/wentch/redkale/net/sncp/SncpDynServlet.java @@ -10,6 +10,7 @@ import static com.wentch.redkale.net.sncp.SncpRequest.DEFAULT_HEADER; import com.wentch.redkale.service.*; import com.wentch.redkale.util.*; import java.io.*; +import java.lang.annotation.*; import java.lang.reflect.*; import java.nio.*; import java.util.*; @@ -26,7 +27,7 @@ import jdk.internal.org.objectweb.asm.Type; */ public final class SncpDynServlet extends SncpServlet { - private final Logger logger = Logger.getLogger(SncpDynServlet.class.getSimpleName()); + private static final Logger logger = Logger.getLogger(SncpDynServlet.class.getSimpleName()); private final boolean finest = logger.isLoggable(Level.FINEST); @@ -117,11 +118,25 @@ public final class SncpDynServlet extends SncpServlet { @Resource protected BsonConvert convert; + protected com.wentch.redkale.util.Attribute[] paramAttrs; // 为null表示无SncpCall处理,index=0固定为null, 其他为参数标记的SncpCall回调方法 + protected java.lang.reflect.Type[] paramTypes; //index=0表示返回参数的type, void的返回参数类型为null public abstract void action(final BsonReader in, final BsonWriter out) throws Throwable; - /* + public final void callParameter(final BsonWriter out, final Object... params) { + if (paramAttrs != null) { + for (int i = 1; i < paramAttrs.length; i++) { + com.wentch.redkale.util.Attribute attr = paramAttrs[i]; + if (attr == null) continue; + out.writeByte((byte) i); + convert.convertTo(out, attr.type(), attr.get(params[i - 1])); + } + } + out.writeByte((byte) 0); + } + + /** ** * * public class TestService implements Service { * public boolean change(TestBean bean, String name, int id) { @@ -139,6 +154,7 @@ public final class SncpDynServlet extends SncpServlet { * String arg2 = convert.convertFrom(in, paramTypes[2]); * int arg3 = convert.convertFrom(in, paramTypes[3]); * Object rs = service.change(arg1, arg2, arg3); + * callParameter(out, arg1, arg2, arg3); * convert.convertTo(out, paramTypes[0], rs); * } * } @@ -266,12 +282,8 @@ public final class SncpDynServlet extends SncpServlet { mv.visitMethodInsn(INVOKEVIRTUAL, serviceName, method.getName(), Type.getMethodDescriptor(method), false); } - int maxStack = codes.length > 0 ? codes[codes.length - 1][1] : 1; - Class returnClass = method.getReturnType(); - if (method.getReturnType() == void.class) { //返回 - mv.visitInsn(RETURN); - maxStack = 8; - } else { + final Class returnClass = method.getReturnType(); + if (returnClass != void.class) { if (returnClass.isPrimitive()) { Class bigClass = Array.get(Array.newInstance(returnClass, 1), 0).getClass(); try { @@ -282,6 +294,51 @@ public final class SncpDynServlet extends SncpServlet { } } mv.visitVarInsn(ASTORE, store); //11 + } + //------------------------- callParameter 方法 -------------------------------- + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 2); + if (paramClasses.length <= 5) { //参数总数量 + mv.visitInsn(ICONST_0 + paramClasses.length); + } else { + mv.visitIntInsn(BIPUSH, paramClasses.length); + } + mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); + int insn = 2; + for (int j = 0; j < paramClasses.length; j++) { + final Class pt = paramClasses[j]; + mv.visitInsn(DUP); + insn++; + if (j <= 5) { + mv.visitInsn(ICONST_0 + j); + } else { + mv.visitIntInsn(BIPUSH, j); + } + if (pt.isPrimitive()) { + if (pt == long.class) { + mv.visitVarInsn(LLOAD, insn++); + } else if (pt == float.class) { + mv.visitVarInsn(FLOAD, insn++); + } else if (pt == double.class) { + mv.visitVarInsn(DLOAD, insn++); + } else { + mv.visitVarInsn(ILOAD, insn); + } + Class bigclaz = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(pt, 1), 0).getClass(); + mv.visitMethodInsn(INVOKESTATIC, bigclaz.getName().replace('.', '/'), "valueOf", "(" + Type.getDescriptor(pt) + ")" + Type.getDescriptor(bigclaz), false); + } else { + mv.visitVarInsn(ALOAD, insn); + } + mv.visitInsn(AASTORE); + } + mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "callParameter", "(" + convertWriterDesc + "[Ljava/lang/Object;)V", false); + + //-------------------------直接返回 或者 调用convertTo方法 -------------------------------- + int maxStack = codes.length > 0 ? codes[codes.length - 1][1] : 1; + if (returnClass == void.class) { //返回 + mv.visitInsn(RETURN); + maxStack = 8; + } else { mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, newDynName, "convert", Type.getDescriptor(BsonConvert.class)); mv.visitVarInsn(ALOAD, 2); @@ -319,6 +376,26 @@ public final class SncpDynServlet extends SncpServlet { types[0] = rt; System.arraycopy(ptypes, 0, types, 1, ptypes.length); instance.paramTypes = types; + + com.wentch.redkale.util.Attribute[] atts = new com.wentch.redkale.util.Attribute[ptypes.length + 1]; + Annotation[][] anns = method.getParameterAnnotations(); + boolean hasattr = false; + for (int i = 0; i < anns.length; i++) { + if (anns[i].length > 0) { + for (Annotation ann : anns[i]) { + if (ann.annotationType() == SncpCall.class) { + try { + atts[i + 1] = ((SncpCall) ann).value().newInstance(); + hasattr = true; + } catch (Exception e) { + logger.log(Level.SEVERE, SncpCall.class.getSimpleName() + ".attribute cannot a newInstance for" + method); + } + break; + } + } + } + } + if (hasattr) instance.paramAttrs = atts; newClazz.getField("service").set(instance, service); return instance; } catch (Exception ex) { diff --git a/src/com/wentch/redkale/source/EntityCallAttribute.java b/src/com/wentch/redkale/source/EntityCallAttribute.java index f9ffd22f6..4b3cee1f4 100644 --- a/src/com/wentch/redkale/source/EntityCallAttribute.java +++ b/src/com/wentch/redkale/source/EntityCallAttribute.java @@ -6,6 +6,7 @@ package com.wentch.redkale.source; import com.wentch.redkale.util.*; +import java.io.*; import java.lang.reflect.*; import java.util.concurrent.*; @@ -46,7 +47,7 @@ public final class EntityCallAttribute implements Attribute { @Override public Class type() { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return (Class) (Class) Serializable[].class; } @Override