This commit is contained in:
@@ -304,6 +304,35 @@ public class HttpRequest extends Request<HttpContext> {
|
||||
return array.toString(UTF8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求内容的JavaBean对象
|
||||
*
|
||||
* @param <T> 泛型
|
||||
* @param type 类型
|
||||
*
|
||||
* @return 内容
|
||||
*/
|
||||
public <T> T getBodyJson(java.lang.reflect.Type type) {
|
||||
String str = array.toString(UTF8);
|
||||
if (str == null || str.isEmpty()) return null;
|
||||
return context.getJsonConvert().convertFrom(type, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求内容的JavaBean对象
|
||||
*
|
||||
* @param <T> 泛型
|
||||
* @param convert JsonConvert
|
||||
* @param type 类型
|
||||
*
|
||||
* @return 内容
|
||||
*/
|
||||
public <T> T getBodyJson(JsonConvert convert, java.lang.reflect.Type type) {
|
||||
String str = array.toString(UTF8);
|
||||
if (str == null || str.isEmpty()) return null;
|
||||
return convert.convertFrom(type, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求内容的byte[]
|
||||
*
|
||||
|
||||
@@ -115,6 +115,7 @@ public final class Rest {
|
||||
final String webServletDesc = Type.getDescriptor(WebServlet.class);
|
||||
final String reqDesc = Type.getDescriptor(HttpRequest.class);
|
||||
final String respDesc = Type.getDescriptor(HttpResponse.class);
|
||||
final String contextDesc = Type.getDescriptor(HttpContext.class);
|
||||
final String retDesc = Type.getDescriptor(RetResult.class);
|
||||
final String futureDesc = Type.getDescriptor(CompletableFuture.class);
|
||||
final String flipperDesc = Type.getDescriptor(Flipper.class);
|
||||
@@ -129,6 +130,7 @@ public final class Rest {
|
||||
|
||||
final String reqInternalName = Type.getInternalName(HttpRequest.class);
|
||||
final String respInternalName = Type.getInternalName(HttpResponse.class);
|
||||
final String contextInternalName = Type.getInternalName(HttpContext.class);
|
||||
final String attrInternalName = Type.getInternalName(org.redkale.util.Attribute.class);
|
||||
final String retInternalName = Type.getInternalName(RetResult.class);
|
||||
final String serviceTypeInternalName = Type.getInternalName(serviceType);
|
||||
@@ -256,6 +258,8 @@ public final class Rest {
|
||||
|
||||
//将每个Service可转换的方法生成HttpServlet对应的HttpMapping方法
|
||||
final Map<String, List<String>> asmParamMap = MethodParamClassVisitor.getMethodParamNames(serviceType);
|
||||
final Map<String, java.lang.reflect.Type> bodyTypes = new HashMap<>();
|
||||
|
||||
for (final MappingEntry entry : entrys) {
|
||||
final Method method = entry.mappingMethod;
|
||||
final Class returnType = method.getReturnType();
|
||||
@@ -350,7 +354,7 @@ public final class Rest {
|
||||
if (anncookie != null) throw new RuntimeException("@RestBody and @RestCookie cannot on the same Parameter in " + method);
|
||||
if (annsid != null) throw new RuntimeException("@RestBody and @RestSessionid cannot on the same Parameter in " + method);
|
||||
if (annaddr != null) throw new RuntimeException("@RestBody and @RestAddress cannot on the same Parameter in " + method);
|
||||
if (ptype != String.class && ptype != byte[].class) throw new RuntimeException("@RestBody must on String or byte[] Parameter in " + method);
|
||||
if (ptype.isPrimitive()) throw new RuntimeException("@RestBody cannot on primitive type Parameter in " + method);
|
||||
}
|
||||
|
||||
RestParam annpara = param.getAnnotation(RestParam.class);
|
||||
@@ -373,7 +377,7 @@ public final class Rest {
|
||||
&& (entry.name.startsWith("find") || entry.name.startsWith("delete")) && params.length == 1) {
|
||||
if (ptype.isPrimitive() || ptype == String.class) n = "#";
|
||||
}
|
||||
paramlist.add(new Object[]{param, n, ptype, radix, comment, required, annpara, annsid, annaddr, annhead, anncookie, annbody});
|
||||
paramlist.add(new Object[]{param, n, ptype, radix, comment, required, annpara, annsid, annaddr, annhead, anncookie, annbody, param.getParameterizedType()});
|
||||
}
|
||||
|
||||
Map<String, Object> mappingMap = new LinkedHashMap<>();
|
||||
@@ -415,7 +419,7 @@ public final class Rest {
|
||||
av0 = mv.visitAnnotation(webparamsDesc, true);
|
||||
AnnotationVisitor av1 = av0.visitArray("value");
|
||||
//设置 WebParam
|
||||
for (Object[] ps : paramlist) { //{param, n, ptype, radix, comment, required, annpara, annsid, annaddr, annhead, anncookie, annbody}
|
||||
for (Object[] ps : paramlist) { //{param, n, ptype, radix, comment, required, annpara, annsid, annaddr, annhead, anncookie, annbody, pgentype}
|
||||
final boolean ishead = ((RestHeader) ps[9]) != null; //是否取getHeader 而不是 getParameter
|
||||
final boolean iscookie = ((RestCookie) ps[10]) != null; //是否取getCookie
|
||||
|
||||
@@ -449,6 +453,7 @@ public final class Rest {
|
||||
RestHeader annhead = (RestHeader) ps[9];
|
||||
RestCookie anncookie = (RestCookie) ps[10];
|
||||
RestBody annbody = (RestBody) ps[11];
|
||||
java.lang.reflect.Type pgentype = (java.lang.reflect.Type) ps[12];
|
||||
|
||||
final boolean ishead = annhead != null; //是否取getHeader 而不是 getParameter
|
||||
final boolean iscookie = anncookie != null; //是否取getCookie
|
||||
@@ -488,11 +493,21 @@ public final class Rest {
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBodyUTF8", "()Ljava/lang/String;", false);
|
||||
mv.visitVarInsn(ASTORE, maxLocals);
|
||||
varInsns.add(new int[]{ALOAD, maxLocals});
|
||||
} else {
|
||||
} else if (ptype == byte[].class) {
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBody", "()[B", false);
|
||||
mv.visitVarInsn(ASTORE, maxLocals);
|
||||
varInsns.add(new int[]{ALOAD, maxLocals});
|
||||
} else { //JavaBean 转 Json
|
||||
String typefieldname = "_redkale_body_jsontype_" + bodyTypes.size();
|
||||
bodyTypes.put(typefieldname, pgentype);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, typefieldname, "Ljava/lang/reflect/Type;");
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBodyJson", "(Ljava/lang/reflect/Type;)Ljava/lang/Object;", false);
|
||||
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(ptype));
|
||||
mv.visitVarInsn(ASTORE, maxLocals);
|
||||
varInsns.add(new int[]{ALOAD, maxLocals});
|
||||
}
|
||||
} else if ("#".equals(pname)) { //从request.getRequstURI 中取参数
|
||||
if (ptype == boolean.class) {
|
||||
@@ -771,12 +786,12 @@ public final class Rest {
|
||||
RestSessionid rs = field.getAnnotation(RestSessionid.class);
|
||||
RestAddress ra = field.getAnnotation(RestAddress.class);
|
||||
RestBody rb = field.getAnnotation(RestBody.class);
|
||||
if (rh == null && rc == null && ra == null) continue;
|
||||
if (rh == null && rc == null && ra == null && rb == 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 (rs != null && field.getType() != String.class) throw new RuntimeException("@RestSessionid must on String Field in " + field);
|
||||
if (ra != null && field.getType() != String.class) throw new RuntimeException("@RestAddress must on String Field in " + field);
|
||||
if (rb != null && field.getType() != String.class && field.getType() != byte[].class) throw new RuntimeException("@RestAddress must on String or byte[] Field in " + field);
|
||||
if (rb != null && field.getType().isPrimitive()) throw new RuntimeException("@RestBody must on cannot on primitive type Field in " + field);
|
||||
org.redkale.util.Attribute attr = org.redkale.util.Attribute.create(loop, field);
|
||||
String attrFieldName;
|
||||
String restname = "";
|
||||
@@ -798,11 +813,14 @@ public final class Rest {
|
||||
} else if (rb != null && field.getType() == byte[].class) {
|
||||
attrFieldName = "_redkale_attr_bodybytes_" + restAttributes.size();
|
||||
//restname = "";
|
||||
} else if (rb != null && field.getType() != String.class && field.getType() != byte[].class) {
|
||||
attrFieldName = "_redkale_attr_bodyjson_" + restAttributes.size();
|
||||
//restname = "";
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
restAttributes.put(attrFieldName, attr);
|
||||
attrParaNames.put(attrFieldName, new Object[]{restname, field.getType()});
|
||||
attrParaNames.put(attrFieldName, new Object[]{restname, field.getType(), field.getGenericType()});
|
||||
fields.add(field.getName());
|
||||
}
|
||||
} while ((loop = loop.getSuperclass()) != Object.class);
|
||||
@@ -833,6 +851,13 @@ public final class Rest {
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBodyUTF8", "()Ljava/lang/String;", false);
|
||||
} else if (en.getKey().contains("_bodybytes_")) {
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBody", "()[B", false);
|
||||
} else if (en.getKey().contains("_bodyjson_")) {//JavaBean 转 Json
|
||||
String typefieldname = "_redkale_body_jsontype_" + bodyTypes.size();
|
||||
bodyTypes.put(typefieldname, (java.lang.reflect.Type) en.getValue()[2]);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, typefieldname, "Ljava/lang/reflect/Type;");
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBodyJson", "(Ljava/lang/reflect/Type;)Ljava/lang/Object;", false);
|
||||
mv.visitTypeInsn(CHECKCAST, Type.getInternalName((Class) en.getValue()[1]));
|
||||
}
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, attrInternalName, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", true);
|
||||
}
|
||||
@@ -978,6 +1003,11 @@ public final class Rest {
|
||||
mappingMaps.add(mappingMap);
|
||||
} // end for each
|
||||
|
||||
for (Map.Entry<String, java.lang.reflect.Type> en : bodyTypes.entrySet()) {
|
||||
fv = cw.visitField(ACC_PRIVATE, en.getKey(), "Ljava/lang/reflect/Type;", null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
|
||||
for (String attrname : restAttributes.keySet()) {
|
||||
fv = cw.visitField(ACC_PRIVATE, attrname, attrDesc, null, null);
|
||||
fv.visitEnd();
|
||||
@@ -1008,6 +1038,11 @@ public final class Rest {
|
||||
attrField.setAccessible(true);
|
||||
attrField.set(obj, en.getValue());
|
||||
}
|
||||
for (Map.Entry<String, java.lang.reflect.Type> en : bodyTypes.entrySet()) {
|
||||
Field genField = newClazz.getDeclaredField(en.getKey());
|
||||
genField.setAccessible(true);
|
||||
genField.set(obj, en.getValue());
|
||||
}
|
||||
Field typesfield = newClazz.getDeclaredField(REST_PARAMTYPES_FIELD_NAME);
|
||||
typesfield.setAccessible(true);
|
||||
java.lang.reflect.Type[][] paramtypeArray = new java.lang.reflect.Type[paramtypes.size()][];
|
||||
|
||||
26
test/org/redkale/test/rest/HelloAsyncHandler.java
Normal file
26
test/org/redkale/test/rest/HelloAsyncHandler.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.test.rest;
|
||||
|
||||
import org.redkale.util.AsyncHandler;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class HelloAsyncHandler implements AsyncHandler {
|
||||
|
||||
@Override
|
||||
public void completed(Object result, Object attachment) {
|
||||
System.out.println("-----HelloAsyncHandler--------result : " + result + ", attachment: " + attachment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable exc, Object attachment) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.redkale.test.rest;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.persistence.Id;
|
||||
import org.redkale.convert.json.JsonFactory;
|
||||
import org.redkale.net.http.*;
|
||||
@@ -28,9 +29,19 @@ public class HelloEntity {
|
||||
@RestBody
|
||||
private byte[] bodys;
|
||||
|
||||
@RestBody
|
||||
private Map<String, String> bodymap;
|
||||
|
||||
@RestAddress
|
||||
private String clientaddr;
|
||||
|
||||
public HelloEntity() {
|
||||
}
|
||||
|
||||
public HelloEntity(int id) {
|
||||
this.helloid = id;
|
||||
}
|
||||
|
||||
/** 以下省略getter setter方法 */
|
||||
public int getHelloid() {
|
||||
return helloid;
|
||||
@@ -104,6 +115,14 @@ public class HelloEntity {
|
||||
this.bodys = bodys;
|
||||
}
|
||||
|
||||
public Map<String, String> getBodymap() {
|
||||
return bodymap;
|
||||
}
|
||||
|
||||
public void setBodymap(Map<String, String> bodymap) {
|
||||
this.bodymap = bodymap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonFactory.root().getConvert().convertTo(this);
|
||||
|
||||
@@ -34,10 +34,11 @@ public class HelloService implements Service {
|
||||
}
|
||||
|
||||
//增加记录
|
||||
public RetResult<HelloEntity> createHello(UserInfo info, HelloEntity entity) {
|
||||
public RetResult<HelloEntity> createHello(UserInfo info, HelloEntity entity, @RestBody Map<String, String> body) {
|
||||
System.out.println("增加记录----------------" + nodeid + ": body =" + body + ", entity =" + entity);
|
||||
entity.setCreator(info == null ? 0 : info.getUserid()); //设置当前用户ID
|
||||
entity.setCreatetime(System.currentTimeMillis());
|
||||
source.insert(entity);
|
||||
if (source != null) source.insert(entity);
|
||||
return new RetResult<>(entity);
|
||||
}
|
||||
|
||||
@@ -88,7 +89,24 @@ public class HelloService implements Service {
|
||||
//异步查询单个
|
||||
@RestMapping(name = "asyncfind")
|
||||
public CompletableFuture<HelloEntity> asyncFindHello(@RestParam(name = "#") int id) { //通过 /pipes/hello/find/1234、/pipes/hello/jsfind/1234 查询对象
|
||||
if (source != null) source.findAsync(HelloEntity.class, id);
|
||||
if (source != null) source.findAsync(HelloEntity.class, id);
|
||||
System.out.println("------------进入asyncfind1-------");
|
||||
return CompletableFuture.completedFuture(new HelloEntity());
|
||||
}
|
||||
|
||||
//异步查询单个
|
||||
@RestMapping(name = "asyncfind2")
|
||||
public void asyncFindHello(AsyncHandler hander, @RestParam(name = "#") int id) { //通过 /pipes/hello/find/1234、/pipes/hello/jsfind/1234 查询对象
|
||||
if (source != null) source.findAsync(HelloEntity.class, id);
|
||||
System.out.println("-----------进入asyncfind2--------" + hander);
|
||||
hander.completed(new HelloEntity(id), id);
|
||||
}
|
||||
|
||||
//异步查询单个
|
||||
@RestMapping(name = "asyncfind3")
|
||||
public void asyncFindHello(HelloAsyncHandler hander, @RestParam(name = "#") int id) { //通过 /pipes/hello/find/1234、/pipes/hello/jsfind/1234 查询对象
|
||||
if (source != null) source.findAsync(HelloEntity.class, id);
|
||||
System.out.println("-----------进入asyncfind3--------" + hander);
|
||||
hander.completed(new HelloEntity(id), id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,16 @@ public class _DynHelloRestServlet1 extends SimpleRestServlet {
|
||||
url = "http://127.0.0.1:" + port + "/pipes/hello/listmap?map={'a':5}";
|
||||
System.out.println("listmap: " + Utility.postHttpContent(url, headers, null));
|
||||
|
||||
url = "http://127.0.0.1:" + port + "/pipes/hello/create?entity={}";
|
||||
System.out.println("增加记录: " + Utility.postHttpContent(url, headers, "{'a':2,'b':3}"));
|
||||
|
||||
url = "http://127.0.0.1:" + port + "/pipes/hello/asyncfind/111111";
|
||||
System.out.println("listmap: " + Utility.postHttpContent(url, headers, null));
|
||||
url = "http://127.0.0.1:" + port + "/pipes/hello/asyncfind2/22222";
|
||||
System.out.println("listmap: " + Utility.postHttpContent(url, headers, null));
|
||||
url = "http://127.0.0.1:" + port + "/pipes/hello/asyncfind3/333333";
|
||||
System.out.println("listmap: " + Utility.postHttpContent(url, headers, null));
|
||||
|
||||
}
|
||||
|
||||
@AuthIgnore
|
||||
@@ -55,7 +65,7 @@ public class _DynHelloRestServlet1 extends SimpleRestServlet {
|
||||
bean.setClientaddr(req.getRemoteAddr());
|
||||
bean.setResname(req.getHeader("hello-res"));
|
||||
UserInfo user = currentUser(req);
|
||||
RetResult<HelloEntity> result = service.createHello(user, bean);
|
||||
RetResult<HelloEntity> result = service.createHello(user, bean, req.getBodyJson(Map.class));
|
||||
resp.finishJson(result);
|
||||
}
|
||||
|
||||
@@ -135,4 +145,20 @@ public class _DynHelloRestServlet1 extends SimpleRestServlet {
|
||||
int id = Integer.parseInt(req.getRequstURILastPath());
|
||||
resp.finishJson(service.asyncFindHello(id));
|
||||
}
|
||||
|
||||
@AuthIgnore
|
||||
@HttpMapping(url = "/hello/asyncfind2/")
|
||||
public void asyncfind2(HttpRequest req, HttpResponse resp) throws IOException {
|
||||
HelloService service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
|
||||
int id = Integer.parseInt(req.getRequstURILastPath());
|
||||
service.asyncFindHello(resp.createAsyncHandler(), id);
|
||||
}
|
||||
|
||||
@AuthIgnore
|
||||
@HttpMapping(url = "/hello/asyncfind3/")
|
||||
public void asyncfind3(HttpRequest req, HttpResponse resp) throws IOException {
|
||||
HelloService service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
|
||||
int id = Integer.parseInt(req.getRequstURILastPath());
|
||||
service.asyncFindHello(resp.createAsyncHandler(HelloAsyncHandler.class), id);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user