Skip to content

Commit

Permalink
docean supports mvc non-JSON format single-parameter call
Browse files Browse the repository at this point in the history
  • Loading branch information
goodjava committed Feb 27, 2024
1 parent e1f628c commit bbbf3d6
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 32 deletions.
88 changes: 58 additions & 30 deletions jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Mvc.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.xiaomi.youpin.docean.mvc.*;
import com.xiaomi.youpin.docean.mvc.common.MvcConst;
import com.xiaomi.youpin.docean.mvc.util.ExceptionUtil;
import com.xiaomi.youpin.docean.mvc.util.GsonUtils;
import com.xiaomi.youpin.docean.mvc.util.Jump;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.FullHttpRequest;
Expand Down Expand Up @@ -100,33 +101,41 @@ private void initHttpRequestMethod() {
ioc.beans().entrySet().stream().forEach(entry -> {
Bean bean = entry.getValue();
if (bean.getType() == Bean.Type.controller.ordinal()) {
Arrays.stream(bean.getClazz().getMethods()).forEach(m -> Optional.ofNullable(m.getAnnotation(RequestMapping.class)).ifPresent(rm -> {
String path = rm.path();
HttpRequestMethod hrm = new HttpRequestMethod();
hrm.setTimeout(rm.timeout());
hrm.setPath(path);
hrm.setObj(bean.getObj());
hrm.setMethod(m);
hrm.setHttpMethod(rm.method());
ioc.publishEvent(new Event(EventType.initController, path));
requestMethodMap.put(path, hrm);
}));
registerControllerMethods(bean);
}
if (bean.getObj() instanceof MvcServlet) {
MvcServlet ms = (MvcServlet) bean.getObj();
String path = ms.path();
HttpRequestMethod hrm = new HttpRequestMethod();
hrm.setPath(path);
hrm.setObj(ms);
hrm.setHttpMethod(ms.method());
Safe.runAndLog(() -> hrm.setMethod(ms.getClass().getMethod("execute", Object.class)));
ioc.publishEvent(new Event(EventType.initController, path));
requestMethodMap.put(path, hrm);
initializeControllerMapping(bean);
}
});
log.info("requestMethodMap size:{}", this.requestMethodMap.size());
}

private void initializeControllerMapping(Bean bean) {
MvcServlet ms = (MvcServlet) bean.getObj();
String path = ms.path();
HttpRequestMethod hrm = new HttpRequestMethod();
hrm.setPath(path);
hrm.setObj(ms);
hrm.setHttpMethod(ms.method());
Safe.runAndLog(() -> hrm.setMethod(ms.getClass().getMethod("execute", Object.class)));
ioc.publishEvent(new Event(EventType.initController, path));
requestMethodMap.put(path, hrm);
}

private void registerControllerMethods(Bean bean) {
Arrays.stream(bean.getClazz().getMethods()).forEach(m -> Optional.ofNullable(m.getAnnotation(RequestMapping.class)).ifPresent(rm -> {
String path = rm.path();
HttpRequestMethod hrm = new HttpRequestMethod();
hrm.setTimeout(rm.timeout());
hrm.setPath(path);
hrm.setObj(bean.getObj());
hrm.setMethod(m);
hrm.setHttpMethod(rm.method());
ioc.publishEvent(new Event(EventType.initController, path));
requestMethodMap.put(path, hrm);
}));
}


private static final class LazyHolder {
private static final Mvc ins = new Mvc(Ioc.ins());
Expand Down Expand Up @@ -173,20 +182,25 @@ public void callService(MvcContext context, MvcRequest request, MvcResponse resp

public void callMethod(MvcContext context, MvcRequest request, MvcResponse response, MvcResult<Object> result, HttpRequestMethod method) {
Safe.run(() -> {
JsonElement args = getArgs(method, request.getMethod().toLowerCase(Locale.ROOT), request, context);
Object[] params = new Object[]{null};
if (method.getMethod().getParameterTypes().length == 1 && method.getMethod().getParameterTypes()[0].equals(MvcContext.class)) {
params[0] = context;
//If there is only one parameter and it is a String, no further parsing is necessary; it can be used directly.
if (isSingleStringParameterMethod(method)) {
params[0] = new String(request.getBody());
} else {
try {
params = methodInvoker.getMethodParams(method.getMethod(), args);
} catch (Exception e) {
log.error("getMethodParams error,path:{},params:{},method:{}", context.getPath(),
new Gson().toJson(context.getParams()), request.getMethod().toLowerCase(Locale.ROOT), e);
JsonElement args = getArgs(method, request.getMethod().toLowerCase(Locale.ROOT), request, context);
if (isSingleMvcContextParameterMethod(method)) {
params[0] = context;
} else {
try {
params = methodInvoker.getMethodParams(method.getMethod(), args);
} catch (Exception e) {
log.error("getMethodParams error,path:{},params:{},method:{}", context.getPath(),
GsonUtils.gson.toJson(context.getParams()), request.getMethod().toLowerCase(Locale.ROOT), e);
}
}
}
Object data = this.mvcConfig.isUseCglib() ? methodInvoker.invokeFastMethod(method.getObj(), method.getMethod(), params) :
methodInvoker.invokeMethod(method.getObj(), method.getMethod(), params);

Object data = invokeControllerMethod(method, params);

if (context.isSync()) {
context.setResponse(data);
Expand Down Expand Up @@ -234,6 +248,20 @@ public void callMethod(MvcContext context, MvcRequest request, MvcResponse respo
});
}

private Object invokeControllerMethod(HttpRequestMethod method, Object[] params) {
Object data = this.mvcConfig.isUseCglib() ? methodInvoker.invokeFastMethod(method.getObj(), method.getMethod(), params) :
methodInvoker.invokeMethod(method.getObj(), method.getMethod(), params);
return data;
}

private static boolean isSingleMvcContextParameterMethod(HttpRequestMethod method) {
return method.getMethod().getParameterTypes().length == 1 && method.getMethod().getParameterTypes()[0].equals(MvcContext.class);
}

private static boolean isSingleStringParameterMethod(HttpRequestMethod method) {
return method.getMethod().getParameterTypes().length == 1 && method.getMethod().getParameterTypes()[0].equals(String.class);
}

/**
* parsing parameters
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.xiaomi.youpin.docean.mvc.html.Html;
import com.xiaomi.youpin.docean.mvc.upload.MvcUpload;
import com.xiaomi.youpin.docean.mvc.util.ExceptionUtil;
import com.xiaomi.youpin.docean.mvc.util.GsonUtils;
import com.xiaomi.youpin.docean.mvc.util.MethodFinder;
import com.xiaomi.youpin.docean.mvc.util.RequestUtils;
import io.netty.channel.ChannelHandlerContext;
Expand Down Expand Up @@ -105,8 +106,9 @@ private void call() {
if (context.isWebsocket()) {
WsRequest req = new Gson().fromJson(new String(request.getBody()), WsRequest.class);
request.setPath(req.getPath());
request.setBody(new Gson().toJson(req.getParams()).getBytes());
request.setBody(GsonUtils.gson.toJson(req.getParams()).getBytes());
}

//Directly returning not found when searching for favicon.ico.
if (isFaviconIco(request)) {
response.writeAndFlush(context, HttpResponseStatus.NOT_FOUND, "");
Expand All @@ -115,6 +117,7 @@ private void call() {
String path = request.getPath();


//Directly render static pages.
if (config.isOpenStaticFile() && Html.isHtmlFile(path)) {
String content = Html.view(config.getStaticFilePath() + path);
if (StringUtils.isEmpty(content)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.xiaomi.youpin.docean.mvc;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.xiaomi.youpin.docean.mvc.httpmethod.HttpMethodUtils;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ public String testSession2(MvcContext context) {
return "session:" + name;
}

//Test the scenario where only a single parameter is passed, and it is of type String.
@RequestMapping(path = "/string")
public String string(String str) {
return str;
}


public void destory() {
log.info("destory controller");
Expand Down

0 comments on commit bbbf3d6

Please sign in to comment.