This commit is contained in:
@@ -170,18 +170,6 @@ public abstract class Response<C extends Context, R extends Request<C>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 public void recycleListener(BiConsumer recycleListener) 代替
|
|
||||||
*
|
|
||||||
* @param recycleListener BiConsumer
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void setRecycleListener(BiConsumer<R, Response<C, R>> recycleListener) {
|
|
||||||
this.recycleListener = recycleListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void recycleListener(BiConsumer<R, Response<C, R>> recycleListener) {
|
public void recycleListener(BiConsumer<R, Response<C, R>> recycleListener) {
|
||||||
this.recycleListener = recycleListener;
|
this.recycleListener = recycleListener;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认Servlet, 没有配置RestServlet实现类则使用该默认类
|
|
||||||
* <p>
|
|
||||||
* 详情见: https://redkale.org
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class DefaultRestServlet extends RestHttpServlet<Object> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object currentUser(HttpRequest req) throws IOException {
|
|
||||||
return new Object();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,538 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 java.io.*;
|
|
||||||
import org.redkale.net.Response;
|
|
||||||
import org.redkale.net.Request;
|
|
||||||
import org.redkale.util.AnyValue;
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import static java.lang.annotation.ElementType.*;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.nio.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 直接只用HttpServlet代替, 将在1.9版本移除
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 详情见: https://redkale.org
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public abstract class HttpBaseServlet extends HttpServlet {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 org.redkale.util.AuthIgnore 代替
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 详情见: https://redkale.org
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Inherited
|
|
||||||
@Documented
|
|
||||||
@Target({METHOD, TYPE})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
@Deprecated
|
|
||||||
protected @interface AuthIgnore {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配合 @WebParam 使用。
|
|
||||||
* 用于对@WebParam中参数的来源类型
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 详情见: https://redkale.org
|
|
||||||
*
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
protected enum ParamSourceType {
|
|
||||||
|
|
||||||
PARAMETER, HEADER, COOKIE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* 使用 org.redkale.net.http.HttpParam 代替
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 详情见: https://redkale.org
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Target({METHOD})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
@Repeatable(WebParams.class)
|
|
||||||
@Deprecated
|
|
||||||
protected @interface WebParam {
|
|
||||||
|
|
||||||
String name(); //参数名
|
|
||||||
|
|
||||||
Class type(); //参数的数据类型
|
|
||||||
|
|
||||||
String comment() default ""; //备注描述
|
|
||||||
|
|
||||||
ParamSourceType src() default ParamSourceType.PARAMETER; //参数来源类型
|
|
||||||
|
|
||||||
int radix() default 10; //转换数字byte/short/int/long时所用的进制数, 默认10进制
|
|
||||||
|
|
||||||
boolean required() default true; //参数是否必传
|
|
||||||
}
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Target({METHOD})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
protected @interface WebParams {
|
|
||||||
|
|
||||||
WebParam[] value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 org.redkale.net.http.HttpMapping 替代。
|
|
||||||
* <p>
|
|
||||||
* 详情见: https://redkale.org
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Target({METHOD})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
@Deprecated
|
|
||||||
protected @interface WebAction {
|
|
||||||
|
|
||||||
int actionid() default 0;
|
|
||||||
|
|
||||||
String url();
|
|
||||||
|
|
||||||
String[] methods() default {};//允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法
|
|
||||||
|
|
||||||
String comment() default ""; //备注描述
|
|
||||||
|
|
||||||
boolean inherited() default true; //是否能被继承, 当 HttpBaseServlet 被继承后该方法是否能被子类继承
|
|
||||||
|
|
||||||
String result() default "Object"; //输出结果的数据类型
|
|
||||||
|
|
||||||
Class[] results() default {}; //输出结果的数据类型集合,由于结果类型可能是泛型而注解的参数值不支持泛型,因此加入明细数据类型集合
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 org.redkale.net.http.HttpMapping 替代。
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 详情见: https://redkale.org
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Target({METHOD})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
@Deprecated
|
|
||||||
protected @interface WebMapping {
|
|
||||||
|
|
||||||
int actionid() default 0;
|
|
||||||
|
|
||||||
String url();
|
|
||||||
|
|
||||||
String[] methods() default {};//允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法
|
|
||||||
|
|
||||||
String comment() default ""; //备注描述
|
|
||||||
|
|
||||||
boolean inherited() default true; //是否能被继承, 当 HttpBaseServlet 被继承后该方法是否能被子类继承
|
|
||||||
|
|
||||||
String result() default "Object"; //输出结果的数据类型
|
|
||||||
|
|
||||||
Class[] results() default {}; //输出结果的数据类型集合,由于结果类型可能是泛型而注解的参数值不支持泛型,因此加入明细数据类型集合
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 org.redkale.net.http.HttpMapping.cacheseconds 替代。
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Target({METHOD})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
@Deprecated
|
|
||||||
protected @interface HttpCacheable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超时的秒数
|
|
||||||
*
|
|
||||||
* @return 超时秒数
|
|
||||||
*/
|
|
||||||
int seconds() default 15;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map.Entry<String, Entry>[] mappings;
|
|
||||||
|
|
||||||
private final HttpServlet authSuccessServlet = new HttpServlet() {
|
|
||||||
@Override
|
|
||||||
public void execute(HttpRequest request, HttpResponse response) throws IOException {
|
|
||||||
Entry entry = (Entry) request.getAttribute("_redkale_entry");
|
|
||||||
if (entry.cacheseconds > 0) {//有缓存设置
|
|
||||||
CacheEntry ce = entry.cache.get(request.getRequestURI());
|
|
||||||
if (ce != null && ce.time + entry.cacheseconds > System.currentTimeMillis()) { //缓存有效
|
|
||||||
response.setStatus(ce.status);
|
|
||||||
response.setContentType(ce.contentType);
|
|
||||||
response.finish(ce.getBuffers());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
response.setBufferHandler(entry.cacheHandler);
|
|
||||||
}
|
|
||||||
entry.servlet.execute(request, response);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final HttpServlet preSuccessServlet = new HttpServlet() {
|
|
||||||
@Override
|
|
||||||
public void execute(HttpRequest request, HttpResponse response) throws IOException {
|
|
||||||
for (Map.Entry<String, Entry> en : mappings) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
request.setAttribute("_redkale_entry", entry);
|
|
||||||
if (entry.ignore) {
|
|
||||||
authSuccessServlet.execute(request, response);
|
|
||||||
} else {
|
|
||||||
HttpBaseServlet.this.authenticate(entry.moduleid, entry.actionid, request, response, authSuccessServlet);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new IOException(this.getClass().getName() + " not found method for URI(" + request.getRequestURI() + ")");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 预执行方法,在execute方法之前运行,通常用于常规统计或基础检测,例如 : <br>
|
|
||||||
* <blockquote><pre>
|
|
||||||
* @Override
|
|
||||||
* public void preExecute(final HttpRequest request, final HttpResponse response, HttpServlet next) throws IOException {
|
|
||||||
* if (finer) response.setRecycleListener((req, resp) -> { //记录处理时间比较长的请求
|
|
||||||
* long e = System.currentTimeMillis() - ((HttpRequest) req).getCreatetime();
|
|
||||||
* if (e > 200) logger.finer("http-execute-cost-time: " + e + " ms. request = " + req);
|
|
||||||
* });
|
|
||||||
* next.execute(request, response);
|
|
||||||
* }
|
|
||||||
* </pre></blockquote>
|
|
||||||
* <p>
|
|
||||||
*
|
|
||||||
* @param request HttpRequest
|
|
||||||
* @param response HttpResponse
|
|
||||||
* @param next HttpServlet
|
|
||||||
*
|
|
||||||
* @throws IOException IOException
|
|
||||||
*/
|
|
||||||
public void preExecute(HttpRequest request, HttpResponse response, final HttpServlet next) throws IOException {
|
|
||||||
next.execute(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 public void authenticate(int moduleid, int actionid, HttpRequest request, HttpResponse response, final HttpServlet next) throws IOException 代替
|
|
||||||
*
|
|
||||||
* @param moduleid int
|
|
||||||
* @param actionid int
|
|
||||||
* @param request HttpRequest
|
|
||||||
* @param response HttpResponse
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
* @throws IOException IOException
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public boolean authenticate(int moduleid, int actionid, HttpRequest request, HttpResponse response) throws IOException {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 用户登录或权限验证, 没有注解为@AuthIgnore 的方法会执行authenticate方法, 若验证成功则必须调用next.execute(request, response);进行下一步操作, 例如: <br>
|
|
||||||
* <blockquote><pre>
|
|
||||||
* @Override
|
|
||||||
* public void authenticate(int moduleid, int actionid, HttpRequest request, HttpResponse response, final HttpServlet next) throws IOException {
|
|
||||||
* UserInfo info = currentUser(request);
|
|
||||||
* if (info == null) {
|
|
||||||
* response.finishJson(RET_UNLOGIN);
|
|
||||||
* return;
|
|
||||||
* } else if (!info.checkAuth(module, actionid)) {
|
|
||||||
* response.finishJson(RET_AUTHILLEGAL);
|
|
||||||
* return;
|
|
||||||
* }
|
|
||||||
* next.execute(request, response);
|
|
||||||
* }
|
|
||||||
* </pre></blockquote>
|
|
||||||
* <p>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param moduleid 模块ID,来自@WebServlet.moduleid()
|
|
||||||
* @param actionid 操作ID,来自@WebMapping.actionid()
|
|
||||||
* @param request HttpRequest
|
|
||||||
* @param response HttpResponse
|
|
||||||
* @param next HttpServlet
|
|
||||||
*
|
|
||||||
* @throws IOException IOException
|
|
||||||
*/
|
|
||||||
public abstract void authenticate(int moduleid, int actionid, HttpRequest request, HttpResponse response, final HttpServlet next) throws IOException;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void execute(HttpRequest request, HttpResponse response) throws IOException {
|
|
||||||
preExecute(request, response, preSuccessServlet);
|
|
||||||
}
|
|
||||||
|
|
||||||
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<String, Entry> map = load();
|
|
||||||
this.mappings = new Map.Entry[map.size()];
|
|
||||||
int i = -1;
|
|
||||||
for (Map.Entry<String, Entry> en : map.entrySet()) {
|
|
||||||
mappings[++i] = new AbstractMap.SimpleEntry<>(path + en.getKey(), en.getValue());
|
|
||||||
}
|
|
||||||
//必须要倒排序, /query /query1 /query12 确保含子集的优先匹配 /query12 /query1 /query
|
|
||||||
Arrays.sort(mappings, (o1, o2) -> o2.getKey().compareTo(o1.getKey()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void postDestroy(HttpContext context, AnyValue config) {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setHeader(HttpRequest request, String name, Serializable value) {
|
|
||||||
request.header.setValue(name, String.valueOf(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addHeader(HttpRequest request, String name, Serializable value) {
|
|
||||||
request.header.addValue(name, String.valueOf(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String _prefix(HttpServlet servlet) {
|
|
||||||
return servlet._prefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
private HashMap<String, Entry> 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<String, Entry> map = new HashMap<>();
|
|
||||||
HashMap<String, Class> nameset = new HashMap<>();
|
|
||||||
final Class selfClz = this.getClass();
|
|
||||||
Class clz = this.getClass();
|
|
||||||
do {
|
|
||||||
if (Modifier.isAbstract(clz.getModifiers())) break;
|
|
||||||
for (final Method method : clz.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 WebMapping mapping = method.getAnnotation(WebMapping.class);
|
|
||||||
final WebAction action = method.getAnnotation(WebAction.class);
|
|
||||||
if (mapping == null && action == null) continue;
|
|
||||||
final boolean inherited = mapping == null ? action.inherited() : mapping.inherited();
|
|
||||||
if (!inherited && selfClz != clz) continue; //忽略不被继承的方法
|
|
||||||
final int actionid = mapping == null ? action.actionid() : mapping.actionid();
|
|
||||||
final String name = mapping == null ? action.url().trim() : mapping.url().trim();
|
|
||||||
final String[] methods = mapping == null ? action.methods() : mapping.methods();
|
|
||||||
if (nameset.containsKey(name)) {
|
|
||||||
if (nameset.get(name) != clz) continue;
|
|
||||||
throw new RuntimeException(this.getClass().getSimpleName() + " have two same " + WebMapping.class.getSimpleName() + "(" + name + ")");
|
|
||||||
}
|
|
||||||
nameset.put(name, clz);
|
|
||||||
map.put(name, new Entry(typeIgnore, serviceid, actionid, name, methods, method, createHttpServlet(method)));
|
|
||||||
}
|
|
||||||
} while ((clz = clz.getSuperclass()) != HttpBaseServlet.class);
|
|
||||||
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 (Throwable 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, "<init>", "()V", null, null));
|
|
||||||
//mv.setDebug(true);
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
|
||||||
mv.visitMethodInsn(INVOKESPECIAL, supDynName, "<init>", "()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.cacheseconds = hc == null ? 0 : hc.seconds() * 1000;
|
|
||||||
this.cache = cacheseconds > 0 ? new ConcurrentHashMap() : null;
|
|
||||||
this.cacheHandler = cacheseconds > 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<String, CacheEntry> cache;
|
|
||||||
|
|
||||||
public final int cacheseconds;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 java.io.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 RestServlet 代替
|
|
||||||
*
|
|
||||||
* 详情见: https://redkale.org
|
|
||||||
*
|
|
||||||
* @author zhangjx
|
|
||||||
* @deprecated
|
|
||||||
* @param <T> 当前用户对象类型
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class RestHttpServlet<T> extends HttpServlet {
|
|
||||||
|
|
||||||
protected T currentUser(HttpRequest req) throws IOException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 java.io.Serializable;
|
|
||||||
import java.net.HttpCookie;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 HttpResult 代替
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 详情见: https://redkale.org
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <T> 结果对象的类型
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class RestOutput<T> {
|
|
||||||
|
|
||||||
private Map<String, String> headers;
|
|
||||||
|
|
||||||
private List<HttpCookie> cookies;
|
|
||||||
|
|
||||||
private String contentType;
|
|
||||||
|
|
||||||
private T result;
|
|
||||||
|
|
||||||
private int status = 0; //不设置则为 200
|
|
||||||
|
|
||||||
private String message;
|
|
||||||
|
|
||||||
public RestOutput() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public RestOutput(T result) {
|
|
||||||
this.result = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RestOutput<T> addHeader(String name, Serializable value) {
|
|
||||||
if (this.headers == null) this.headers = new HashMap<>();
|
|
||||||
this.headers.put(name, String.valueOf(value));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RestOutput<T> addCookie(HttpCookie cookie) {
|
|
||||||
if (this.cookies == null) this.cookies = new ArrayList<>();
|
|
||||||
this.cookies.add(cookie);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getHeaders() {
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHeaders(Map<String, String> headers) {
|
|
||||||
this.headers = headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<HttpCookie> getCookies() {
|
|
||||||
return cookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCookies(List<HttpCookie> cookies) {
|
|
||||||
this.cookies = cookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getContentType() {
|
|
||||||
return contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContentType(String contentType) {
|
|
||||||
this.contentType = contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getResult() {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setResult(T result) {
|
|
||||||
this.result = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatus(int status) {
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMessage(String message) {
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user