This commit is contained in:
Redkale
2016-09-05 15:07:57 +08:00
parent 90884f4621
commit b49a4d2c83
2 changed files with 112 additions and 49 deletions

View File

@@ -12,7 +12,7 @@ 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.lang.reflect.*;
import java.nio.*;
import java.util.*;
import java.util.concurrent.*;
@@ -51,6 +51,45 @@ public abstract class HttpBaseServlet extends HttpServlet {
}
/**
* 配合 @WebParam 使用。
* 用于对@WebParam中参数的来源类型
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
protected enum ParamSourceType {
PARAMETER, HEADER, COOKIE;
}
/**
* 配合 &#64;WebAction 使用。
* 用于对&#64;WebAction方法中参数描述
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Target({ElementType.ANNOTATION_TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
protected @interface WebParam {
String value(); //参数名
Class type(); //参数的数据类型
String comment() default ""; //备注描述
ParamSourceType src() default ParamSourceType.PARAMETER; //参数来源类型
int radix() default 10; //转换数字byte/short/int/long时所用的进制数 默认10进制
}
/**
* 配合 HttpBaseServlet 使用。
* 用于对&#64;WebServlet对应的url进行细分。 其url必须是包含WebServlet中定义的前缀 且不能是正则表达式
@@ -72,6 +111,8 @@ public abstract class HttpBaseServlet extends HttpServlet {
String[] methods() default {};//允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法
String comment() default ""; //备注描述
WebParam[] params() default {};
}
/**

View File

@@ -65,6 +65,8 @@ public final class Rest {
final String attrDesc = Type.getDescriptor(org.redkale.util.Attribute.class);
final String authDesc = Type.getDescriptor(HttpBaseServlet.AuthIgnore.class);
final String actionDesc = Type.getDescriptor(HttpBaseServlet.WebAction.class);
final String webparamDesc = Type.getDescriptor(HttpBaseServlet.WebParam.class);
final String sourcetypeDesc = Type.getDescriptor(HttpBaseServlet.ParamSourceType.class);
final String serviceTypeString = serviceType.getName().replace('.', '/');
final Class userType = getSuperUserType(baseServletClass);
@@ -215,14 +217,14 @@ public final class Rest {
final int maxStack = 3 + params.length;
List<int[]> varInsns = new ArrayList<>();
int maxLocals = 4;
boolean hasVisitWebAction = false;
final String jsvar = entry.jsvar.isEmpty() ? null : entry.jsvar;
int argIndex = 0;
List<Map<String, Object>> paramMaps = new ArrayList<>();
List<Object[]> paramlist = new ArrayList<>();
for (final Parameter param : params) {
Map<String, Object> paramMap = new LinkedHashMap<>();
final Class ptype = param.getType();
String n = null;
String comment = "";
int radix = 10;
RestHeader annhead = null;
RestCookie anncookie = null;
@@ -232,6 +234,7 @@ public final class Rest {
if (annhead != null) {
n = annhead.value();
radix = annhead.radix();
comment = annhead.comment();
if (n.isEmpty()) throw new RuntimeException("@RestHeader.value is illegal in " + method);
}
anncookie = param.getAnnotation(RestCookie.class);
@@ -240,6 +243,7 @@ public final class Rest {
if (ptype != String.class) throw new RuntimeException("@RestCookie must on String Parameter in " + method);
n = anncookie.value();
radix = anncookie.radix();
comment = anncookie.comment();
if (n.isEmpty()) throw new RuntimeException("@RestCookie.value is illegal in " + method);
}
annaddr = param.getAnnotation(RestAddress.class);
@@ -251,8 +255,9 @@ public final class Rest {
}
RestParam annpara = param.getAnnotation(RestParam.class);
if (annpara != null) radix = annpara.radix();
if (annpara != null) comment = annpara.comment();
if (n == null) n = (annpara == null || annpara.value().isEmpty()) ? null : annpara.value();
if (n == null && ptype == userType) n = "_current_user";
if (n == null && ptype == userType) n = "&"; //用户类型特殊处理
if (n == null) {
if (param.isNamePresent()) {
n = param.getName();
@@ -264,26 +269,64 @@ public final class Rest {
&& (entry.name.startsWith("find") || entry.name.startsWith("delete")) && params.length == 1) {
if (ptype.isPrimitive() || ptype == String.class) n = "#";
}
if (!hasVisitWebAction) {
hasVisitWebAction = true;
//设置 WebAction
av0 = mv.visitAnnotation(actionDesc, true);
String url = "/" + defmodulename.toLowerCase() + "/" + entry.name + ("#".equals(n) ? "/" : "");
av0.visit("url", url);
av0.visit("actionid", entry.actionid);
AnnotationVisitor av1 = av0.visitArray("methods");
for (String m : entry.methods) {
av1.visit(null, m);
paramlist.add(new Object[]{param, n, ptype, radix, comment, annpara, annaddr, annhead, anncookie});
}
{
//设置 WebAction
boolean reqpath = false;
for (Object[] ps : paramlist) {
if ("#".equals((String) ps[1])) {
reqpath = true;
break;
}
av1.visitEnd();
av0.visitEnd();
actionMap.put("url", url);
actionMap.put("actionid", entry.actionid);
actionMap.put("methods", entry.methods);
}
final String pname = n; //参数名
av0 = mv.visitAnnotation(actionDesc, true);
String url = "/" + defmodulename.toLowerCase() + "/" + entry.name + (reqpath ? "/" : "");
av0.visit("url", url);
av0.visit("actionid", entry.actionid);
AnnotationVisitor av1 = av0.visitArray("methods");
for (String m : entry.methods) {
av1.visit(null, m);
}
av1.visitEnd();
{
AnnotationVisitor av3 = av0.visitArray("params");
for (Object[] ps : paramlist) { //{param, n, ptype, radix, comment, annpara, annaddr, annhead, anncookie}
final boolean ishead = ((RestHeader) ps[7]) != null; //是否取getHeader 而不是 getParameter
final boolean iscookie = ((RestCookie) ps[8]) != null; //是否取getCookie
AnnotationVisitor av2 = av3.visitAnnotation(null, webparamDesc);
av2.visit("value", (String) ps[1]);
av2.visit("type", Type.getType(Type.getDescriptor((Class) ps[2])));
av2.visit("radix", (Integer) ps[3]);
av2.visitEnum("src", sourcetypeDesc, ishead ? HttpBaseServlet.ParamSourceType.HEADER.name()
: (iscookie ? HttpBaseServlet.ParamSourceType.COOKIE.name() : HttpBaseServlet.ParamSourceType.PARAMETER.name()));
av2.visit("comment", (String) ps[4]);
av2.visitEnd();
}
av3.visitEnd();
}
av0.visitEnd();
actionMap.put("url", url);
actionMap.put("actionid", entry.actionid);
actionMap.put("methods", entry.methods);
}
List<Map<String, Object>> paramMaps = new ArrayList<>();
for (Object[] ps : paramlist) {
Map<String, Object> paramMap = new LinkedHashMap<>();
String pname = (String) ps[1]; //参数名
Class ptype = (Class) ps[2];
int radix = (Integer) ps[3];
String comment = (String) ps[4];
RestParam annpara = (RestParam) ps[5];
RestAddress annaddr = (RestAddress) ps[6];
RestHeader annhead = (RestHeader) ps[7];
RestCookie anncookie = (RestCookie) ps[8];
final boolean ishead = annhead != null; //是否取getHeader 而不是 getParameter
final boolean iscookie = anncookie != null; //是否取getCookie
@@ -358,6 +401,12 @@ public final class Rest {
} else {
throw new RuntimeException(method + " only " + RestParam.class.getSimpleName() + "(#) to Type(primitive class or String)");
}
} else if ("&".equals(pname) && ptype == userType) { //当前用户对象的类名
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "currentUser", Type.getMethodDescriptor(currentUserMethod), false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[]{ALOAD, maxLocals});
} else if (ptype == boolean.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname);
@@ -437,12 +486,6 @@ public final class Rest {
//mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "findFlipper", "(Lorg/redkale/net/http/HttpRequest;)Lorg/redkale/source/Flipper;", false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[]{ALOAD, maxLocals});
} else if (ptype == userType) { //当前用户对象的类名
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "currentUser", Type.getMethodDescriptor(currentUserMethod), false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[]{ALOAD, maxLocals});
} else { //其他Json对象
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(Type.getType(Type.getDescriptor(ptype)));
@@ -520,27 +563,6 @@ public final class Rest {
paramMaps.add(paramMap);
} // end params for each
if (!hasVisitWebAction) { //当无参数时则没有设置过 WebAction
hasVisitWebAction = true;
//设置 WebAction
av0 = mv.visitAnnotation(actionDesc, true);
String url = "/" + defmodulename.toLowerCase() + "/" + entry.name;
av0.visit("url", url);
av0.visit("actionid", entry.actionid);
av0.visit("comment", entry.comment);
AnnotationVisitor av1 = av0.visitArray("methods");
for (String m : entry.methods) {
av1.visit(null, m);
}
av1.visitEnd();
av0.visitEnd();
actionMap.put("url", url);
actionMap.put("actionid", entry.actionid);
actionMap.put("methods", entry.methods);
actionMap.put("comment", entry.comment);
}
//mv.visitVarInsn(ALOAD, 0); //调用this
//mv.visitFieldInsn(GETFIELD, newDynName, REST_SERVICE_FIELD_NAME, serviceDesc);
mv.visitVarInsn(ALOAD, 3);