This commit is contained in:
kamhung
2015-12-08 15:21:31 +08:00
parent 48b0b4f192
commit c7dbd039af
4 changed files with 127 additions and 20 deletions

View File

@@ -10,7 +10,7 @@ import java.lang.annotation.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 参数回写
* 参数回写, 当Service的方法需要更改参数对象内部的数据时需要使用SncpCall
*
* @author zhangjx
*/

View File

@@ -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> T remote(final BsonConvert convert, Transport transport, final int index, final Object... params) {
Future<byte[]> 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 <T> 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 <T> 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);
}
}
}

View File

@@ -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) {

View File

@@ -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<T, F> implements Attribute<T[], F[]> {
@Override
public Class<? extends F[]> type() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
return (Class<F[]>) (Class) Serializable[].class;
}
@Override