From bbbf3d625a8f28711a582fc084efed713197d2c0 Mon Sep 17 00:00:00 2001 From: zhangzhiyong Date: Tue, 27 Feb 2024 14:55:10 +0800 Subject: [PATCH] docean supports mvc non-JSON format single-parameter call --- .../java/com/xiaomi/youpin/docean/Mvc.java | 88 ++++++++++++------- .../xiaomi/youpin/docean/mvc/MvcRunnable.java | 5 +- .../com/xiaomi/youpin/docean/mvc/Post.java | 1 - .../docean/test/demo/DemoController.java | 6 ++ 4 files changed, 68 insertions(+), 32 deletions(-) diff --git a/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Mvc.java b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Mvc.java index df8f4804f..81a29df60 100644 --- a/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Mvc.java +++ b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Mvc.java @@ -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; @@ -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()); @@ -173,20 +182,25 @@ public void callService(MvcContext context, MvcRequest request, MvcResponse resp public void callMethod(MvcContext context, MvcRequest request, MvcResponse response, MvcResult 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); @@ -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 * diff --git a/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/mvc/MvcRunnable.java b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/mvc/MvcRunnable.java index ea1ebdd13..917841de1 100644 --- a/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/mvc/MvcRunnable.java +++ b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/mvc/MvcRunnable.java @@ -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; @@ -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, ""); @@ -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)) { diff --git a/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/mvc/Post.java b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/mvc/Post.java index bd0ecbe77..09656a1a9 100644 --- a/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/mvc/Post.java +++ b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/mvc/Post.java @@ -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; diff --git a/jcommon/docean/src/test/java/com/xiaomi/youpin/docean/test/demo/DemoController.java b/jcommon/docean/src/test/java/com/xiaomi/youpin/docean/test/demo/DemoController.java index 122649cab..fe68c91b7 100644 --- a/jcommon/docean/src/test/java/com/xiaomi/youpin/docean/test/demo/DemoController.java +++ b/jcommon/docean/src/test/java/com/xiaomi/youpin/docean/test/demo/DemoController.java @@ -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");