This commit is contained in:
Redkale
2017-03-22 10:31:14 +08:00
parent 0bd0df3245
commit 19a44ce8cf
5 changed files with 195 additions and 48 deletions

View File

@@ -130,6 +130,39 @@ public abstract class Sncp {
} }
} }
static void checkAsyncModifier(Class param, Method method) {
if (param == AsyncHandler.class) return;
if (Modifier.isFinal(param.getModifiers())) {
throw new RuntimeException("AsyncHandler Type Parameter on {" + method + "} cannot final modifier");
}
if (!Modifier.isPublic(param.getModifiers())) {
throw new RuntimeException("AsyncHandler Type Parameter on {" + method + "} must be public modifier");
}
if (param.isInterface()) return;
boolean constructorflag = false;
for (Constructor c : param.getDeclaredConstructors()) {
if (c.getParameterCount() == 0) {
int mod = c.getModifiers();
if (Modifier.isPublic(mod) || Modifier.isProtected(mod)) {
constructorflag = true;
break;
}
}
}
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");
} else if (m.getName().equals("failed") && Modifier.isFinal(m.getModifiers())) {
throw new RuntimeException(param + "'s failed method cannot final modifier");
} else if (m.getName().equals("sncp_getParams") && Modifier.isFinal(m.getModifiers())) {
throw new RuntimeException(param + "'s sncp_getParams method cannot final modifier");
} else if (m.getName().equals("sncp_setParams") && Modifier.isFinal(m.getModifiers())) {
throw new RuntimeException(param + "'s sncp_setParams method cannot final modifier");
}
}
}
/** /**
* <blockquote><pre> * <blockquote><pre>
* public class TestService implements Service{ * public class TestService implements Service{
@@ -139,16 +172,16 @@ public abstract class Sncp {
* } * }
* *
* &#64;RpcMultiRun(selfrun = false) * &#64;RpcMultiRun(selfrun = false)
public void createSomeThing(TestBean bean){ * public void createSomeThing(TestBean bean){
//do something * //do something
} * }
*
&#64;RpcMultiRun * &#64;RpcMultiRun
public String updateSomeThing(String id){ * public String updateSomeThing(String id){
return "hello" + id; * return "hello" + id;
} * }
} * }
</pre></blockquote> * </pre></blockquote>
* *
* <blockquote><pre> * <blockquote><pre>
* &#64;Resource(name = "") * &#64;Resource(name = "")
@@ -362,7 +395,13 @@ public abstract class Sncp {
mv.visitInsn(mrun.samerun() ? ICONST_1 : ICONST_0); mv.visitInsn(mrun.samerun() ? ICONST_1 : ICONST_0);
mv.visitInsn(mrun.diffrun() ? ICONST_1 : ICONST_0); mv.visitInsn(mrun.diffrun() ? ICONST_1 : ICONST_0);
int varindex = 0; int varindex = 0;
boolean handlerFuncFlag = false;
for (Class pt : paramtypes) { for (Class pt : paramtypes) {
if (AsyncHandler.class.isAssignableFrom(pt)) {
if (handlerFuncFlag) throw new RuntimeException(method + " have more than one AsyncHandler type parameter");
checkAsyncModifier(pt, method);
handlerFuncFlag = true;
}
if (pt.isPrimitive()) { if (pt.isPrimitive()) {
if (pt == long.class) { if (pt == long.class) {
mv.visitVarInsn(LLOAD, ++varindex); mv.visitVarInsn(LLOAD, ++varindex);
@@ -403,8 +442,15 @@ public abstract class Sncp {
//mv.setDebug(true); //mv.setDebug(true);
{ //给参数加上 Annotation { //给参数加上 Annotation
final Annotation[][] anns = method.getParameterAnnotations(); final Annotation[][] anns = method.getParameterAnnotations();
boolean handlerAttachFlag = false;
for (int k = 0; k < anns.length; k++) { for (int k = 0; k < anns.length; k++) {
for (Annotation ann : anns[k]) { for (Annotation ann : anns[k]) {
if (ann.annotationType() == RpcAttachment.class) {
if (handlerAttachFlag) {
throw new RuntimeException(method + " have more than one @RpcAttachment parameter");
}
handlerAttachFlag = true;
}
if (ann instanceof SncpDyn || ann instanceof RpcMultiRun) continue; //必须过滤掉 RpcMultiRun、SncpDyn否则生成远程模式Service时会出错 if (ann instanceof SncpDyn || ann instanceof RpcMultiRun) continue; //必须过滤掉 RpcMultiRun、SncpDyn否则生成远程模式Service时会出错
visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann); visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
} }

View File

@@ -5,10 +5,15 @@
*/ */
package org.redkale.net.sncp; package org.redkale.net.sncp;
import java.util.logging.Level;
import org.redkale.convert.bson.*;
import org.redkale.net.sncp.SncpDynServlet.SncpServletAction;
import org.redkale.util.AsyncHandler; import org.redkale.util.AsyncHandler;
/** /**
* 异步回调函数 * 异步回调函数 <br>
*
* public class _DyncSncpAsyncHandler extends XXXAsyncHandler implements SncpAsyncHandler
* *
* *
* <p> * <p>
@@ -18,17 +23,123 @@ import org.redkale.util.AsyncHandler;
* @param <V> 结果对象的泛型 * @param <V> 结果对象的泛型
* @param <A> 附件对象的泛型 * @param <A> 附件对象的泛型
*/ */
public abstract class SncpAsyncHandler<V, A> implements AsyncHandler<V, A> { public interface SncpAsyncHandler<V, A> extends AsyncHandler<V, A> {
//为了在回调函数中调用_callParameter方法 public Object[] sncp_getParams();
protected Object[] params;
public Object[] getParams() { public void sncp_setParams(Object... params);
return params;
static class Factory {
/**
* <blockquote><pre>
* 若参数类型为AsyncHandler子类必须保证其子类可被继承且completed、failed可被重载且包含空参数的构造函数。
* 考虑点:
* 1、AsyncHandler子类是接口且还有其他多个方法
* 2、AsyncHandler子类是类 需要继承,且必须有空参数构造函数
* 3、AsyncHandler子类无论是接口还是类都可能存在其他泛型
*
* public class _DyncSncpAsyncHandler_xxx extends XXXAsyncHandler implements SncpAsyncHandler {
*
* public SncpAsyncHandler handler;
*
* protected Object[] params;
*
* &#64;Override
* public void completed(Object result, Object attachment) {
* handler.completed(result, attachment);
* }
*
* &#64;Override
* public void failed(Throwable exc, Object attachment) {
* handler.failed(exc, attachment);
* }
*
* &#64;Override
* public Object[] sncp_getParams() {
* return params;
* }
*
* &#64;Override
* public void sncp_setParams(Object... params) {
* this.params = params;
* handler.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
*/
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 void setParams(Object... params) { static class DefaultSncpAsyncHandler<V, A> implements SncpAsyncHandler<V, A> {
this.params = params;
}
//为了在回调函数中调用_callParameter方法
protected Object[] params;
protected SncpServletAction action;
protected BsonReader in;
protected BsonWriter out;
protected SncpRequest request;
protected SncpResponse response;
public DefaultSncpAsyncHandler(SncpServletAction action, BsonReader in, BsonWriter out, SncpRequest request, SncpResponse response) {
this.action = action;
this.in = in;
this.out = out;
this.request = request;
this.response = response;
}
@Override
public void completed(Object result, Object attachment) {
try {
action._callParameter(out, sncp_getParams());
action.convert.convertTo(out, Object.class, result);
response.finish(0, out);
} catch (Exception e) {
failed(e, attachment);
} finally {
action.convert.offerBsonReader(in);
action.convert.offerBsonWriter(out);
}
}
@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);
}
@Override
public Object[] sncp_getParams() {
return params;
}
@Override
public void sncp_setParams(Object... params) {
this.params = params;
}
}
} }

View File

@@ -75,6 +75,7 @@ public final class SncpClient {
if (handlerFuncIndex >= 0) { if (handlerFuncIndex >= 0) {
throw new RuntimeException(method + " have more than one AsyncHandler type parameter"); throw new RuntimeException(method + " have more than one AsyncHandler type parameter");
} }
Sncp.checkAsyncModifier(params[i], method);
handlerFuncIndex = i; handlerFuncIndex = i;
break; break;
} }

View File

@@ -120,29 +120,11 @@ 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; SncpAsyncHandler handler = null;
try { try {
handler = action.handlerFuncParamIndex >= 0 ? new SncpAsyncHandler() { if (action.handlerFuncParamIndex >= 0) {
@Override handler = SncpAsyncHandler.Factory.create(action.handlerFuncParamClass, action, in, out, request, response);
public void completed(Object result, Object attachment) { }
try {
action._callParameter(out, params);
action.convert.convertTo(out, Object.class, result);
response.finish(0, out);
} catch (Exception e) {
failed(e, attachment);
} finally {
action.convert.offerBsonReader(in);
action.convert.offerBsonWriter(out);
}
}
@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, handler); action.action(in, out, handler);
if (handler == null) { if (handler == null) {
@@ -170,6 +152,8 @@ public final class SncpDynServlet extends SncpServlet {
protected int handlerFuncParamIndex = -1; //handlerFuncParamIndex>=0表示存在AsyncHandler参数 protected int handlerFuncParamIndex = -1; //handlerFuncParamIndex>=0表示存在AsyncHandler参数
protected Class handlerFuncParamClass; //AsyncHandler参数的类型
public abstract void action(final BsonReader in, final BsonWriter out, final SncpAsyncHandler handler) 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) {
@@ -226,9 +210,9 @@ public final class SncpDynServlet extends SncpServlet {
* TestBean arg1 = convert.convertFrom(paramTypes[2], in); * TestBean arg1 = convert.convertFrom(paramTypes[2], in);
* String arg2 = convert.convertFrom(paramTypes[3], in); * String arg2 = convert.convertFrom(paramTypes[3], in);
* int arg3 = convert.convertFrom(paramTypes[4], in); * int arg3 = convert.convertFrom(paramTypes[4], in);
* handler.setParams(arg0, arg1, arg2, arg3); * handler.sncp_setParams(arg0, arg1, arg2, arg3);
* service.insert(arg0, arg1, arg2, arg3); * service.insert(arg0, arg1, arg2, arg3);
* } * }
* } * }
* *
* class DynActionTestService_update extends SncpServletAction { * class DynActionTestService_update extends SncpServletAction {
@@ -244,11 +228,11 @@ public final class SncpDynServlet extends SncpServlet {
* TestBean arg1 = convert.convertFrom(paramTypes[4], in); * TestBean arg1 = convert.convertFrom(paramTypes[4], in);
* String arg2 = convert.convertFrom(paramTypes[5], in); * String arg2 = convert.convertFrom(paramTypes[5], in);
* int arg3 = convert.convertFrom(paramTypes[6], in); * int arg3 = convert.convertFrom(paramTypes[6], in);
* handler.setParams(a1, a2, a3, arg1, arg2, arg3); * handler.sncp_setParams(a1, a2, a3, arg1, arg2, arg3);
* service.update(a1, a2, a3, arg1, arg2, arg3); * service.update(a1, a2, a3, arg1, arg2, arg3);
* } * }
* } * }
* *
* </pre></blockquote> * </pre></blockquote>
* *
* @param service Service * @param service Service
@@ -307,6 +291,7 @@ public final class SncpDynServlet extends SncpServlet {
throw new RuntimeException(ex); //不可能会发生 throw new RuntimeException(ex); //不可能会发生
} }
int handlerFuncIndex = -1; int handlerFuncIndex = -1;
Class handlerFuncClass = null;
{ // action方法 { // action方法
mv = new AsmMethodVisitor(cw.visitMethod(ACC_PUBLIC, "action", "(" + convertReaderDesc + convertWriterDesc + asyncHandlerDesc + ")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);
@@ -320,8 +305,11 @@ public final class SncpDynServlet extends SncpServlet {
if (handlerFuncIndex >= 0) { if (handlerFuncIndex >= 0) {
throw new RuntimeException(method + " have more than one AsyncHandler type parameter"); throw new RuntimeException(method + " have more than one AsyncHandler type parameter");
} }
Sncp.checkAsyncModifier(paramClasses[i], method);
handlerFuncIndex = i; handlerFuncIndex = i;
handlerFuncClass = paramClasses[i];
mv.visitVarInsn(ALOAD, 3); mv.visitVarInsn(ALOAD, 3);
mv.visitTypeInsn(CHECKCAST, paramClasses[i].getName().replace('.', '/'));
mv.visitVarInsn(ASTORE, store); mv.visitVarInsn(ASTORE, store);
codes[i] = new int[]{ALOAD, store}; codes[i] = new int[]{ALOAD, store};
store++; store++;
@@ -421,7 +409,7 @@ public final class SncpDynServlet extends SncpServlet {
} }
mv.visitInsn(AASTORE); mv.visitInsn(AASTORE);
} }
mv.visitMethodInsn(INVOKEVIRTUAL, handlerName, "setParams", "([Ljava/lang/Object;)V", false); mv.visitMethodInsn(INVOKEINTERFACE, handlerName, "sncp_setParams", "([Ljava/lang/Object;)V", true);
} }
{ //调用service { //调用service
mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0);
@@ -527,6 +515,7 @@ public final class SncpDynServlet extends SncpServlet {
System.arraycopy(ptypes, 0, types, 1, ptypes.length); System.arraycopy(ptypes, 0, types, 1, ptypes.length);
instance.paramTypes = types; instance.paramTypes = types;
instance.handlerFuncParamIndex = handlerFuncIndex; instance.handlerFuncParamIndex = handlerFuncIndex;
instance.handlerFuncParamClass = handlerFuncClass;
org.redkale.util.Attribute[] atts = new org.redkale.util.Attribute[ptypes.length + 1]; org.redkale.util.Attribute[] atts = new org.redkale.util.Attribute[ptypes.length + 1];
Annotation[][] anns = method.getParameterAnnotations(); Annotation[][] anns = method.getParameterAnnotations();

View File

@@ -24,7 +24,7 @@ import org.redkale.util.*;
* Service编写异步方法 * Service编写异步方法
* 1、异步方法有且仅有一个类型为AsyncHandler的参数。 * 1、异步方法有且仅有一个类型为AsyncHandler的参数。
* 2、异步方法返回类型必须是void。 * 2、异步方法返回类型必须是void。
* 例如: * 例如:
* public void insertRecord(AsyncHandler&#60;Integer, Record&#62; handler, String name, &#64;RpcAttachment Record record); * public void insertRecord(AsyncHandler&#60;Integer, Record&#62; handler, String name, &#64;RpcAttachment Record record);
* *
* </pre></blockquote> * </pre></blockquote>