Skip to content

Commit

Permalink
docean supports mvc non-JSON format single-parameter call (#794)
Browse files Browse the repository at this point in the history
* update

* Support for static file parsing has been added

* docean supports mvc non-JSON format single-parameter call
  • Loading branch information
goodjava committed Feb 27, 2024
1 parent 4f3b522 commit 10e353c
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 35 deletions.
4 changes: 2 additions & 2 deletions jcommon/docean/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
<dependency>
<groupId>run.mone</groupId>
<artifactId>easy</artifactId>
<!-- <version>1.4-jdk21-SNAPSHOT</version>-->
<version>1.5.0-jdk21</version>
<version>1.4-jdk21-SNAPSHOT</version>
<!-- <version>1.5.0-jdk21</version>-->
</dependency>
<dependency>
<groupId>cglib</groupId>
Expand Down
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 @@ -32,6 +32,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 @@ -102,33 +103,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 @@ -175,20 +184,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 @@ -238,6 +252,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,16 +106,16 @@ 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, "");
return;
}
String path = request.getPath();


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 10e353c

Please sign in to comment.