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 java.lang.annotation.*;
import static java.lang.annotation.ElementType.*; import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.reflect.Method; import java.lang.reflect.*;
import java.nio.*; import java.nio.*;
import java.util.*; import java.util.*;
import java.util.concurrent.*; 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 使用。 * 配合 HttpBaseServlet 使用。
* 用于对&#64;WebServlet对应的url进行细分。 其url必须是包含WebServlet中定义的前缀 且不能是正则表达式 * 用于对&#64;WebServlet对应的url进行细分。 其url必须是包含WebServlet中定义的前缀 且不能是正则表达式
@@ -72,6 +111,8 @@ public abstract class HttpBaseServlet extends HttpServlet {
String[] methods() default {};//允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法 String[] methods() default {};//允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法
String comment() default ""; //备注描述 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 attrDesc = Type.getDescriptor(org.redkale.util.Attribute.class);
final String authDesc = Type.getDescriptor(HttpBaseServlet.AuthIgnore.class); final String authDesc = Type.getDescriptor(HttpBaseServlet.AuthIgnore.class);
final String actionDesc = Type.getDescriptor(HttpBaseServlet.WebAction.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 String serviceTypeString = serviceType.getName().replace('.', '/');
final Class userType = getSuperUserType(baseServletClass); final Class userType = getSuperUserType(baseServletClass);
@@ -215,14 +217,14 @@ public final class Rest {
final int maxStack = 3 + params.length; final int maxStack = 3 + params.length;
List<int[]> varInsns = new ArrayList<>(); List<int[]> varInsns = new ArrayList<>();
int maxLocals = 4; int maxLocals = 4;
boolean hasVisitWebAction = false;
final String jsvar = entry.jsvar.isEmpty() ? null : entry.jsvar; final String jsvar = entry.jsvar.isEmpty() ? null : entry.jsvar;
int argIndex = 0; int argIndex = 0;
List<Map<String, Object>> paramMaps = new ArrayList<>();
List<Object[]> paramlist = new ArrayList<>();
for (final Parameter param : params) { for (final Parameter param : params) {
Map<String, Object> paramMap = new LinkedHashMap<>();
final Class ptype = param.getType(); final Class ptype = param.getType();
String n = null; String n = null;
String comment = "";
int radix = 10; int radix = 10;
RestHeader annhead = null; RestHeader annhead = null;
RestCookie anncookie = null; RestCookie anncookie = null;
@@ -232,6 +234,7 @@ public final class Rest {
if (annhead != null) { if (annhead != null) {
n = annhead.value(); n = annhead.value();
radix = annhead.radix(); radix = annhead.radix();
comment = annhead.comment();
if (n.isEmpty()) throw new RuntimeException("@RestHeader.value is illegal in " + method); if (n.isEmpty()) throw new RuntimeException("@RestHeader.value is illegal in " + method);
} }
anncookie = param.getAnnotation(RestCookie.class); 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); if (ptype != String.class) throw new RuntimeException("@RestCookie must on String Parameter in " + method);
n = anncookie.value(); n = anncookie.value();
radix = anncookie.radix(); radix = anncookie.radix();
comment = anncookie.comment();
if (n.isEmpty()) throw new RuntimeException("@RestCookie.value is illegal in " + method); if (n.isEmpty()) throw new RuntimeException("@RestCookie.value is illegal in " + method);
} }
annaddr = param.getAnnotation(RestAddress.class); annaddr = param.getAnnotation(RestAddress.class);
@@ -251,8 +255,9 @@ public final class Rest {
} }
RestParam annpara = param.getAnnotation(RestParam.class); RestParam annpara = param.getAnnotation(RestParam.class);
if (annpara != null) radix = annpara.radix(); 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) 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 (n == null) {
if (param.isNamePresent()) { if (param.isNamePresent()) {
n = param.getName(); n = param.getName();
@@ -264,26 +269,64 @@ public final class Rest {
&& (entry.name.startsWith("find") || entry.name.startsWith("delete")) && params.length == 1) { && (entry.name.startsWith("find") || entry.name.startsWith("delete")) && params.length == 1) {
if (ptype.isPrimitive() || ptype == String.class) n = "#"; 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"); paramlist.add(new Object[]{param, n, ptype, radix, comment, annpara, annaddr, annhead, anncookie});
for (String m : entry.methods) { }
av1.visit(null, m); {
//设置 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 ishead = annhead != null; //是否取getHeader 而不是 getParameter
final boolean iscookie = anncookie != null; //是否取getCookie final boolean iscookie = anncookie != null; //是否取getCookie
@@ -358,6 +401,12 @@ public final class Rest {
} else { } else {
throw new RuntimeException(method + " only " + RestParam.class.getSimpleName() + "(#) to Type(primitive class or String)"); 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) { } else if (ptype == boolean.class) {
mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname); 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.visitMethodInsn(INVOKEVIRTUAL, newDynName, "findFlipper", "(Lorg/redkale/net/http/HttpRequest;)Lorg/redkale/source/Flipper;", false);
mv.visitVarInsn(ASTORE, maxLocals); mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[]{ALOAD, 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对象 } else { //其他Json对象
mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(Type.getType(Type.getDescriptor(ptype))); mv.visitLdcInsn(Type.getType(Type.getDescriptor(ptype)));
@@ -520,27 +563,6 @@ public final class Rest {
paramMaps.add(paramMap); paramMaps.add(paramMap);
} // end params for each } // 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.visitVarInsn(ALOAD, 0); //调用this
//mv.visitFieldInsn(GETFIELD, newDynName, REST_SERVICE_FIELD_NAME, serviceDesc); //mv.visitFieldInsn(GETFIELD, newDynName, REST_SERVICE_FIELD_NAME, serviceDesc);
mv.visitVarInsn(ALOAD, 3); mv.visitVarInsn(ALOAD, 3);