异步接口支持AsyncHandler子类
This commit is contained in:
@@ -404,11 +404,21 @@ public final class Rest {
|
||||
|
||||
paramMap.put("name", pname);
|
||||
paramMap.put("type", ptype.getName());
|
||||
if (ptype == AsyncHandler.class) { //HttpResponse.createAsyncHandler()
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "createAsyncHandler", "()Lorg/redkale/util/AsyncHandler;", false);
|
||||
mv.visitVarInsn(ASTORE, maxLocals);
|
||||
varInsns.add(new int[]{ALOAD, maxLocals});
|
||||
if (AsyncHandler.class.isAssignableFrom(ptype)) { //HttpResponse.createAsyncHandler() or HttpResponse.createAsyncHandler(Class)
|
||||
if (ptype == AsyncHandler.class) {
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "createAsyncHandler", "()Lorg/redkale/util/AsyncHandler;", false);
|
||||
mv.visitVarInsn(ASTORE, maxLocals);
|
||||
varInsns.add(new int[]{ALOAD, maxLocals});
|
||||
} else {
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitLdcInsn(Type.getType(Type.getDescriptor(ptype)));
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "createAsyncHandler", "(Lorg/redkale/net/http/HttpResponse;Ljava/lang/Class;)Lorg/redkale/util/AsyncHandler;", false);
|
||||
mv.visitTypeInsn(CHECKCAST, ptype.getName().replace('.', '/'));
|
||||
mv.visitVarInsn(ASTORE, maxLocals);
|
||||
varInsns.add(new int[]{ALOAD, maxLocals});
|
||||
}
|
||||
hasAsyncHandler = true;
|
||||
} else if (annsid != null) { //HttpRequest.getSessionid(true|false)
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
package org.redkale.net.http;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import jdk.internal.org.objectweb.asm.*;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
import org.redkale.net.sncp.SncpAsyncHandler;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -36,4 +41,126 @@ public abstract class RestHttpServlet<T> extends HttpBaseServlet {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建AsyncHandler实例,将非字符串对象以JSON格式输出,字符串以文本输出 <br>
|
||||
*
|
||||
* 传入的AsyncHandler子类必须是public,且保证其子类可被继承且completed、failed可被重载且包含空参数的构造函数。
|
||||
*
|
||||
* @param <H> AsyncHandler泛型
|
||||
* @param response HttpResponse
|
||||
* @param handlerClass Class
|
||||
*
|
||||
* @return AsyncHandler
|
||||
*/
|
||||
protected final <H extends AsyncHandler> H createAsyncHandler(HttpResponse response, final Class<H> handlerClass) {
|
||||
if (handlerClass == null || handlerClass == AsyncHandler.class) return (H) response.createAsyncHandler();
|
||||
Creator<H> creator = creators.get(handlerClass);
|
||||
if (creator == null) {
|
||||
creator = createCreator(handlerClass);
|
||||
creators.put(handlerClass, creator);
|
||||
}
|
||||
return (H) creator.create(response.createAsyncHandler());
|
||||
}
|
||||
|
||||
private static final ConcurrentHashMap<Class, Creator> creators = new ConcurrentHashMap<>();
|
||||
|
||||
private static <H extends AsyncHandler> Creator<H> createCreator(Class<H> handlerClass) {
|
||||
//-------------------------------------------------------------
|
||||
final boolean handlerinterface = handlerClass.isInterface();
|
||||
final String handlerClassName = handlerClass.getName().replace('.', '/');
|
||||
final String handlerName = AsyncHandler.class.getName().replace('.', '/');
|
||||
final String handlerDesc = Type.getDescriptor(AsyncHandler.class);
|
||||
final String newDynName = handlerClass.getName().replace('.', '/') + "_Dync" + AsyncHandler.class.getSimpleName() + "_" + (System.currentTimeMillis() % 10000);
|
||||
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||
FieldVisitor fv;
|
||||
AsmMethodVisitor mv;
|
||||
AnnotationVisitor av0;
|
||||
cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, newDynName, null, handlerinterface ? "java/lang/Object" : handlerClassName, handlerinterface ? new String[]{handlerClassName} : new String[]{handlerName});
|
||||
|
||||
{ //handler 属性
|
||||
fv = cw.visitField(ACC_PRIVATE, "handler", handlerDesc, null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{//构造方法
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "(" + handlerDesc + ")V", null, null));
|
||||
//mv.setDebug(true);
|
||||
{
|
||||
av0 = mv.visitAnnotation("Ljava/beans/ConstructorProperties;", true);
|
||||
{
|
||||
AnnotationVisitor av1 = av0.visitArray("value");
|
||||
av1.visit(null, "handler");
|
||||
av1.visitEnd();
|
||||
}
|
||||
av0.visitEnd();
|
||||
}
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, handlerinterface ? "java/lang/Object" : handlerClassName, "<init>", "()V", false);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitFieldInsn(PUTFIELD, newDynName, "handler", handlerDesc);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(2, 2);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
for (java.lang.reflect.Method method : handlerClass.getMethods()) { //
|
||||
if ("completed".equals(method.getName()) && method.getParameterCount() == 2) {
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "completed", Type.getMethodDescriptor(method), null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "handler", handlerDesc);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, handlerName, "completed", "(Ljava/lang/Object;Ljava/lang/Object;)V", true);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(3, 3);
|
||||
mv.visitEnd();
|
||||
} else if ("failed".equals(method.getName()) && method.getParameterCount() == 2) {
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "failed", Type.getMethodDescriptor(method), null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "handler", handlerDesc);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, handlerName, "failed", "(Ljava/lang/Throwable;Ljava/lang/Object;)V", true);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(3, 3);
|
||||
mv.visitEnd();
|
||||
} else if (handlerinterface || java.lang.reflect.Modifier.isAbstract(method.getModifiers())) {
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, method.getName(), Type.getMethodDescriptor(method), null, null));
|
||||
Class returnType = method.getReturnType();
|
||||
if (returnType == void.class) {
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(0, 1);
|
||||
} else if (returnType.isPrimitive()) {
|
||||
mv.visitInsn(ICONST_0);
|
||||
if (returnType == long.class) {
|
||||
mv.visitInsn(LRETURN);
|
||||
mv.visitMaxs(2, 1);
|
||||
} else if (returnType == float.class) {
|
||||
mv.visitInsn(FRETURN);
|
||||
mv.visitMaxs(2, 1);
|
||||
} else if (returnType == double.class) {
|
||||
mv.visitInsn(DRETURN);
|
||||
mv.visitMaxs(2, 1);
|
||||
} else {
|
||||
mv.visitInsn(IRETURN);
|
||||
mv.visitMaxs(1, 1);
|
||||
}
|
||||
} else {
|
||||
mv.visitInsn(ACONST_NULL);
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(1, 1);
|
||||
}
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
cw.visitEnd();
|
||||
byte[] bytes = cw.toByteArray();
|
||||
Class<SncpAsyncHandler> newHandlerClazz = (Class<SncpAsyncHandler>) new ClassLoader(handlerClass.getClassLoader()) {
|
||||
public final Class<?> loadClass(String name, byte[] b) {
|
||||
return defineClass(name, b, 0, b.length);
|
||||
}
|
||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
||||
return (Creator<H>) Creator.create(newHandlerClazz);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +149,8 @@ public abstract class Sncp {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (constructorflag) throw new RuntimeException(param + " must have a empty parameter Constructor");
|
||||
if (param.getDeclaredConstructors().length == 0) constructorflag = true;
|
||||
if (!constructorflag) throw new RuntimeException(param + " must have a empty parameter Constructor");
|
||||
for (Method m : param.getMethods()) {
|
||||
if (m.getName().equals("completed") && Modifier.isFinal(m.getModifiers())) {
|
||||
throw new RuntimeException(param + "'s completed method cannot final modifier");
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
package org.redkale.net.sncp;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import jdk.internal.org.objectweb.asm.*;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
import org.redkale.convert.bson.*;
|
||||
import org.redkale.net.sncp.SncpDynServlet.SncpServletAction;
|
||||
import org.redkale.util.AsyncHandler;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 异步回调函数 <br>
|
||||
@@ -33,59 +35,168 @@ public interface SncpAsyncHandler<V, A> extends AsyncHandler<V, A> {
|
||||
|
||||
/**
|
||||
* <blockquote><pre>
|
||||
* 若参数类型为AsyncHandler子类,必须保证其子类可被继承且completed、failed可被重载且包含空参数的构造函数。
|
||||
*
|
||||
* 考虑点:
|
||||
* 1、AsyncHandler子类是接口,且还有其他多个方法
|
||||
* 2、AsyncHandler子类是类, 需要继承,且必须有空参数构造函数
|
||||
* 3、AsyncHandler子类无论是接口还是类,都可能存在其他泛型
|
||||
*
|
||||
* public class _DyncSncpAsyncHandler_xxx extends XXXAsyncHandler implements SncpAsyncHandler {
|
||||
* public class XXXAsyncHandler_DyncSncpAsyncHandler_4323 extends XXXAsyncHandler implements SncpAsyncHandler {
|
||||
*
|
||||
* public SncpAsyncHandler handler;
|
||||
* private SncpAsyncHandler sncphandler;
|
||||
*
|
||||
* protected Object[] params;
|
||||
* @java.beans.ConstructorProperties({"sncphandler"})
|
||||
* public XXXAsyncHandler_DyncSncpAsyncHandler_4323(SncpAsyncHandler sncphandler) {
|
||||
* super();
|
||||
* this.sncphandler = sncphandler;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public void completed(Object result, Object attachment) {
|
||||
* handler.completed(result, attachment);
|
||||
* sncphandler.completed(result, attachment);
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public void failed(Throwable exc, Object attachment) {
|
||||
* handler.failed(exc, attachment);
|
||||
* sncphandler.failed(exc, attachment);
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public Object[] sncp_getParams() {
|
||||
* return params;
|
||||
* return sncphandler.sncp_getParams();
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public void sncp_setParams(Object... params) {
|
||||
* this.params = params;
|
||||
* handler.sncp_setParams(params);
|
||||
* sncphandler.sncp_setParams(params);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @param <V> 结果对象的泛型
|
||||
* @param <A> 附件对象的泛型
|
||||
* @param handlerClass AsyncHandler类型或子类
|
||||
* @param action SncpServletAction
|
||||
* @param in BsonReader
|
||||
* @param out BsonWriter
|
||||
* @param request SncpRequest
|
||||
* @param response SncpResponse
|
||||
*
|
||||
* @return SncpAsyncHandler
|
||||
* @return Creator
|
||||
*/
|
||||
public static <V, A> SncpAsyncHandler<V, A> create(Class<? extends AsyncHandler> handlerClass, SncpServletAction action,
|
||||
BsonReader in, BsonWriter out, SncpRequest request, SncpResponse response) {
|
||||
if (handlerClass == AsyncHandler.class) return new DefaultSncpAsyncHandler(action, in, out, request, response);
|
||||
//子类, 待实现
|
||||
return new DefaultSncpAsyncHandler(action, in, out, request, response);
|
||||
public static Creator<SncpAsyncHandler> createCreator(Class<? extends AsyncHandler> handlerClass) {
|
||||
//-------------------------------------------------------------
|
||||
final boolean handlerinterface = handlerClass.isInterface();
|
||||
final String handlerClassName = handlerClass.getName().replace('.', '/');
|
||||
final String sncyHandlerName = SncpAsyncHandler.class.getName().replace('.', '/');
|
||||
final String sncyHandlerDesc = Type.getDescriptor(SncpAsyncHandler.class);
|
||||
final String newDynName = handlerClass.getName().replace('.', '/') + "_Dync" + SncpAsyncHandler.class.getSimpleName() + "_" + (System.currentTimeMillis() % 10000);
|
||||
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||
FieldVisitor fv;
|
||||
AsmMethodVisitor mv;
|
||||
AnnotationVisitor av0;
|
||||
cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, newDynName, null, handlerinterface ? "java/lang/Object" : handlerClassName, handlerinterface ? new String[]{handlerClassName, sncyHandlerName} : new String[]{sncyHandlerName});
|
||||
|
||||
{ //handler 属性
|
||||
fv = cw.visitField(ACC_PRIVATE, "sncphandler", sncyHandlerDesc, null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{//构造方法
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "(" + sncyHandlerDesc + ")V", null, null));
|
||||
//mv.setDebug(true);
|
||||
{
|
||||
av0 = mv.visitAnnotation("Ljava/beans/ConstructorProperties;", true);
|
||||
{
|
||||
AnnotationVisitor av1 = av0.visitArray("value");
|
||||
av1.visit(null, "sncphandler");
|
||||
av1.visitEnd();
|
||||
}
|
||||
av0.visitEnd();
|
||||
}
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, handlerinterface ? "java/lang/Object" : handlerClassName, "<init>", "()V", false);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitFieldInsn(PUTFIELD, newDynName, "sncphandler", sncyHandlerDesc);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(2, 2);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
for (java.lang.reflect.Method method : handlerClass.getMethods()) { //
|
||||
if ("completed".equals(method.getName()) && method.getParameterCount() == 2) {
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "completed", Type.getMethodDescriptor(method), null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "sncphandler", sncyHandlerDesc);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, sncyHandlerName, "completed", "(Ljava/lang/Object;Ljava/lang/Object;)V", true);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(3, 3);
|
||||
mv.visitEnd();
|
||||
} else if ("failed".equals(method.getName()) && method.getParameterCount() == 2) {
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "failed", Type.getMethodDescriptor(method), null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "sncphandler", sncyHandlerDesc);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, sncyHandlerName, "failed", "(Ljava/lang/Throwable;Ljava/lang/Object;)V", true);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(3, 3);
|
||||
mv.visitEnd();
|
||||
} else if (handlerinterface || java.lang.reflect.Modifier.isAbstract(method.getModifiers())) {
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, method.getName(), Type.getMethodDescriptor(method), null, null));
|
||||
Class returnType = method.getReturnType();
|
||||
if (returnType == void.class) {
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(0, 1);
|
||||
} else if (returnType.isPrimitive()) {
|
||||
mv.visitInsn(ICONST_0);
|
||||
if (returnType == long.class) {
|
||||
mv.visitInsn(LRETURN);
|
||||
mv.visitMaxs(2, 1);
|
||||
} else if (returnType == float.class) {
|
||||
mv.visitInsn(FRETURN);
|
||||
mv.visitMaxs(2, 1);
|
||||
} else if (returnType == double.class) {
|
||||
mv.visitInsn(DRETURN);
|
||||
mv.visitMaxs(2, 1);
|
||||
} else {
|
||||
mv.visitInsn(IRETURN);
|
||||
mv.visitMaxs(1, 1);
|
||||
}
|
||||
} else {
|
||||
mv.visitInsn(ACONST_NULL);
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(1, 1);
|
||||
}
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
{ // sncp_getParams
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "sncp_getParams", "()[Ljava/lang/Object;", null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "sncphandler", sncyHandlerDesc);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, sncyHandlerName, "sncp_getParams", "()[Ljava/lang/Object;", true);
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(1, 1);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{ // sncp_setParams
|
||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "sncp_setParams", "([Ljava/lang/Object;)V", null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "sncphandler", sncyHandlerDesc);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, sncyHandlerName, "sncp_setParams", "([Ljava/lang/Object;)V", true);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(2, 2);
|
||||
mv.visitEnd();
|
||||
}
|
||||
cw.visitEnd();
|
||||
byte[] bytes = cw.toByteArray();
|
||||
Class<SncpAsyncHandler> newHandlerClazz = (Class<SncpAsyncHandler>) new ClassLoader(handlerClass.getClassLoader()) {
|
||||
public final Class<?> loadClass(String name, byte[] b) {
|
||||
return defineClass(name, b, 0, b.length);
|
||||
}
|
||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
||||
return Creator.create(newHandlerClazz);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class DefaultSncpAsyncHandler<V, A> implements SncpAsyncHandler<V, A> {
|
||||
|
||||
@@ -41,6 +41,8 @@ public final class SncpClient {
|
||||
|
||||
protected final Type[] paramTypes;
|
||||
|
||||
protected final Class[] paramClass;
|
||||
|
||||
protected final Attribute[] paramAttrs; // 为null表示无RpcCall处理,index=0固定为null, 其他为参数标记的RpcCall回调方法
|
||||
|
||||
protected final int handlerFuncParamIndex;
|
||||
@@ -60,6 +62,7 @@ public final class SncpClient {
|
||||
}
|
||||
this.resultTypes = rt == void.class ? null : rt;
|
||||
this.paramTypes = method.getGenericParameterTypes();
|
||||
this.paramClass = method.getParameterTypes();
|
||||
this.method = method;
|
||||
Annotation[][] anns = method.getParameterAnnotations();
|
||||
int targetAddrIndex = -1;
|
||||
@@ -328,11 +331,12 @@ public final class SncpClient {
|
||||
|
||||
private SncpFuture<byte[]> remoteSncp0(final AsyncHandler handler, final BsonConvert bsonConvert, final Transport transport, final SocketAddress addr0, final SncpAction action, final Object... params) {
|
||||
Type[] myparamtypes = action.paramTypes;
|
||||
Class[] myparamclass = action.paramClass;
|
||||
if (action.addressSourceParamIndex >= 0) params[action.addressSourceParamIndex] = this.clientAddress;
|
||||
final BsonWriter writer = bsonConvert.pollBsonWriter(transport.getBufferSupplier()); // 将head写入
|
||||
writer.writeTo(DEFAULT_HEADER);
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
bsonConvert.convertTo(writer, myparamtypes[i], params[i]);
|
||||
bsonConvert.convertTo(writer, AsyncHandler.class.isAssignableFrom(myparamclass[i]) ? AsyncHandler.class : myparamtypes[i], params[i]);
|
||||
}
|
||||
final int reqBodyLength = writer.count() - HEADER_SIZE; //body总长度
|
||||
final long seqid = System.nanoTime();
|
||||
|
||||
@@ -19,6 +19,7 @@ import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
import jdk.internal.org.objectweb.asm.Type;
|
||||
import org.redkale.convert.bson.*;
|
||||
import org.redkale.net.sncp.SncpAsyncHandler.DefaultSncpAsyncHandler;
|
||||
import org.redkale.service.*;
|
||||
import org.redkale.util.*;
|
||||
import org.redkale.service.RpcCall;
|
||||
@@ -123,7 +124,16 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
SncpAsyncHandler handler = null;
|
||||
try {
|
||||
if (action.handlerFuncParamIndex >= 0) {
|
||||
handler = SncpAsyncHandler.Factory.create(action.handlerFuncParamClass, action, in, out, request, response);
|
||||
if (action.handlerFuncParamClass == AsyncHandler.class) {
|
||||
handler = new DefaultSncpAsyncHandler(action, in, out, request, response);
|
||||
} else {
|
||||
Creator<SncpAsyncHandler> creator = action.handlerCreator;
|
||||
if (creator == null) {
|
||||
creator = SncpAsyncHandler.Factory.createCreator(action.handlerFuncParamClass);
|
||||
action.handlerCreator = creator;
|
||||
}
|
||||
handler = creator.create(new DefaultSncpAsyncHandler(action, in, out, request, response));
|
||||
}
|
||||
}
|
||||
in.setBytes(request.getBody());
|
||||
action.action(in, out, handler);
|
||||
@@ -143,6 +153,8 @@ public final class SncpDynServlet extends SncpServlet {
|
||||
|
||||
public Method method;
|
||||
|
||||
public Creator<SncpAsyncHandler> handlerCreator;
|
||||
|
||||
@Resource
|
||||
protected BsonConvert convert;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.redkale.util.*;
|
||||
* <blockquote><pre>
|
||||
* 异步方法:
|
||||
* Service编写异步方法:
|
||||
* 1、异步方法有且仅有一个类型为AsyncHandler的参数。
|
||||
* 1、异步方法有且仅有一个类型为AsyncHandler的参数。若参数类型为AsyncHandler子类,必须保证其子类可被继承且completed、failed可被重载且包含空参数的构造函数。
|
||||
* 2、异步方法返回类型必须是void。
|
||||
* 例如:
|
||||
* public void insertRecord(AsyncHandler<Integer, Record> handler, String name, @RpcAttachment Record record);
|
||||
|
||||
@@ -85,6 +85,10 @@ public class ABMainService implements Service {
|
||||
url = "http://127.0.0.1:" + abport + "/pipes/abmain/asyncabtime/张先生";
|
||||
System.out.println(Utility.postHttpContent(url));
|
||||
|
||||
//异步方法
|
||||
url = "http://127.0.0.1:" + abport + "/pipes/abmain/asyncabtime2/张先生";
|
||||
System.out.println(Utility.postHttpContent(url));
|
||||
|
||||
server.shutdown();
|
||||
}
|
||||
|
||||
@@ -120,6 +124,10 @@ public class ABMainService implements Service {
|
||||
url = "http://127.0.0.1:" + abport + "/pipes/abmain/asyncabtime/张先生";
|
||||
System.out.println(Utility.postHttpContent(url));
|
||||
|
||||
//异步方法
|
||||
url = "http://127.0.0.1:" + abport + "/pipes/abmain/asyncabtime2/张先生";
|
||||
System.out.println(Utility.postHttpContent(url));
|
||||
|
||||
server.shutdown();
|
||||
//远程模式
|
||||
remotemain(args);
|
||||
@@ -162,4 +170,25 @@ public class ABMainService implements Service {
|
||||
if (handler != null) handler.failed(t, a);
|
||||
}), name);
|
||||
}
|
||||
|
||||
@RestMapping(name = "asyncabtime2")
|
||||
public void abCurrentTime(final MyAsyncHandler<String, Void> handler, @RestParam(name = "#") final String name) {
|
||||
bcService.bcCurrentTime(new MyAsyncHandler<String, Void>() {
|
||||
@Override
|
||||
public int id() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completed(String v, Void a) {
|
||||
System.out.println("执行了 ABMainService.abCurrentTime----异步方法2");
|
||||
String rs = "异步abCurrentTime: " + v;
|
||||
if (handler != null) handler.completed(rs, a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable exc, Void attachment) {
|
||||
}
|
||||
}, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,4 +33,14 @@ public class BCService implements Service {
|
||||
if (handler != null) handler.failed(t, a);
|
||||
}), name);
|
||||
}
|
||||
|
||||
public void bcCurrentTime(final MyAsyncHandler<String, Void> handler, final String name) {
|
||||
cService.ccCurrentTime(AsyncHandler.create((v, a) -> {
|
||||
System.out.println("执行了 BCService.bcCurrentTime----异步方法2");
|
||||
String rs = "异步bcCurrentTime: " + (v == null ? null : v.getResult());
|
||||
if (handler != null) handler.completed(rs, null);
|
||||
}, (t, a) -> {
|
||||
if (handler != null) handler.failed(t, a);
|
||||
}), name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,4 +25,10 @@ public class CService implements Service {
|
||||
System.out.println("执行了 CService.ccCurrentTime----异步方法");
|
||||
if (handler != null) handler.completed(new RetResult(rs), null);
|
||||
}
|
||||
|
||||
public void mcCurrentTime(final MyAsyncHandler<RetResult<String>, Void> handler, final String name) {
|
||||
String rs = "异步mcCurrentTime: " + name + ": " + Utility.formatTime(System.currentTimeMillis());
|
||||
System.out.println("执行了 CService.mcCurrentTime----异步方法2");
|
||||
if (handler != null) handler.completed(new RetResult(rs), null);
|
||||
}
|
||||
}
|
||||
|
||||
20
test/org/redkale/test/service/MyAsyncHandler.java
Normal file
20
test/org/redkale/test/service/MyAsyncHandler.java
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.test.service;
|
||||
|
||||
import org.redkale.util.AsyncHandler;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <V> V
|
||||
* @param <A> A
|
||||
*/
|
||||
public abstract class MyAsyncHandler<V, A> implements AsyncHandler<V, A> {
|
||||
|
||||
public abstract int id();
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user