From 707fc783b5e9c3505f20033197fa74eb902e7774 Mon Sep 17 00:00:00 2001
From: Redkale <22250530@qq.com>
Date: Thu, 25 Aug 2016 08:52:18 +0800
Subject: [PATCH]
---
.../redkale/net/http/BasedHttpServlet.java | 356 +----------------
src/org/redkale/net/http/HttpBaseServlet.java | 366 ++++++++++++++++++
.../redkale/net/http/HttpPrepareServlet.java | 8 +-
src/org/redkale/net/http/RestHttpServlet.java | 2 +-
src/org/redkale/net/http/RestService.java | 2 +-
.../redkale/net/http/RestServletBuilder.java | 4 +-
6 files changed, 378 insertions(+), 360 deletions(-)
create mode 100644 src/org/redkale/net/http/HttpBaseServlet.java
diff --git a/src/org/redkale/net/http/BasedHttpServlet.java b/src/org/redkale/net/http/BasedHttpServlet.java
index 97d1baf33..376579a8a 100644
--- a/src/org/redkale/net/http/BasedHttpServlet.java
+++ b/src/org/redkale/net/http/BasedHttpServlet.java
@@ -5,362 +5,14 @@
*/
package org.redkale.net.http;
-import org.redkale.net.Response;
-import org.redkale.net.Request;
-import org.redkale.util.AnyValue;
-import java.io.IOException;
-import java.lang.annotation.*;
-import static java.lang.annotation.ElementType.*;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import java.lang.reflect.Method;
-import java.nio.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.logging.*;
-import jdk.internal.org.objectweb.asm.*;
-import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
-import static jdk.internal.org.objectweb.asm.Opcodes.*;
-import org.redkale.service.RetResult;
-
/**
*
*
* 详情见: http://redkale.org
+ *
+ * @deprecated 使用 org.redkale.net.http.HttpBaseServlet 代替
*
* @author zhangjx
*/
-public abstract class BasedHttpServlet extends HttpServlet {
-
- protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
-
- public static final int RET_SERVER_ERROR = 1800_0001;
-
- public static final int RET_METHOD_ERROR = 1800_0002;
-
- /**
- * 配合 BasedHttpServlet 使用。
- * 当标记为 @AuthIgnore 的方法在执行execute之前不会调用authenticate 方法。
- *
- *
- * 详情见: http://redkale.org
- *
- * @author zhangjx
- */
- @Inherited
- @Documented
- @Target({METHOD, TYPE})
- @Retention(RUNTIME)
- protected @interface AuthIgnore {
-
- }
-
- /**
- * 配合 BasedHttpServlet 使用。
- * 用于对@WebServlet对应的url进行细分。 其url必须是包含WebServlet中定义的前缀, 且不能是正则表达式
- *
- *
- * 详情见: http://redkale.org
- *
- * @author zhangjx
- */
- @Target({ElementType.METHOD})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- protected @interface WebAction {
-
- int actionid() default 0;
-
- String url();
-
- String[] methods() default {};//允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法
- }
-
- /**
- * 配合 BasedHttpServlet 使用。
- * 当标记为 @HttpCacheable 的方法使用response.finish的参数将被缓存一定时间(默认值timeout=15秒)。
- * 通常情况下 @HttpCacheable 需要与 @AuthIgnore 一起使用,因为没有标记@AuthIgnore的方法一般输出的结果与当前用户信息有关。
- *
- *
- * 详情见: http://redkale.org
- *
- * @author zhangjx
- */
- @Target({ElementType.METHOD})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- protected @interface HttpCacheable {
-
- /**
- * 超时的秒数
- *
- * @return 超时秒数
- */
- int timeout() default 15;
- }
-
- private Map.Entry[] actions;
-
- /**
- * 异常输出
- *
- * @param req HTTP请求对象
- * @param resp HTTP响应对象
- * @param exp 异常
- */
- protected void sendExceptionResult(HttpRequest req, HttpResponse resp, Throwable exp) {
- logger.log(Level.SEVERE, "request = " + req, exp);
- resp.finishJson(new RetResult(RET_SERVER_ERROR, "Server Error"));
- }
-
- public boolean preExecute(HttpRequest request, HttpResponse response) throws IOException {
- return true;
- }
-
- @Override
- public final void execute(HttpRequest request, HttpResponse response) throws IOException {
- if (!preExecute(request, response)) return;
- for (Map.Entry en : actions) {
- if (request.getRequestURI().startsWith(en.getKey())) {
- Entry entry = en.getValue();
- if (!entry.checkMethod(request.getMethod())) {
- response.finishJson(new RetResult(RET_METHOD_ERROR, "Method(" + request.getMethod() + ") Error"));
- return;
- }
- if (entry.ignore || authenticate(entry.moduleid, entry.actionid, request, response)) {
- if (entry.cachetimeout > 0) {//有缓存设置
- CacheEntry ce = entry.cache.get(request.getRequestURI());
- if (ce != null && ce.time + entry.cachetimeout > System.currentTimeMillis()) { //缓存有效
- response.setStatus(ce.status);
- response.setContentType(ce.contentType);
- response.finish(ce.getBuffers());
- return;
- }
- response.setBufferHandler(entry.cacheHandler);
- }
- entry.servlet.execute(request, response);
- }
- return;
- }
- }
- throw new IOException(this.getClass().getName() + " not found method for URI(" + request.getRequestURI() + ")");
- }
-
- public final void preInit(HttpContext context, AnyValue config) {
- String path = _prefix == null ? "" : _prefix;
- WebServlet ws = this.getClass().getAnnotation(WebServlet.class);
- if (ws != null && !ws.repair()) path = "";
- HashMap map = load();
- this.actions = new Map.Entry[map.size()];
- int i = -1;
- for (Map.Entry en : map.entrySet()) {
- actions[++i] = new AbstractMap.SimpleEntry<>(path + en.getKey(), en.getValue());
- }
- //必须要倒排序, /query /query1 /query12 确保含子集的优先匹配 /query12 /query1 /query
- Arrays.sort(actions, (o1, o2) -> o2.getKey().compareTo(o1.getKey()));
- }
-
- public final void postDestroy(HttpContext context, AnyValue config) {
- }
-
- public abstract boolean authenticate(int module, int actionid, HttpRequest request, HttpResponse response) throws IOException;
-
- private HashMap load() {
- final boolean typeIgnore = this.getClass().getAnnotation(AuthIgnore.class) != null;
- WebServlet module = this.getClass().getAnnotation(WebServlet.class);
- final int serviceid = module == null ? 0 : module.moduleid();
- final HashMap map = new HashMap<>();
- Set nameset = new HashSet<>();
- for (final Method method : this.getClass().getMethods()) {
- //-----------------------------------------------
- String methodname = method.getName();
- if ("service".equals(methodname) || "preExecute".equals(methodname) || "execute".equals(methodname) || "authenticate".equals(methodname)) continue;
- //-----------------------------------------------
- Class[] paramTypes = method.getParameterTypes();
- if (paramTypes.length != 2 || paramTypes[0] != HttpRequest.class
- || paramTypes[1] != HttpResponse.class) continue;
- //-----------------------------------------------
- Class[] exps = method.getExceptionTypes();
- if (exps.length > 0 && (exps.length != 1 || exps[0] != IOException.class)) continue;
- //-----------------------------------------------
-
- final WebAction action = method.getAnnotation(WebAction.class);
- if (action == null) continue;
- final int actionid = action.actionid();
- final String name = action.url().trim();
-
- if (nameset.contains(name)) throw new RuntimeException(this.getClass().getSimpleName() + " has two same " + WebAction.class.getSimpleName() + "(" + name + ")");
- //屏蔽以下代码,允许相互包含
-// for (String n : nameset) {
-// if (n.contains(name) || name.contains(n)) {
-// throw new RuntimeException(this.getClass().getSimpleName() + " has two sub-contains " + WebAction.class.getSimpleName() + "(" + name + ", " + n + ")");
-// }
-// }
- nameset.add(name);
- map.put(name, new Entry(typeIgnore, serviceid, actionid, name, action.methods(), method, createHttpServlet(method)));
- }
- return map;
- }
-
- private HttpServlet createHttpServlet(final Method method) {
- //------------------------------------------------------------------------------
- final String supDynName = HttpServlet.class.getName().replace('.', '/');
- final String interName = this.getClass().getName().replace('.', '/');
- final String interDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(this.getClass());
- final String requestSupDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(Request.class);
- final String responseSupDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(Response.class);
- final String requestDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(HttpRequest.class);
- final String responseDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(HttpResponse.class);
- String newDynName = interName + "_Dyn_" + method.getName();
- int i = 0;
- for (;;) {
- try {
- Class.forName(newDynName.replace('/', '.'));
- newDynName += "_" + (++i);
- } catch (Exception ex) {
- break;
- }
- }
- //------------------------------------------------------------------------------
- ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
- FieldVisitor fv;
- MethodVisitor mv;
- AnnotationVisitor av0;
- final String factfield = "_factServlet";
- cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null);
- {
- fv = cw.visitField(ACC_PUBLIC, factfield, interDesc, null, null);
- fv.visitEnd();
- }
- { //构造函数
- mv = (cw.visitMethod(ACC_PUBLIC, "", "()V", null, null));
- //mv.setDebug(true);
- mv.visitVarInsn(ALOAD, 0);
- mv.visitMethodInsn(INVOKESPECIAL, supDynName, "", "()V", false);
- mv.visitInsn(RETURN);
- mv.visitMaxs(1, 1);
- mv.visitEnd();
- }
- {
- mv = (cw.visitMethod(ACC_PUBLIC, "execute", "(" + requestDesc + responseDesc + ")V", null, new String[]{"java/io/IOException"}));
- mv.visitVarInsn(ALOAD, 0);
- mv.visitFieldInsn(GETFIELD, newDynName, factfield, interDesc);
- mv.visitVarInsn(ALOAD, 1);
- mv.visitVarInsn(ALOAD, 2);
- mv.visitMethodInsn(INVOKEVIRTUAL, interName, method.getName(), "(" + requestDesc + responseDesc + ")V", false);
- mv.visitInsn(RETURN);
- mv.visitMaxs(3, 3);
- mv.visitEnd();
- }
- {
- mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "execute", "(" + requestSupDesc + responseSupDesc + ")V", null, new String[]{"java/io/IOException"});
- mv.visitVarInsn(ALOAD, 0);
- mv.visitVarInsn(ALOAD, 1);
- mv.visitTypeInsn(CHECKCAST, HttpRequest.class.getName().replace('.', '/'));
- mv.visitVarInsn(ALOAD, 2);
- mv.visitTypeInsn(CHECKCAST, HttpResponse.class.getName().replace('.', '/'));
- mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "execute", "(" + requestDesc + responseDesc + ")V", false);
- mv.visitInsn(RETURN);
- mv.visitMaxs(3, 3);
- mv.visitEnd();
- }
- cw.visitEnd();
- //------------------------------------------------------------------------------
- byte[] bytes = cw.toByteArray();
- Class> newClazz = new ClassLoader(this.getClass().getClassLoader()) {
- public final Class> loadClass(String name, byte[] b) {
- return defineClass(name, b, 0, b.length);
- }
- }.loadClass(newDynName.replace('/', '.'), bytes);
- try {
- HttpServlet instance = (HttpServlet) newClazz.newInstance();
- instance.getClass().getField(factfield).set(instance, this);
- return instance;
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
- private static final class Entry {
-
- public Entry(boolean typeIgnore, int moduleid, int actionid, String name, String[] methods, Method method, HttpServlet servlet) {
- this.moduleid = moduleid;
- this.actionid = actionid;
- this.name = name;
- this.methods = methods;
- this.method = method;
- this.servlet = servlet;
- this.ignore = typeIgnore || method.getAnnotation(AuthIgnore.class) != null;
- HttpCacheable hc = method.getAnnotation(HttpCacheable.class);
- this.cachetimeout = hc == null ? 0 : hc.timeout() * 1000;
- this.cache = cachetimeout > 0 ? new ConcurrentHashMap() : null;
- this.cacheHandler = cachetimeout > 0 ? (HttpResponse response, ByteBuffer[] buffers) -> {
- int status = response.getStatus();
- if (status != 200) return null;
- CacheEntry ce = new CacheEntry(response.getStatus(), response.getContentType(), buffers);
- cache.put(response.getRequest().getRequestURI(), ce);
- return ce.getBuffers();
- } : null;
- }
-
- public boolean isNeedCheck() {
- return this.moduleid != 0 || this.actionid != 0;
- }
-
- public boolean checkMethod(final String reqMethod) {
- if (methods.length == 0) return true;
- for (String m : methods) {
- if (reqMethod.equalsIgnoreCase(m)) return true;
- }
- return false;
- }
-
- public final HttpResponse.BufferHandler cacheHandler;
-
- public final ConcurrentHashMap cache;
-
- public final int cachetimeout;
-
- public final boolean ignore;
-
- public final int moduleid;
-
- public final int actionid;
-
- public final String name;
-
- public final String[] methods;
-
- public final Method method;
-
- public final HttpServlet servlet;
- }
-
- private static final class CacheEntry {
-
- public final long time = System.currentTimeMillis();
-
- private final ByteBuffer[] buffers;
-
- private final int status;
-
- private final String contentType;
-
- public CacheEntry(int status, String contentType, ByteBuffer[] bufs) {
- this.status = status;
- this.contentType = contentType;
- final ByteBuffer[] newBuffers = new ByteBuffer[bufs.length];
- for (int i = 0; i < newBuffers.length; i++) {
- newBuffers[i] = bufs[i].duplicate().asReadOnlyBuffer();
- }
- this.buffers = newBuffers;
- }
-
- public ByteBuffer[] getBuffers() {
- final ByteBuffer[] newBuffers = new ByteBuffer[buffers.length];
- for (int i = 0; i < newBuffers.length; i++) {
- newBuffers[i] = buffers[i].duplicate();
- }
- return newBuffers;
- }
- }
-}
+public abstract class BasedHttpServlet extends HttpBaseServlet {
+}
\ No newline at end of file
diff --git a/src/org/redkale/net/http/HttpBaseServlet.java b/src/org/redkale/net/http/HttpBaseServlet.java
new file mode 100644
index 000000000..ca89ec0bd
--- /dev/null
+++ b/src/org/redkale/net/http/HttpBaseServlet.java
@@ -0,0 +1,366 @@
+/*
+ * 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.http;
+
+import org.redkale.net.Response;
+import org.redkale.net.Request;
+import org.redkale.util.AnyValue;
+import java.io.IOException;
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.reflect.Method;
+import java.nio.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.logging.*;
+import jdk.internal.org.objectweb.asm.*;
+import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+import org.redkale.service.RetResult;
+
+/**
+ *
+ *
+ * 详情见: http://redkale.org
+ *
+ * @author zhangjx
+ */
+public abstract class HttpBaseServlet extends HttpServlet {
+
+ protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
+
+ public static final int RET_SERVER_ERROR = 1800_0001;
+
+ public static final int RET_METHOD_ERROR = 1800_0002;
+
+ /**
+ * 配合 HttpBaseServlet 使用。
+ * 当标记为 @AuthIgnore 的方法在执行execute之前不会调用authenticate 方法。
+ *
+ *
+ * 详情见: http://redkale.org
+ *
+ * @author zhangjx
+ */
+ @Inherited
+ @Documented
+ @Target({METHOD, TYPE})
+ @Retention(RUNTIME)
+ protected @interface AuthIgnore {
+
+ }
+
+ /**
+ * 配合 HttpBaseServlet 使用。
+ * 用于对@WebServlet对应的url进行细分。 其url必须是包含WebServlet中定义的前缀, 且不能是正则表达式
+ *
+ *
+ * 详情见: http://redkale.org
+ *
+ * @author zhangjx
+ */
+ @Target({ElementType.METHOD})
+ @Retention(RetentionPolicy.RUNTIME)
+ @Documented
+ protected @interface WebAction {
+
+ int actionid() default 0;
+
+ String url();
+
+ String[] methods() default {};//允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法
+ }
+
+ /**
+ * 配合 HttpBaseServlet 使用。
+ * 当标记为 @HttpCacheable 的方法使用response.finish的参数将被缓存一定时间(默认值timeout=15秒)。
+ * 通常情况下 @HttpCacheable 需要与 @AuthIgnore 一起使用,因为没有标记@AuthIgnore的方法一般输出的结果与当前用户信息有关。
+ *
+ *
+ * 详情见: http://redkale.org
+ *
+ * @author zhangjx
+ */
+ @Target({ElementType.METHOD})
+ @Retention(RetentionPolicy.RUNTIME)
+ @Documented
+ protected @interface HttpCacheable {
+
+ /**
+ * 超时的秒数
+ *
+ * @return 超时秒数
+ */
+ int timeout() default 15;
+ }
+
+ private Map.Entry[] actions;
+
+ /**
+ * 异常输出
+ *
+ * @param req HTTP请求对象
+ * @param resp HTTP响应对象
+ * @param exp 异常
+ */
+ protected void sendExceptionResult(HttpRequest req, HttpResponse resp, Throwable exp) {
+ logger.log(Level.SEVERE, "request = " + req, exp);
+ resp.finishJson(new RetResult(RET_SERVER_ERROR, "Server Error"));
+ }
+
+ public boolean preExecute(HttpRequest request, HttpResponse response) throws IOException {
+ return true;
+ }
+
+ @Override
+ public final void execute(HttpRequest request, HttpResponse response) throws IOException {
+ if (!preExecute(request, response)) return;
+ for (Map.Entry en : actions) {
+ if (request.getRequestURI().startsWith(en.getKey())) {
+ Entry entry = en.getValue();
+ if (!entry.checkMethod(request.getMethod())) {
+ response.finishJson(new RetResult(RET_METHOD_ERROR, "Method(" + request.getMethod() + ") Error"));
+ return;
+ }
+ if (entry.ignore || authenticate(entry.moduleid, entry.actionid, request, response)) {
+ if (entry.cachetimeout > 0) {//有缓存设置
+ CacheEntry ce = entry.cache.get(request.getRequestURI());
+ if (ce != null && ce.time + entry.cachetimeout > System.currentTimeMillis()) { //缓存有效
+ response.setStatus(ce.status);
+ response.setContentType(ce.contentType);
+ response.finish(ce.getBuffers());
+ return;
+ }
+ response.setBufferHandler(entry.cacheHandler);
+ }
+ entry.servlet.execute(request, response);
+ }
+ return;
+ }
+ }
+ throw new IOException(this.getClass().getName() + " not found method for URI(" + request.getRequestURI() + ")");
+ }
+
+ public final void preInit(HttpContext context, AnyValue config) {
+ String path = _prefix == null ? "" : _prefix;
+ WebServlet ws = this.getClass().getAnnotation(WebServlet.class);
+ if (ws != null && !ws.repair()) path = "";
+ HashMap map = load();
+ this.actions = new Map.Entry[map.size()];
+ int i = -1;
+ for (Map.Entry en : map.entrySet()) {
+ actions[++i] = new AbstractMap.SimpleEntry<>(path + en.getKey(), en.getValue());
+ }
+ //必须要倒排序, /query /query1 /query12 确保含子集的优先匹配 /query12 /query1 /query
+ Arrays.sort(actions, (o1, o2) -> o2.getKey().compareTo(o1.getKey()));
+ }
+
+ public final void postDestroy(HttpContext context, AnyValue config) {
+ }
+
+ public abstract boolean authenticate(int module, int actionid, HttpRequest request, HttpResponse response) throws IOException;
+
+ private HashMap load() {
+ final boolean typeIgnore = this.getClass().getAnnotation(AuthIgnore.class) != null;
+ WebServlet module = this.getClass().getAnnotation(WebServlet.class);
+ final int serviceid = module == null ? 0 : module.moduleid();
+ final HashMap map = new HashMap<>();
+ Set nameset = new HashSet<>();
+ for (final Method method : this.getClass().getMethods()) {
+ //-----------------------------------------------
+ String methodname = method.getName();
+ if ("service".equals(methodname) || "preExecute".equals(methodname) || "execute".equals(methodname) || "authenticate".equals(methodname)) continue;
+ //-----------------------------------------------
+ Class[] paramTypes = method.getParameterTypes();
+ if (paramTypes.length != 2 || paramTypes[0] != HttpRequest.class
+ || paramTypes[1] != HttpResponse.class) continue;
+ //-----------------------------------------------
+ Class[] exps = method.getExceptionTypes();
+ if (exps.length > 0 && (exps.length != 1 || exps[0] != IOException.class)) continue;
+ //-----------------------------------------------
+
+ final WebAction action = method.getAnnotation(WebAction.class);
+ if (action == null) continue;
+ final int actionid = action.actionid();
+ final String name = action.url().trim();
+
+ if (nameset.contains(name)) throw new RuntimeException(this.getClass().getSimpleName() + " has two same " + WebAction.class.getSimpleName() + "(" + name + ")");
+ //屏蔽以下代码,允许相互包含
+// for (String n : nameset) {
+// if (n.contains(name) || name.contains(n)) {
+// throw new RuntimeException(this.getClass().getSimpleName() + " has two sub-contains " + WebAction.class.getSimpleName() + "(" + name + ", " + n + ")");
+// }
+// }
+ nameset.add(name);
+ map.put(name, new Entry(typeIgnore, serviceid, actionid, name, action.methods(), method, createHttpServlet(method)));
+ }
+ return map;
+ }
+
+ private HttpServlet createHttpServlet(final Method method) {
+ //------------------------------------------------------------------------------
+ final String supDynName = HttpServlet.class.getName().replace('.', '/');
+ final String interName = this.getClass().getName().replace('.', '/');
+ final String interDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(this.getClass());
+ final String requestSupDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(Request.class);
+ final String responseSupDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(Response.class);
+ final String requestDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(HttpRequest.class);
+ final String responseDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(HttpResponse.class);
+ String newDynName = interName + "_Dyn_" + method.getName();
+ int i = 0;
+ for (;;) {
+ try {
+ Class.forName(newDynName.replace('/', '.'));
+ newDynName += "_" + (++i);
+ } catch (Exception ex) {
+ break;
+ }
+ }
+ //------------------------------------------------------------------------------
+ ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
+ FieldVisitor fv;
+ MethodVisitor mv;
+ AnnotationVisitor av0;
+ final String factfield = "_factServlet";
+ cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null);
+ {
+ fv = cw.visitField(ACC_PUBLIC, factfield, interDesc, null, null);
+ fv.visitEnd();
+ }
+ { //构造函数
+ mv = (cw.visitMethod(ACC_PUBLIC, "", "()V", null, null));
+ //mv.setDebug(true);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, supDynName, "", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ {
+ mv = (cw.visitMethod(ACC_PUBLIC, "execute", "(" + requestDesc + responseDesc + ")V", null, new String[]{"java/io/IOException"}));
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, newDynName, factfield, interDesc);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitVarInsn(ALOAD, 2);
+ mv.visitMethodInsn(INVOKEVIRTUAL, interName, method.getName(), "(" + requestDesc + responseDesc + ")V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(3, 3);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "execute", "(" + requestSupDesc + responseSupDesc + ")V", null, new String[]{"java/io/IOException"});
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitTypeInsn(CHECKCAST, HttpRequest.class.getName().replace('.', '/'));
+ mv.visitVarInsn(ALOAD, 2);
+ mv.visitTypeInsn(CHECKCAST, HttpResponse.class.getName().replace('.', '/'));
+ mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "execute", "(" + requestDesc + responseDesc + ")V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(3, 3);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+ //------------------------------------------------------------------------------
+ byte[] bytes = cw.toByteArray();
+ Class> newClazz = new ClassLoader(this.getClass().getClassLoader()) {
+ public final Class> loadClass(String name, byte[] b) {
+ return defineClass(name, b, 0, b.length);
+ }
+ }.loadClass(newDynName.replace('/', '.'), bytes);
+ try {
+ HttpServlet instance = (HttpServlet) newClazz.newInstance();
+ instance.getClass().getField(factfield).set(instance, this);
+ return instance;
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private static final class Entry {
+
+ public Entry(boolean typeIgnore, int moduleid, int actionid, String name, String[] methods, Method method, HttpServlet servlet) {
+ this.moduleid = moduleid;
+ this.actionid = actionid;
+ this.name = name;
+ this.methods = methods;
+ this.method = method;
+ this.servlet = servlet;
+ this.ignore = typeIgnore || method.getAnnotation(AuthIgnore.class) != null;
+ HttpCacheable hc = method.getAnnotation(HttpCacheable.class);
+ this.cachetimeout = hc == null ? 0 : hc.timeout() * 1000;
+ this.cache = cachetimeout > 0 ? new ConcurrentHashMap() : null;
+ this.cacheHandler = cachetimeout > 0 ? (HttpResponse response, ByteBuffer[] buffers) -> {
+ int status = response.getStatus();
+ if (status != 200) return null;
+ CacheEntry ce = new CacheEntry(response.getStatus(), response.getContentType(), buffers);
+ cache.put(response.getRequest().getRequestURI(), ce);
+ return ce.getBuffers();
+ } : null;
+ }
+
+ public boolean isNeedCheck() {
+ return this.moduleid != 0 || this.actionid != 0;
+ }
+
+ public boolean checkMethod(final String reqMethod) {
+ if (methods.length == 0) return true;
+ for (String m : methods) {
+ if (reqMethod.equalsIgnoreCase(m)) return true;
+ }
+ return false;
+ }
+
+ public final HttpResponse.BufferHandler cacheHandler;
+
+ public final ConcurrentHashMap cache;
+
+ public final int cachetimeout;
+
+ public final boolean ignore;
+
+ public final int moduleid;
+
+ public final int actionid;
+
+ public final String name;
+
+ public final String[] methods;
+
+ public final Method method;
+
+ public final HttpServlet servlet;
+ }
+
+ private static final class CacheEntry {
+
+ public final long time = System.currentTimeMillis();
+
+ private final ByteBuffer[] buffers;
+
+ private final int status;
+
+ private final String contentType;
+
+ public CacheEntry(int status, String contentType, ByteBuffer[] bufs) {
+ this.status = status;
+ this.contentType = contentType;
+ final ByteBuffer[] newBuffers = new ByteBuffer[bufs.length];
+ for (int i = 0; i < newBuffers.length; i++) {
+ newBuffers[i] = bufs[i].duplicate().asReadOnlyBuffer();
+ }
+ this.buffers = newBuffers;
+ }
+
+ public ByteBuffer[] getBuffers() {
+ final ByteBuffer[] newBuffers = new ByteBuffer[buffers.length];
+ for (int i = 0; i < newBuffers.length; i++) {
+ newBuffers[i] = buffers[i].duplicate();
+ }
+ return newBuffers;
+ }
+ }
+}
diff --git a/src/org/redkale/net/http/HttpPrepareServlet.java b/src/org/redkale/net/http/HttpPrepareServlet.java
index 12dd5d480..45640f5cd 100644
--- a/src/org/redkale/net/http/HttpPrepareServlet.java
+++ b/src/org/redkale/net/http/HttpPrepareServlet.java
@@ -36,8 +36,8 @@ public final class HttpPrepareServlet extends PrepareServlet {
if (s instanceof WebSocketServlet) {
((WebSocketServlet) s).preInit(context, getServletConf(s));
- } else if (s instanceof BasedHttpServlet) {
- ((BasedHttpServlet) s).preInit(context, getServletConf(s));
+ } else if (s instanceof HttpBaseServlet) {
+ ((HttpBaseServlet) s).preInit(context, getServletConf(s));
}
s.init(context, getServletConf(s));
});
@@ -165,8 +165,8 @@ public final class HttpPrepareServlet extends PrepareServlet
*/
-public abstract class RestHttpServlet extends BasedHttpServlet {
+public abstract class RestHttpServlet extends HttpBaseServlet {
protected abstract T currentUser(HttpRequest req) throws IOException;
diff --git a/src/org/redkale/net/http/RestService.java b/src/org/redkale/net/http/RestService.java
index 92b502f16..d5f10c351 100644
--- a/src/org/redkale/net/http/RestService.java
+++ b/src/org/redkale/net/http/RestService.java
@@ -29,6 +29,6 @@ public @interface RestService {
boolean repair() default true; //同@WebServlet的repair属性
- int module() default 0; //模块ID值,鉴权时用到, 对应@WebServlet.ignore
+ int module() default 0; //模块ID值,鉴权时用到, 对应@WebServlet.module
}
diff --git a/src/org/redkale/net/http/RestServletBuilder.java b/src/org/redkale/net/http/RestServletBuilder.java
index 6f88e9567..37e0f5f0d 100644
--- a/src/org/redkale/net/http/RestServletBuilder.java
+++ b/src/org/redkale/net/http/RestServletBuilder.java
@@ -49,8 +49,8 @@ public final class RestServletBuilder {
final String webServletDesc = Type.getDescriptor(WebServlet.class);
final String httpRequestDesc = Type.getDescriptor(HttpRequest.class);
final String httpResponseDesc = Type.getDescriptor(HttpResponse.class);
- final String authDesc = Type.getDescriptor(BasedHttpServlet.AuthIgnore.class);
- final String actionDesc = Type.getDescriptor(BasedHttpServlet.WebAction.class);
+ final String authDesc = Type.getDescriptor(HttpBaseServlet.AuthIgnore.class);
+ final String actionDesc = Type.getDescriptor(HttpBaseServlet.WebAction.class);
final String serviceTypeString = serviceType.getName().replace('.', '/');
final Class userType = getSuperUserType(baseServletClass);