This commit is contained in:
Redkale
2016-08-29 17:21:02 +08:00
parent 9f5ab4b068
commit e8e6459679
10 changed files with 188 additions and 24 deletions

View File

@@ -56,6 +56,7 @@ public final class Rest {
final String webServletDesc = Type.getDescriptor(WebServlet.class);
final String httpRequestDesc = Type.getDescriptor(HttpRequest.class);
final String httpResponseDesc = Type.getDescriptor(HttpResponse.class);
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 serviceTypeString = serviceType.getName().replace('.', '/');
@@ -135,6 +136,7 @@ public final class Rest {
}
final List<MappingEntry> entrys = new ArrayList<>();
final Map<String, org.redkale.util.Attribute> restAttributes = new LinkedHashMap<>();
for (final Method method : serviceType.getMethods()) {
Class[] extypes = method.getExceptionTypes();
@@ -407,6 +409,68 @@ public final class Rest {
mv.visitTypeInsn(CHECKCAST, ptype.getName().replace('.', '/'));
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[]{ALOAD, maxLocals});
//构建 RestHeader、RestCookie、RestAddress 等赋值操作
Class loop = ptype;
Set<String> fields = new HashSet<>();
Map<String, String> attrParaNames = new LinkedHashMap<>();
do {
for (Field field : loop.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())) continue;
if (Modifier.isFinal(field.getModifiers())) continue;
if (fields.contains(field.getName())) continue;
RestHeader rh = field.getAnnotation(RestHeader.class);
RestCookie rc = field.getAnnotation(RestCookie.class);
RestAddress ra = field.getAnnotation(RestAddress.class);
if (rh == null && rc == null && ra == null) continue;
if (rh != null && field.getType() != String.class) throw new RuntimeException("@RestHeader must on String Field in " + field);
if (rc != null && field.getType() != String.class) throw new RuntimeException("@RestCookie must on String Field in " + field);
if (ra != null && field.getType() != String.class) throw new RuntimeException("@RestAddress must on String Field in " + field);
org.redkale.util.Attribute attr = org.redkale.util.Attribute.create(loop, field);
String attrFieldName;
String restname = "";
if (rh != null) {
attrFieldName = "_redkale_attr_header_" + restAttributes.size();
restname = rh.value();
} else if (rc != null) {
attrFieldName = "_redkale_attr_cookie_" + restAttributes.size();
restname = rc.value();
} else if (ra != null) {
attrFieldName = "_redkale_attr_address_" + restAttributes.size();
} else {
continue;
}
restAttributes.put(attrFieldName, attr);
attrParaNames.put(attrFieldName, restname);
fields.add(field.getName());
}
} while ((loop = loop.getSuperclass()) != Object.class);
if (!attrParaNames.isEmpty()) { //参数存在 RestHeader、RestCookie、RestAddress字段
mv.visitVarInsn(ALOAD, maxLocals);
Label lif = new Label();
mv.visitJumpInsn(IFNULL, lif); //if(bean != null) {
for (Map.Entry<String, String> en : attrParaNames.entrySet()) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, en.getKey(), attrDesc);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitVarInsn(ALOAD, 1);
if (en.getKey().contains("_header_")) {
mv.visitLdcInsn(en.getValue());
mv.visitLdcInsn("");
mv.visitMethodInsn(INVOKEVIRTUAL, "org/redkale/net/http/HttpRequest", "getHeader", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
} else if (en.getKey().contains("_cookie_")) {
mv.visitLdcInsn(en.getValue());
mv.visitLdcInsn("");
mv.visitMethodInsn(INVOKEVIRTUAL, "org/redkale/net/http/HttpRequest", "getCookie", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
} else if (en.getKey().contains("_address_")) {
mv.visitMethodInsn(INVOKEVIRTUAL, "org/redkale/net/http/HttpRequest", "getRemoteAddr", "()Ljava/lang/String;", false);
}
mv.visitMethodInsn(INVOKEINTERFACE, "org/redkale/util/Attribute", "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", true);
}
mv.visitLabel(lif); // end if }
mv.visitFrame(Opcodes.F_APPEND, 1, new Object[]{ptype.getName().replace('.', '/')}, 0, null);
}
}
maxLocals++;
paramMaps.add(paramMap);
@@ -671,7 +735,13 @@ public final class Rest {
mv.visitMaxs(maxStack, maxLocals);
actionMap.put("params", paramMaps);
actionMaps.add(actionMap);
} // end for each
} // end for each
for (String attrname : restAttributes.keySet()) {
fv = cw.visitField(ACC_PRIVATE, attrname, attrDesc, null, null);
fv.visitEnd();
}
classMap.put("actions", actionMaps);
{ //toString函数
@@ -691,7 +761,13 @@ public final class Rest {
}
}.loadClass(newDynName.replace('/', '.'), bytes);
try {
return ((Class<T>) newClazz).newInstance();
T obj = ((Class<T>) newClazz).newInstance();
for (Map.Entry<String, org.redkale.util.Attribute> en : restAttributes.entrySet()) {
Field attrField = newClazz.getDeclaredField(en.getKey());
attrField.setAccessible(true);
attrField.set(obj, en.getValue());
}
return obj;
} catch (Exception e) {
throw new RuntimeException(e);
}

View File

@@ -10,7 +10,7 @@ import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 只能注解于Service类的方法的参数或参数内的字段
* 只能注解于Service类的方法的参数或参数内的String字段
* <p>
* 详情见: http://redkale.org
*

View File

@@ -17,16 +17,16 @@ import org.redkale.util.Attribute;
*/
public abstract class RestHttpServlet<T> extends HttpBaseServlet {
Attribute[] _paramAttrs; // 为null表示无DynCall处理index=0固定为null, 其他为参数标记的DynCall回调方法
protected abstract T currentUser(HttpRequest req) throws IOException;
Attribute[] _paramAttrs; // 为null表示无DynCall处理index=0固定为null, 其他为参数标记的DynCall回调方法
protected void _callParameter(final HttpResponse response, final Object... params) {
if (_paramAttrs == null) return;
for (int i = 1; i < _paramAttrs.length; i++) {
org.redkale.util.Attribute attr = _paramAttrs[i];
if (attr == null) continue;
//convert.convertTo(out, attr.type(), attr.get(params[i - 1]));
}
}

View File

@@ -82,6 +82,25 @@ public class AsmMethodVisitor {
if (debug) System.out.println("mv.visitVarInsn(" + opcodes[opcode] + ", " + var + ");");
}
public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
visitor.visitFrame(type, nLocal, local, nStack, stack);
if (debug) {
String typestr = "" + type;
if (type == -1) {
typestr = "Opcodes.F_NEW";
} else if (type == 1) {
typestr = "Opcodes.F_APPEND";
} else if (type == 2) {
typestr = "Opcodes.F_CHOP";
} else if (type == 3) {
typestr = "Opcodes.F_SAME";
} else if (type == 4) {
typestr = "Opcodes.F_SAME1";
}
System.out.println("mv.visitFrame(" + typestr + ", " + nLocal + ", " + Arrays.toString(local) + ", " + nStack + ", " + Arrays.toString(stack) + ");");
}
}
public void visitJumpInsn(int opcode, Label var) { //调用此方法的 ClassWriter 必须由 COMPUTE_FRAMES 构建
visitor.visitJumpInsn(opcode, var);
if (debug) {

View File

@@ -44,17 +44,17 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
* public String get(Record obj) {
* return obj.getName();
* }
*
*
* &#64;Override
* public void set(Record obj, String value) {
* obj.setName(value);
* }
*
*
* &#64;Override
* public Class type() {
* return String.class;
* }
*
*
* &#64;Override
* public Class declaringClass() {
* return Record.class;
@@ -421,6 +421,8 @@ public interface Attribute<T, F> {
column = tgetter.getReturnType();
} else if (tsetter != null) {
column = tsetter.getParameterTypes()[0];
} else if (fieldtype == null) {
throw new RuntimeException("[" + clazz + "]have no public field or setter or getter");
}
final Class pcolumn = column;
if (column.isPrimitive()) column = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(column, 1), 0).getClass();