From 83680c46e8e5ccb1261921c48ac7ff774043a3a7 Mon Sep 17 00:00:00 2001 From: Redkale <22250530@qq.com> Date: Fri, 12 May 2017 19:56:09 +0800 Subject: [PATCH] --- .../redkale/net/http/DefaultRestServlet.java | 2 + src/org/redkale/net/http/HttpCacheable.java | 8 +- src/org/redkale/net/http/HttpResponse.java | 50 +++--- src/org/redkale/net/http/Rest.java | 23 +-- src/org/redkale/net/http/RestBody.java | 4 +- src/org/redkale/net/http/RestHttpServlet.java | 164 ------------------ 6 files changed, 41 insertions(+), 210 deletions(-) diff --git a/src/org/redkale/net/http/DefaultRestServlet.java b/src/org/redkale/net/http/DefaultRestServlet.java index 244e572fa..0e4f73ccb 100644 --- a/src/org/redkale/net/http/DefaultRestServlet.java +++ b/src/org/redkale/net/http/DefaultRestServlet.java @@ -12,8 +12,10 @@ import java.io.IOException; *

* 详情见: https://redkale.org * + * @deprecated * @author zhangjx */ +@Deprecated public class DefaultRestServlet extends RestHttpServlet { @Override diff --git a/src/org/redkale/net/http/HttpCacheable.java b/src/org/redkale/net/http/HttpCacheable.java index 5b36e98fb..f795be9aa 100644 --- a/src/org/redkale/net/http/HttpCacheable.java +++ b/src/org/redkale/net/http/HttpCacheable.java @@ -10,9 +10,11 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** - * 配合 HttpServlet 使用。 - * 当标记为 @HttpCacheable 的方法使用response.finish的参数将被缓存一段时间(默认值 seconds=15秒)。 - * 通常情况下 @HttpCacheable 需要与 @AuthIgnore 一起使用,没有标记@AuthIgnore的方法一般输出的结果与当前用户信息有关。 + * 配合 HttpServlet 使用。
+ * 当标记为 @HttpCacheable 的方法使用response.finish的参数将被缓存一段时间(默认值 seconds=15秒)。
+ * 通常情况下 @HttpCacheable 需要与 @AuthIgnore 一起使用,没有标记@AuthIgnore的方法一般输出的结果与当前用户信息有关。
+ *

+ * 注意: 不能标记在HttpServlet类中已有的方法(如: execute/preExecute/authenticate) * *

* 详情见: https://redkale.org diff --git a/src/org/redkale/net/http/HttpResponse.java b/src/org/redkale/net/http/HttpResponse.java index 01ba51632..036edf00d 100644 --- a/src/org/redkale/net/http/HttpResponse.java +++ b/src/org/redkale/net/http/HttpResponse.java @@ -359,6 +359,32 @@ public class HttpResponse extends Response { }); } + /** + * 将CompletableFuture的结果对象以JSON格式输出 + * + * @param convert 指定的JsonConvert + * @param type 指定的类型 + * @param future 输出对象的句柄 + */ + public void finishJson(final JsonConvert convert, final Type type, final CompletableFuture future) { + future.whenComplete((v, e) -> { + if (e != null) { + context.getLogger().log(Level.WARNING, "Servlet occur, forece to close channel. request = " + request, e); + finish(500, null); + return; + } + if (v instanceof CharSequence) { + finish(v.toString()); + } else if (v instanceof HttpResult) { + finishJson(convert, (HttpResult) v); + } else if (v instanceof org.redkale.service.RetResult) { + finishJson(convert, (org.redkale.service.RetResult) v); + } else { + finishJson(convert, type, v); + } + }); + } + /** * 将HttpResult的结果对象以JSON格式输出 * @@ -397,30 +423,6 @@ public class HttpResponse extends Response { } } - /** - * 将CompletableFuture的结果对象以JSON格式输出 - * - * @param convert 指定的JsonConvert - * @param type 指定的类型 - * @param future 输出对象的句柄 - */ - public void finishJson(final JsonConvert convert, final Type type, final CompletableFuture future) { - future.whenComplete((v, e) -> { - if (e != null) { - context.getLogger().log(Level.WARNING, "Servlet occur, forece to close channel. request = " + request, e); - finish(500, null); - return; - } - if (v instanceof CharSequence) { - finish(v.toString()); - } else if (v instanceof org.redkale.service.RetResult) { - finishJson(convert, (org.redkale.service.RetResult) v); - } else { - finishJson(convert, type, v); - } - }); - } - /** * 将指定字符串以响应结果输出 * diff --git a/src/org/redkale/net/http/Rest.java b/src/org/redkale/net/http/Rest.java index 389d646f6..a6a240c3b 100644 --- a/src/org/redkale/net/http/Rest.java +++ b/src/org/redkale/net/http/Rest.java @@ -111,8 +111,6 @@ public final class Rest { if (!java.lang.reflect.Modifier.isPublic(mod)) return null; if (java.lang.reflect.Modifier.isAbstract(mod)) return null; - final java.lang.reflect.Type futureRestOutputType = new TypeToken>() { - }.getType(); final String serviceDesc = Type.getDescriptor(serviceType); final String webServletDesc = Type.getDescriptor(WebServlet.class); final String reqDesc = Type.getDescriptor(HttpRequest.class); @@ -120,7 +118,7 @@ public final class Rest { final String retDesc = Type.getDescriptor(RetResult.class); final String futureDesc = Type.getDescriptor(CompletableFuture.class); final String flipperDesc = Type.getDescriptor(Flipper.class); - final String restoutputDesc = Type.getDescriptor(RestOutput.class); + final String httprsDesc = Type.getDescriptor(HttpResult.class); final String attrDesc = Type.getDescriptor(org.redkale.util.Attribute.class); final String authDesc = Type.getDescriptor(AuthIgnore.class); final String cacheDesc = Type.getDescriptor(HttpCacheable.class); @@ -464,10 +462,10 @@ public final class Rest { mv.visitVarInsn(ASTORE, maxLocals); varInsns.add(new int[]{ALOAD, maxLocals}); } else { - mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 3); 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.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "createAsyncHandler", "(Ljava/lang/Class;)Lorg/redkale/util/AsyncHandler;", false); mv.visitTypeInsn(CHECKCAST, ptype.getName().replace('.', '/')); mv.visitVarInsn(ASTORE, maxLocals); varInsns.add(new int[]{ALOAD, maxLocals}); @@ -945,12 +943,11 @@ public final class Rest { mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finishJson", "(" + retDesc + ")V", false); mv.visitInsn(RETURN); maxLocals++; - } else if (RestOutput.class.isAssignableFrom(returnType)) { + } else if (HttpResult.class.isAssignableFrom(returnType)) { mv.visitVarInsn(ASTORE, maxLocals); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 2); + mv.visitVarInsn(ALOAD, 2); //response mv.visitVarInsn(ALOAD, maxLocals); - mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "finishJson", "(" + respDesc + restoutputDesc + ")V", false); + mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finishJson", "(" + httprsDesc + ")V", false); mv.visitInsn(RETURN); maxLocals++; } else if (Number.class.isAssignableFrom(returnType) || CharSequence.class.isAssignableFrom(returnType)) { //returnType == String.class 必须放在前面 @@ -961,14 +958,6 @@ public final class Rest { mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false); mv.visitInsn(RETURN); maxLocals++; - } else if (futureRestOutputType == returnGenericType) { - mv.visitVarInsn(ASTORE, maxLocals); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 2); - mv.visitVarInsn(ALOAD, maxLocals); - mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "finishJson", "(" + respDesc + futureDesc + ")V", false); - mv.visitInsn(RETURN); - maxLocals++; } else if (CompletableFuture.class.isAssignableFrom(returnType)) { mv.visitVarInsn(ASTORE, maxLocals); mv.visitVarInsn(ALOAD, 2);//response diff --git a/src/org/redkale/net/http/RestBody.java b/src/org/redkale/net/http/RestBody.java index 44e22c1b5..0888cfaab 100644 --- a/src/org/redkale/net/http/RestBody.java +++ b/src/org/redkale/net/http/RestBody.java @@ -10,9 +10,9 @@ import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** - * 只能注解于Service类的方法的String/byte[]参数或参数内的String/byte[]字段 + * 只能注解于Service类的方法的String/byte[]/JavaBean参数或参数内的String/byte[]/JavaBean字段 *

- * 用于获取HTTP请求端的请求内容UTF-8编码字符串或者 byte[] + * 用于获取HTTP请求端的请求内容UTF-8编码字符串、byte[]、JavaBean * *

* 详情见: https://redkale.org diff --git a/src/org/redkale/net/http/RestHttpServlet.java b/src/org/redkale/net/http/RestHttpServlet.java index f501fb204..f096e3cec 100644 --- a/src/org/redkale/net/http/RestHttpServlet.java +++ b/src/org/redkale/net/http/RestHttpServlet.java @@ -6,11 +6,6 @@ package org.redkale.net.http; import java.io.*; -import java.util.concurrent.*; -import java.util.logging.Level; -import jdk.internal.org.objectweb.asm.*; -import static jdk.internal.org.objectweb.asm.Opcodes.*; -import org.redkale.util.*; /** * @@ -23,163 +18,4 @@ public abstract class RestHttpServlet extends HttpServlet { protected abstract T currentUser(HttpRequest req) throws IOException; - protected void finishJson(final HttpResponse response, CompletableFuture future) throws IOException { - future.whenComplete((output, e) -> { - if (e != null) { - response.getContext().getLogger().log(Level.WARNING, "Servlet occur, forece to close channel. request = " + response.getRequest(), e); - response.finish(500, null); - return; - } - try { - finishJson(response, output); - } catch (IOException ioe) { - response.getContext().getLogger().log(Level.WARNING, "Servlet finish RestOutput occur, forece to close channel. request = " + response.getRequest(), ioe); - response.finish(500, null); - } - }); - } - - protected void finishJson(final HttpResponse response, RestOutput output) throws IOException { - if (output == null) { - response.finishJson(output); - return; - } - if (output.getContentType() != null) response.setContentType(output.getContentType()); - response.addHeader(output.getHeaders()); - response.addCookie(output.getCookies()); - response.setStatus(output.getStatus() < 1 ? 200 : output.getStatus()); - if (output.getResult() instanceof File) { - response.finish((File) output.getResult()); - } else if (output.getResult() instanceof String) { - response.finish((String) output.getResult()); - } else if (output.getResult() == null) { - response.finish(output.getMessage()); - } else { - response.finishJson(output.getResult()); - } - } - - /** - * 创建AsyncHandler实例,将非字符串对象以JSON格式输出,字符串以文本输出
- * - * 传入的AsyncHandler子类必须是public,且保证其子类可被继承且completed、failed可被重载且包含空参数的构造函数。 - * - * @param AsyncHandler泛型 - * @param response HttpResponse - * @param handlerClass Class - * - * @return AsyncHandler - */ - protected final H createAsyncHandler(HttpResponse response, final Class handlerClass) { - if (handlerClass == null || handlerClass == AsyncHandler.class) return (H) response.createAsyncHandler(); - Creator creator = creators.get(handlerClass); - if (creator == null) { - creator = createCreator(handlerClass); - creators.put(handlerClass, creator); - } - return (H) creator.create(response.createAsyncHandler()); - } - - private static final ConcurrentHashMap creators = new ConcurrentHashMap<>(); - - private static Creator createCreator(Class handlerClass) { - //生成规则与SncpAsyncHandler.Factory 很类似 - //------------------------------------------------------------- - 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, "", "(" + 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, "", "()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 newHandlerClazz = (Class) 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) Creator.create(newHandlerClazz); - } }