This commit is contained in:
Redkale
2017-05-12 21:30:18 +08:00
parent 83680c46e8
commit 225745a282
6 changed files with 164 additions and 11 deletions

View File

@@ -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[]
*

View File

@@ -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()][];

View 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.
}
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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);
}
}