This commit is contained in:
33
src/org/redkale/net/sncp/SncpAsyncHandler.java
Normal file
33
src/org/redkale/net/sncp/SncpAsyncHandler.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.net.sncp;
|
||||||
|
|
||||||
|
import org.redkale.util.AsyncHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步回调函数
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @param <V> 结果对象的泛型
|
||||||
|
* @param <A> 附件对象的泛型
|
||||||
|
*/
|
||||||
|
public abstract class SncpAsyncHandler<V, A> implements AsyncHandler<V, A> {
|
||||||
|
|
||||||
|
protected Object[] params;
|
||||||
|
|
||||||
|
public Object[] getParams() {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParams(Object... params) {
|
||||||
|
this.params = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -296,7 +296,7 @@ public final class SncpClient {
|
|||||||
final Attribute attr = action.paramAttrs[i];
|
final Attribute attr = action.paramAttrs[i];
|
||||||
attr.set(params[i - 1], bsonConvert.convertFrom(attr.type(), reader));
|
attr.set(params[i - 1], bsonConvert.convertFrom(attr.type(), reader));
|
||||||
}
|
}
|
||||||
return bsonConvert.convertFrom(action.resultTypes, reader);
|
return bsonConvert.convertFrom(action.handlerFuncParamIndex >= 0 ? Object.class : action.resultTypes, reader);
|
||||||
} 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);
|
||||||
@@ -438,7 +438,7 @@ public final class SncpClient {
|
|||||||
final Attribute attr = action.paramAttrs[i];
|
final Attribute attr = action.paramAttrs[i];
|
||||||
attr.set(params[i - 1], bsonConvert.convertFrom(attr.type(), reader));
|
attr.set(params[i - 1], bsonConvert.convertFrom(attr.type(), reader));
|
||||||
}
|
}
|
||||||
Object rs = bsonConvert.convertFrom(action.resultTypes, reader);
|
Object rs = bsonConvert.convertFrom(action.handlerFuncParamIndex >= 0 ? Object.class : action.resultTypes, reader);
|
||||||
handler.completed(rs, handlerAttach);
|
handler.completed(rs, handlerAttach);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
handler.failed(e, handlerAttach);
|
handler.failed(e, handlerAttach);
|
||||||
|
|||||||
@@ -120,32 +120,39 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
BsonWriter out = action.convert.pollBsonWriter(bufferSupplier);
|
BsonWriter out = action.convert.pollBsonWriter(bufferSupplier);
|
||||||
out.writeTo(DEFAULT_HEADER);
|
out.writeTo(DEFAULT_HEADER);
|
||||||
BsonReader in = action.convert.pollBsonReader();
|
BsonReader in = action.convert.pollBsonReader();
|
||||||
|
SncpAsyncHandler handler;
|
||||||
try {
|
try {
|
||||||
AsyncHandler handler = action.handlerFuncParamIndex >= 0 ? AsyncHandler.create((v, a) -> {
|
handler = action.handlerFuncParamIndex >= 0 ? new SncpAsyncHandler() {
|
||||||
try {
|
@Override
|
||||||
action.convert.convertTo(out, Object.class, v);
|
public void completed(Object result, Object attachment) {
|
||||||
response.finish(0, out);
|
try {
|
||||||
} catch (Exception e) {
|
action._callParameter(out, params);
|
||||||
response.getContext().getLogger().log(Level.INFO, "sncp execute error(" + request + ")", e);
|
action.convert.convertTo(out, Object.class, result);
|
||||||
response.finish(SncpResponse.RETCODE_THROWEXCEPTION, null);
|
response.finish(0, out);
|
||||||
} finally {
|
} catch (Exception e) {
|
||||||
action.convert.offerBsonReader(in);
|
failed(e, attachment);
|
||||||
action.convert.offerBsonWriter(out);
|
} finally {
|
||||||
|
action.convert.offerBsonReader(in);
|
||||||
|
action.convert.offerBsonWriter(out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, (t, a) -> {
|
|
||||||
response.getContext().getLogger().log(Level.INFO, "sncp execute error(" + request + ")", t);
|
|
||||||
response.finish(SncpResponse.RETCODE_THROWEXCEPTION, null);
|
|
||||||
}) : null;
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void failed(Throwable exc, Object attachment) {
|
||||||
|
response.getContext().getLogger().log(Level.INFO, "sncp execute error(" + request + ")", exc);
|
||||||
|
response.finish(SncpResponse.RETCODE_THROWEXCEPTION, null);
|
||||||
|
}
|
||||||
|
} : null;
|
||||||
in.setBytes(request.getBody());
|
in.setBytes(request.getBody());
|
||||||
action.action(in, out);
|
action.action(in, out, handler);
|
||||||
response.finish(0, out);
|
if (handler == null) {
|
||||||
|
response.finish(0, out);
|
||||||
|
action.convert.offerBsonReader(in);
|
||||||
|
action.convert.offerBsonWriter(out);
|
||||||
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
response.getContext().getLogger().log(Level.INFO, "sncp execute error(" + request + ")", t);
|
response.getContext().getLogger().log(Level.INFO, "sncp execute error(" + request + ")", t);
|
||||||
response.finish(SncpResponse.RETCODE_THROWEXCEPTION, null);
|
response.finish(SncpResponse.RETCODE_THROWEXCEPTION, null);
|
||||||
} finally {
|
|
||||||
action.convert.offerBsonReader(in);
|
|
||||||
action.convert.offerBsonWriter(out);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,7 +170,7 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
|
|
||||||
protected int handlerFuncParamIndex = -1; //handlerFuncParamIndex>=0表示存在AsyncHandler参数
|
protected int handlerFuncParamIndex = -1; //handlerFuncParamIndex>=0表示存在AsyncHandler参数
|
||||||
|
|
||||||
public abstract void action(final BsonReader in, final BsonWriter out) throws Throwable;
|
public abstract void action(final BsonReader in, final BsonWriter out, final SncpAsyncHandler handler) throws Throwable;
|
||||||
|
|
||||||
public final void _callParameter(final BsonWriter out, final Object... params) {
|
public final void _callParameter(final BsonWriter out, final Object... params) {
|
||||||
if (paramAttrs != null) {
|
if (paramAttrs != null) {
|
||||||
@@ -213,6 +220,8 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
final String supDynName = SncpServletAction.class.getName().replace('.', '/');
|
final String supDynName = SncpServletAction.class.getName().replace('.', '/');
|
||||||
final String serviceName = serviceClass.getName().replace('.', '/');
|
final String serviceName = serviceClass.getName().replace('.', '/');
|
||||||
final String convertName = BsonConvert.class.getName().replace('.', '/');
|
final String convertName = BsonConvert.class.getName().replace('.', '/');
|
||||||
|
final String handlerName = SncpAsyncHandler.class.getName().replace('.', '/');
|
||||||
|
final String asyncHandlerDesc = Type.getDescriptor(SncpAsyncHandler.class);
|
||||||
final String convertReaderDesc = Type.getDescriptor(BsonReader.class);
|
final String convertReaderDesc = Type.getDescriptor(BsonReader.class);
|
||||||
final String convertWriterDesc = Type.getDescriptor(BsonWriter.class);
|
final String convertWriterDesc = Type.getDescriptor(BsonWriter.class);
|
||||||
final String serviceDesc = Type.getDescriptor(serviceClass);
|
final String serviceDesc = Type.getDescriptor(serviceClass);
|
||||||
@@ -256,11 +265,11 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
}
|
}
|
||||||
int handlerFuncIndex = -1;
|
int handlerFuncIndex = -1;
|
||||||
{ // action方法
|
{ // action方法
|
||||||
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "action", "(" + convertReaderDesc + convertWriterDesc + ")V", null, new String[]{"java/lang/Throwable"}));
|
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "action", "(" + convertReaderDesc + convertWriterDesc + asyncHandlerDesc + ")V", null, new String[]{"java/lang/Throwable"}));
|
||||||
//mv.setDebug(true);
|
//mv.setDebug(true);
|
||||||
int iconst = ICONST_1;
|
int iconst = ICONST_1;
|
||||||
int intconst = 1;
|
int intconst = 1;
|
||||||
int store = 3; //action的参数个数+1
|
int store = 4; //action的参数个数+1
|
||||||
final Class[] paramClasses = method.getParameterTypes();
|
final Class[] paramClasses = method.getParameterTypes();
|
||||||
int[][] codes = new int[paramClasses.length][2];
|
int[][] codes = new int[paramClasses.length][2];
|
||||||
for (int i = 0; i < paramClasses.length; i++) { //参数
|
for (int i = 0; i < paramClasses.length; i++) { //参数
|
||||||
@@ -269,6 +278,19 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
throw new RuntimeException(method + " have more than one AsyncHandler type parameter");
|
throw new RuntimeException(method + " have more than one AsyncHandler type parameter");
|
||||||
}
|
}
|
||||||
handlerFuncIndex = i;
|
handlerFuncIndex = i;
|
||||||
|
mv.visitVarInsn(ALOAD, 3);
|
||||||
|
mv.visitVarInsn(ASTORE, store);
|
||||||
|
codes[i] = new int[]{ALOAD, store};
|
||||||
|
store++;
|
||||||
|
iconst++;
|
||||||
|
intconst++;
|
||||||
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
|
mv.visitFieldInsn(GETFIELD, newDynName, "convert", Type.getDescriptor(BsonConvert.class));
|
||||||
|
mv.visitLdcInsn(Type.getType(Type.getDescriptor(AsyncHandler.class)));
|
||||||
|
mv.visitVarInsn(ALOAD, 1);
|
||||||
|
mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
|
||||||
|
mv.visitInsn(POP);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
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));
|
||||||
@@ -321,6 +343,43 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
intconst++;
|
intconst++;
|
||||||
store++;
|
store++;
|
||||||
}
|
}
|
||||||
|
if (handlerFuncIndex >= 0) { //调用SncpAsyncHandler.setParams(Object... params)
|
||||||
|
mv.visitVarInsn(ALOAD, 3);
|
||||||
|
if (paramClasses.length > 5) {
|
||||||
|
mv.visitIntInsn(BIPUSH, paramClasses.length);
|
||||||
|
} else {
|
||||||
|
mv.visitInsn(paramClasses.length + ICONST_0);
|
||||||
|
}
|
||||||
|
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
|
||||||
|
int insn = 3; //action的参数个数
|
||||||
|
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, handlerName, "setParams", "([Ljava/lang/Object;)V", false);
|
||||||
|
}
|
||||||
{ //调用service
|
{ //调用service
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
mv.visitFieldInsn(GETFIELD, newDynName, "service", serviceDesc);
|
mv.visitFieldInsn(GETFIELD, newDynName, "service", serviceDesc);
|
||||||
@@ -343,7 +402,7 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
}
|
}
|
||||||
mv.visitVarInsn(ASTORE, store); //11
|
mv.visitVarInsn(ASTORE, store); //11
|
||||||
}
|
}
|
||||||
if (true) {
|
if (handlerFuncIndex < 0) {
|
||||||
//------------------------- _callParameter 方法 --------------------------------
|
//------------------------- _callParameter 方法 --------------------------------
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
mv.visitVarInsn(ALOAD, 2);
|
mv.visitVarInsn(ALOAD, 2);
|
||||||
@@ -353,7 +412,7 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
mv.visitIntInsn(BIPUSH, paramClasses.length);
|
mv.visitIntInsn(BIPUSH, paramClasses.length);
|
||||||
}
|
}
|
||||||
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
|
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
|
||||||
int insn = 2;
|
int insn = 3;//action的参数个数
|
||||||
for (int j = 0; j < paramClasses.length; j++) {
|
for (int j = 0; j < paramClasses.length; j++) {
|
||||||
final Class pt = paramClasses[j];
|
final Class pt = paramClasses[j];
|
||||||
mv.visitInsn(DUP);
|
mv.visitInsn(DUP);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class ABMainService implements Service {
|
|||||||
//------------------------ 初始化 BCService ------------------------------------
|
//------------------------ 初始化 BCService ------------------------------------
|
||||||
final Transport bctransport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, Utility.ofSet(new InetSocketAddress("127.0.0.1", 5577)));
|
final Transport bctransport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, Utility.ofSet(new InetSocketAddress("127.0.0.1", 5577)));
|
||||||
BCService bcservice = Sncp.createLocalService("", null, ResourceFactory.root(), BCService.class, new InetSocketAddress("127.0.0.1", 5588), bctransport, null);
|
BCService bcservice = Sncp.createLocalService("", null, ResourceFactory.root(), BCService.class, new InetSocketAddress("127.0.0.1", 5588), bctransport, null);
|
||||||
CService remoteCService = Sncp.createRemoteService("", null, CService.class, new InetSocketAddress("127.0.0.1", 5588), bctransport);
|
CService remoteCService = Sncp.createRemoteService("", null, CService.class, new InetSocketAddress("127.0.0.1", 5588), bctransport);
|
||||||
factory.inject(remoteCService);
|
factory.inject(remoteCService);
|
||||||
factory.register("", remoteCService);
|
factory.register("", remoteCService);
|
||||||
SncpServer bcserver = new SncpServer();
|
SncpServer bcserver = new SncpServer();
|
||||||
@@ -61,7 +61,7 @@ public class ABMainService implements Service {
|
|||||||
//------------------------ 初始化 ABMainService ------------------------------------
|
//------------------------ 初始化 ABMainService ------------------------------------
|
||||||
final Transport abtransport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, Utility.ofSet(new InetSocketAddress("127.0.0.1", 5588)));
|
final Transport abtransport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, Utility.ofSet(new InetSocketAddress("127.0.0.1", 5588)));
|
||||||
ABMainService service = Sncp.createLocalService("", null, ResourceFactory.root(), ABMainService.class, new InetSocketAddress("127.0.0.1", 5599), bctransport, null);
|
ABMainService service = Sncp.createLocalService("", null, ResourceFactory.root(), ABMainService.class, new InetSocketAddress("127.0.0.1", 5599), bctransport, null);
|
||||||
BCService remoteBCService = Sncp.createRemoteService("", null, BCService.class, new InetSocketAddress("127.0.0.1", 5599), abtransport);
|
BCService remoteBCService = Sncp.createRemoteService("", null, BCService.class, new InetSocketAddress("127.0.0.1", 5599), abtransport);
|
||||||
factory.inject(remoteBCService);
|
factory.inject(remoteBCService);
|
||||||
factory.register("", remoteBCService);
|
factory.register("", remoteBCService);
|
||||||
|
|
||||||
@@ -157,8 +157,9 @@ public class ABMainService implements Service {
|
|||||||
bcService.bcCurrentTime(AsyncHandler.create((v, a) -> {
|
bcService.bcCurrentTime(AsyncHandler.create((v, a) -> {
|
||||||
System.out.println("执行了 ABMainService.abCurrentTime----异步方法");
|
System.out.println("执行了 ABMainService.abCurrentTime----异步方法");
|
||||||
String rs = "异步abCurrentTime: " + v;
|
String rs = "异步abCurrentTime: " + v;
|
||||||
if (handler != null) handler.completed(rs, null);
|
if (handler != null) handler.completed(rs, a);
|
||||||
}, (t, a) -> {
|
}, (t, a) -> {
|
||||||
|
if (handler != null) handler.failed(t, a);
|
||||||
}), name);
|
}), name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,10 @@ public class BCService implements Service {
|
|||||||
public void bcCurrentTime(final AsyncHandler<String, Void> handler, final String name) {
|
public void bcCurrentTime(final AsyncHandler<String, Void> handler, final String name) {
|
||||||
cService.ccCurrentTime(AsyncHandler.create((v, a) -> {
|
cService.ccCurrentTime(AsyncHandler.create((v, a) -> {
|
||||||
System.out.println("执行了 BCService.bcCurrentTime----异步方法");
|
System.out.println("执行了 BCService.bcCurrentTime----异步方法");
|
||||||
String rs = "异步bcCurrentTime: " + v.getResult();
|
String rs = "异步bcCurrentTime: " + (v == null ? null : v.getResult());
|
||||||
if (handler != null) handler.completed(rs, null);
|
if (handler != null) handler.completed(rs, null);
|
||||||
}, (t, a) -> {
|
}, (t, a) -> {
|
||||||
|
if (handler != null) handler.failed(t, a);
|
||||||
}), name);
|
}), name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user