This commit is contained in:
@@ -56,6 +56,7 @@ public final class Rest {
|
|||||||
final String webServletDesc = Type.getDescriptor(WebServlet.class);
|
final String webServletDesc = Type.getDescriptor(WebServlet.class);
|
||||||
final String httpRequestDesc = Type.getDescriptor(HttpRequest.class);
|
final String httpRequestDesc = Type.getDescriptor(HttpRequest.class);
|
||||||
final String httpResponseDesc = Type.getDescriptor(HttpResponse.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 authDesc = Type.getDescriptor(HttpBaseServlet.AuthIgnore.class);
|
||||||
final String actionDesc = Type.getDescriptor(HttpBaseServlet.WebAction.class);
|
final String actionDesc = Type.getDescriptor(HttpBaseServlet.WebAction.class);
|
||||||
final String serviceTypeString = serviceType.getName().replace('.', '/');
|
final String serviceTypeString = serviceType.getName().replace('.', '/');
|
||||||
@@ -135,6 +136,7 @@ public final class Rest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final List<MappingEntry> entrys = new ArrayList<>();
|
final List<MappingEntry> entrys = new ArrayList<>();
|
||||||
|
final Map<String, org.redkale.util.Attribute> restAttributes = new LinkedHashMap<>();
|
||||||
|
|
||||||
for (final Method method : serviceType.getMethods()) {
|
for (final Method method : serviceType.getMethods()) {
|
||||||
Class[] extypes = method.getExceptionTypes();
|
Class[] extypes = method.getExceptionTypes();
|
||||||
@@ -407,6 +409,68 @@ public final class Rest {
|
|||||||
mv.visitTypeInsn(CHECKCAST, ptype.getName().replace('.', '/'));
|
mv.visitTypeInsn(CHECKCAST, ptype.getName().replace('.', '/'));
|
||||||
mv.visitVarInsn(ASTORE, maxLocals);
|
mv.visitVarInsn(ASTORE, maxLocals);
|
||||||
varInsns.add(new int[]{ALOAD, 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++;
|
maxLocals++;
|
||||||
paramMaps.add(paramMap);
|
paramMaps.add(paramMap);
|
||||||
@@ -672,6 +736,12 @@ public final class Rest {
|
|||||||
actionMap.put("params", paramMaps);
|
actionMap.put("params", paramMaps);
|
||||||
actionMaps.add(actionMap);
|
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);
|
classMap.put("actions", actionMaps);
|
||||||
|
|
||||||
{ //toString函数
|
{ //toString函数
|
||||||
@@ -691,7 +761,13 @@ public final class Rest {
|
|||||||
}
|
}
|
||||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
}.loadClass(newDynName.replace('/', '.'), bytes);
|
||||||
try {
|
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) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import static java.lang.annotation.ElementType.*;
|
|||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 只能注解于Service类的方法的参数或参数内的字段
|
* 只能注解于Service类的方法的参数或参数内的String字段
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: http://redkale.org
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ import org.redkale.util.Attribute;
|
|||||||
*/
|
*/
|
||||||
public abstract class RestHttpServlet<T> extends HttpBaseServlet {
|
public abstract class RestHttpServlet<T> extends HttpBaseServlet {
|
||||||
|
|
||||||
Attribute[] _paramAttrs; // 为null表示无DynCall处理,index=0固定为null, 其他为参数标记的DynCall回调方法
|
|
||||||
|
|
||||||
protected abstract T currentUser(HttpRequest req) throws IOException;
|
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) {
|
protected void _callParameter(final HttpResponse response, final Object... params) {
|
||||||
if (_paramAttrs == null) return;
|
if (_paramAttrs == null) return;
|
||||||
for (int i = 1; i < _paramAttrs.length; i++) {
|
for (int i = 1; i < _paramAttrs.length; i++) {
|
||||||
|
|||||||
@@ -82,6 +82,25 @@ public class AsmMethodVisitor {
|
|||||||
if (debug) System.out.println("mv.visitVarInsn(" + opcodes[opcode] + ", " + var + ");");
|
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 构建
|
public void visitJumpInsn(int opcode, Label var) { //调用此方法的 ClassWriter 必须由 COMPUTE_FRAMES 构建
|
||||||
visitor.visitJumpInsn(opcode, var);
|
visitor.visitJumpInsn(opcode, var);
|
||||||
if (debug) {
|
if (debug) {
|
||||||
|
|||||||
@@ -421,6 +421,8 @@ public interface Attribute<T, F> {
|
|||||||
column = tgetter.getReturnType();
|
column = tgetter.getReturnType();
|
||||||
} else if (tsetter != null) {
|
} else if (tsetter != null) {
|
||||||
column = tsetter.getParameterTypes()[0];
|
column = tsetter.getParameterTypes()[0];
|
||||||
|
} else if (fieldtype == null) {
|
||||||
|
throw new RuntimeException("[" + clazz + "]have no public field or setter or getter");
|
||||||
}
|
}
|
||||||
final Class pcolumn = column;
|
final Class pcolumn = column;
|
||||||
if (column.isPrimitive()) column = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(column, 1), 0).getClass();
|
if (column.isPrimitive()) column = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(column, 1), 0).getClass();
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
package org.redkale.test.rest;
|
package org.redkale.test.rest;
|
||||||
|
|
||||||
import org.redkale.convert.json.JsonFactory;
|
import org.redkale.convert.json.JsonFactory;
|
||||||
|
import org.redkale.net.http.*;
|
||||||
import org.redkale.source.FilterBean;
|
import org.redkale.source.FilterBean;
|
||||||
|
|
||||||
public class HelloBean implements FilterBean {
|
public class HelloBean implements FilterBean {
|
||||||
|
|
||||||
private int helloid;
|
private int helloid;
|
||||||
|
|
||||||
|
@RestHeader("hello-res")
|
||||||
|
private String res;
|
||||||
|
|
||||||
public int getHelloid() {
|
public int getHelloid() {
|
||||||
return helloid;
|
return helloid;
|
||||||
}
|
}
|
||||||
@@ -15,8 +19,17 @@ public class HelloBean implements FilterBean {
|
|||||||
this.helloid = helloid;
|
this.helloid = helloid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRes() {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRes(String res) {
|
||||||
|
this.res = res;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return JsonFactory.root().getConvert().convertTo(this);
|
return JsonFactory.root().getConvert().convertTo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ package org.redkale.test.rest;
|
|||||||
|
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import org.redkale.convert.json.JsonFactory;
|
import org.redkale.convert.json.JsonFactory;
|
||||||
|
import org.redkale.net.http.*;
|
||||||
|
import org.redkale.source.VirtualEntity;
|
||||||
|
|
||||||
|
@VirtualEntity
|
||||||
public class HelloEntity {
|
public class HelloEntity {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@@ -16,6 +19,12 @@ public class HelloEntity {
|
|||||||
|
|
||||||
private long createtime;
|
private long createtime;
|
||||||
|
|
||||||
|
@RestHeader("hello-res")
|
||||||
|
private String resname;
|
||||||
|
|
||||||
|
@RestAddress
|
||||||
|
private String clientaddr;
|
||||||
|
|
||||||
public int getHelloid() {
|
public int getHelloid() {
|
||||||
return helloid;
|
return helloid;
|
||||||
}
|
}
|
||||||
@@ -56,6 +65,22 @@ public class HelloEntity {
|
|||||||
this.creator = creator;
|
this.creator = creator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getClientaddr() {
|
||||||
|
return clientaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientaddr(String clientaddr) {
|
||||||
|
this.clientaddr = clientaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResname() {
|
||||||
|
return resname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResname(String resname) {
|
||||||
|
this.resname = resname;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return JsonFactory.root().getConvert().convertTo(this);
|
return JsonFactory.root().getConvert().convertTo(this);
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import org.redkale.source.DataSource;
|
|||||||
import org.redkale.source.Flipper;
|
import org.redkale.source.Flipper;
|
||||||
import org.redkale.util.Sheet;
|
import org.redkale.util.Sheet;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 类说明:
|
* 类说明:
|
||||||
* Flipper : Source组件中的翻页对象
|
* Flipper : Source组件中的翻页对象
|
||||||
@@ -37,9 +36,10 @@ public class HelloService implements Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//修改记录
|
//修改记录
|
||||||
public void updateHello(HelloEntity entity) { //通过 /hello/update?bean={...} 修改对象
|
public void updateHello(@RestAddress String clientAddr, HelloEntity entity) { //通过 /hello/update?bean={...} 修改对象
|
||||||
entity.setUpdatetime(System.currentTimeMillis());
|
System.out.println("修改记录: clientAddr = " + clientAddr + ", entity =" + entity);
|
||||||
source.update(entity);
|
if (entity != null) entity.setUpdatetime(System.currentTimeMillis());
|
||||||
|
if (source != null) source.update(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
//修改记录
|
//修改记录
|
||||||
|
|||||||
@@ -15,16 +15,13 @@ import org.redkale.service.*;
|
|||||||
*/
|
*/
|
||||||
public abstract class RetCodes {
|
public abstract class RetCodes {
|
||||||
|
|
||||||
static {
|
protected static final Map<Integer, String> rets = new HashMap<>();
|
||||||
load(RetCodes.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected RetCodes() {
|
protected RetCodes() {
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
protected static final Map<Integer, String> rets = new HashMap<>();
|
|
||||||
|
|
||||||
protected static void load(Class clazz) {
|
protected static void load(Class clazz) {
|
||||||
for (Field field : clazz.getFields()) {
|
for (Field field : clazz.getFields()) {
|
||||||
if (!Modifier.isStatic(field.getModifiers())) continue;
|
if (!Modifier.isStatic(field.getModifiers())) continue;
|
||||||
@@ -158,4 +155,9 @@ public abstract class RetCodes {
|
|||||||
|
|
||||||
@RetLabel("用户设备ID无效")
|
@RetLabel("用户设备ID无效")
|
||||||
public static final int RET_USER_APPTOKEN_ILLEGAL = 30020030;
|
public static final int RET_USER_APPTOKEN_ILLEGAL = 30020030;
|
||||||
|
|
||||||
|
|
||||||
|
static {
|
||||||
|
load(RetCodes.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,45 @@
|
|||||||
package org.redkale.test.rest;
|
package org.redkale.test.rest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.*;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import org.redkale.net.http.*;
|
import org.redkale.net.http.*;
|
||||||
import org.redkale.service.RetResult;
|
import org.redkale.service.RetResult;
|
||||||
import org.redkale.source.Flipper;
|
import org.redkale.source.Flipper;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
import org.redkale.util.AnyValue.DefaultAnyValue;
|
||||||
|
|
||||||
@WebServlet(value = {"/hello/*"}, repair = true)
|
@WebServlet(value = {"/hello/*"}, repair = true)
|
||||||
public class _DynHelloRestServlet extends SimpleRestServlet {
|
public class _DynHelloRestServlet1 extends SimpleRestServlet {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private HelloService _service;
|
private HelloService _service;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Throwable {
|
||||||
|
final int port = 8888;
|
||||||
|
HelloService service = new HelloService();
|
||||||
|
HttpServer server = new HttpServer();
|
||||||
|
RestHttpServlet servlet = Rest.createRestServlet(SimpleRestServlet.class, "", HelloService.class, false);
|
||||||
|
Field field = servlet.getClass().getDeclaredField("_service");
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(servlet, service);
|
||||||
|
server.addHttpServlet(servlet, "/pipes", null, "/hello/*");
|
||||||
|
|
||||||
|
DefaultAnyValue conf = DefaultAnyValue.create("port", "" + port);
|
||||||
|
server.init(conf);
|
||||||
|
server.start();
|
||||||
|
Thread.sleep(100);
|
||||||
|
|
||||||
|
HelloEntity entity = new HelloEntity();
|
||||||
|
entity.setHelloname("my name");
|
||||||
|
Map<String, String> headers = new HashMap<>();
|
||||||
|
headers.put("hello-res", "my res");
|
||||||
|
String url = "http://127.0.0.1:" + port + "/pipes/hello/update?entity={}&bean2={}";
|
||||||
|
System.out.println(Utility.postHttpContent(url, headers, null));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@AuthIgnore
|
@AuthIgnore
|
||||||
@WebAction(url = "/hello/create")
|
@WebAction(url = "/hello/create")
|
||||||
public void create(HttpRequest req, HttpResponse resp) throws IOException {
|
public void create(HttpRequest req, HttpResponse resp) throws IOException {
|
||||||
@@ -34,8 +60,9 @@ public class _DynHelloRestServlet extends SimpleRestServlet {
|
|||||||
@AuthIgnore
|
@AuthIgnore
|
||||||
@WebAction(url = "/hello/update")
|
@WebAction(url = "/hello/update")
|
||||||
public void update(HttpRequest req, HttpResponse resp) throws IOException {
|
public void update(HttpRequest req, HttpResponse resp) throws IOException {
|
||||||
|
String clientaddr = req.getRemoteAddr();
|
||||||
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
|
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
|
||||||
_service.updateHello(bean);
|
_service.updateHello(clientaddr, bean);
|
||||||
resp.finishJson(RetResult.success());
|
resp.finishJson(RetResult.success());
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user