This commit is contained in:
@@ -10,7 +10,7 @@ import java.lang.annotation.*;
|
|||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 参数回写
|
* 参数回写, 当Service的方法需要更改参数对象内部的数据时,需要使用SncpCall
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ public final class SncpClient {
|
|||||||
|
|
||||||
protected final Type[] paramTypes;
|
protected final Type[] paramTypes;
|
||||||
|
|
||||||
|
protected final Attribute[] paramAttrs; // 为null表示无SncpCall处理,index=0固定为null, 其他为参数标记的SncpCall回调方法
|
||||||
|
|
||||||
protected final int addressParamIndex;
|
protected final int addressParamIndex;
|
||||||
|
|
||||||
public SncpAction(Method method, DLong actionid) {
|
public SncpAction(Method method, DLong actionid) {
|
||||||
@@ -50,6 +52,8 @@ public final class SncpClient {
|
|||||||
this.method = method;
|
this.method = method;
|
||||||
Annotation[][] anns = method.getParameterAnnotations();
|
Annotation[][] anns = method.getParameterAnnotations();
|
||||||
int addrIndex = -1;
|
int addrIndex = -1;
|
||||||
|
boolean hasattr = false;
|
||||||
|
Attribute[] atts = new Attribute[paramTypes.length + 1];
|
||||||
if (anns.length > 0) {
|
if (anns.length > 0) {
|
||||||
Class<?>[] params = method.getParameterTypes();
|
Class<?>[] params = method.getParameterTypes();
|
||||||
for (int i = 0; i < anns.length; i++) {
|
for (int i = 0; i < anns.length; i++) {
|
||||||
@@ -60,10 +64,22 @@ public final class SncpClient {
|
|||||||
break;
|
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.addressParamIndex = addrIndex;
|
||||||
|
this.paramAttrs = hasattr ? atts : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
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) {
|
public <T> T remote(final BsonConvert convert, Transport transport, final int index, final Object... params) {
|
||||||
Future<byte[]> future = remote(convert, transport, actions[index], params);
|
Future<byte[]> future = remote(convert, transport, actions[index], params);
|
||||||
|
final BsonReader in = convert.pollBsonReader();
|
||||||
try {
|
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) {
|
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||||
logger.log(Level.SEVERE, actions[index].method + " sncp (params: " + jsonConvert.convertTo(params) + ") remote error", 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);
|
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) {
|
public <T> void remote(final BsonConvert convert, Transport[] transports, boolean run, final int index, final Object... params) {
|
||||||
if (!run) return;
|
if (!run || transports == null || transports.length < 1) return;
|
||||||
for (Transport transport : transports) {
|
remote(convert, transports[0], index, params);
|
||||||
remote(convert, transport, actions[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) {
|
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) {
|
if (executor != null) {
|
||||||
executor.accept(() -> {
|
executor.accept(() -> {
|
||||||
for (Transport transport : transports) {
|
remote(convert, transports[0], index, params);
|
||||||
remote(convert, transport, actions[index], params);
|
for (int i = 1; i < transports.length; i++) {
|
||||||
|
remote(convert, transports[i], actions[index], params);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
for (Transport transport : transports) {
|
remote(convert, transports[0], index, params);
|
||||||
remote(convert, transport, actions[index], params);
|
for (int i = 1; i < transports.length; i++) {
|
||||||
|
remote(convert, transports[i], actions[index], params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import static com.wentch.redkale.net.sncp.SncpRequest.DEFAULT_HEADER;
|
|||||||
import com.wentch.redkale.service.*;
|
import com.wentch.redkale.service.*;
|
||||||
import com.wentch.redkale.util.*;
|
import com.wentch.redkale.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.lang.annotation.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -26,7 +27,7 @@ import jdk.internal.org.objectweb.asm.Type;
|
|||||||
*/
|
*/
|
||||||
public final class SncpDynServlet extends SncpServlet {
|
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);
|
private final boolean finest = logger.isLoggable(Level.FINEST);
|
||||||
|
|
||||||
@@ -117,11 +118,25 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
@Resource
|
@Resource
|
||||||
protected BsonConvert convert;
|
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
|
protected java.lang.reflect.Type[] paramTypes; //index=0表示返回参数的type, void的返回参数类型为null
|
||||||
|
|
||||||
public abstract void action(final BsonReader in, final BsonWriter out) throws Throwable;
|
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 class TestService implements Service {
|
||||||
* public boolean change(TestBean bean, String name, int id) {
|
* 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]);
|
* String arg2 = convert.convertFrom(in, paramTypes[2]);
|
||||||
* int arg3 = convert.convertFrom(in, paramTypes[3]);
|
* int arg3 = convert.convertFrom(in, paramTypes[3]);
|
||||||
* Object rs = service.change(arg1, arg2, arg3);
|
* Object rs = service.change(arg1, arg2, arg3);
|
||||||
|
* callParameter(out, arg1, arg2, arg3);
|
||||||
* convert.convertTo(out, paramTypes[0], rs);
|
* 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);
|
mv.visitMethodInsn(INVOKEVIRTUAL, serviceName, method.getName(), Type.getMethodDescriptor(method), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxStack = codes.length > 0 ? codes[codes.length - 1][1] : 1;
|
final Class returnClass = method.getReturnType();
|
||||||
Class returnClass = method.getReturnType();
|
if (returnClass != void.class) {
|
||||||
if (method.getReturnType() == void.class) { //返回
|
|
||||||
mv.visitInsn(RETURN);
|
|
||||||
maxStack = 8;
|
|
||||||
} else {
|
|
||||||
if (returnClass.isPrimitive()) {
|
if (returnClass.isPrimitive()) {
|
||||||
Class bigClass = Array.get(Array.newInstance(returnClass, 1), 0).getClass();
|
Class bigClass = Array.get(Array.newInstance(returnClass, 1), 0).getClass();
|
||||||
try {
|
try {
|
||||||
@@ -282,6 +294,51 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mv.visitVarInsn(ASTORE, store); //11
|
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.visitVarInsn(ALOAD, 0);
|
||||||
mv.visitFieldInsn(GETFIELD, newDynName, "convert", Type.getDescriptor(BsonConvert.class));
|
mv.visitFieldInsn(GETFIELD, newDynName, "convert", Type.getDescriptor(BsonConvert.class));
|
||||||
mv.visitVarInsn(ALOAD, 2);
|
mv.visitVarInsn(ALOAD, 2);
|
||||||
@@ -319,6 +376,26 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
types[0] = rt;
|
types[0] = rt;
|
||||||
System.arraycopy(ptypes, 0, types, 1, ptypes.length);
|
System.arraycopy(ptypes, 0, types, 1, ptypes.length);
|
||||||
instance.paramTypes = types;
|
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);
|
newClazz.getField("service").set(instance, service);
|
||||||
return instance;
|
return instance;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package com.wentch.redkale.source;
|
package com.wentch.redkale.source;
|
||||||
|
|
||||||
import com.wentch.redkale.util.*;
|
import com.wentch.redkale.util.*;
|
||||||
|
import java.io.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ public final class EntityCallAttribute<T, F> implements Attribute<T[], F[]> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<? extends F[]> type() {
|
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
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user