From 4def12a0f50b670bb7c11436c15f1c10448c4279 Mon Sep 17 00:00:00 2001 From: tangtj Date: Sun, 8 Mar 2020 16:54:26 +0800 Subject: [PATCH 1/2] Route annotation configuration specified Http method support --- .../cicada/server/annotation/CicadaRoute.java | 4 + .../cicada/server/enums/HttpMethod.java | 30 +++++++ .../cicada/server/enums/StatusEnum.java | 2 + .../cicada/server/handle/HttpDispatcher.java | 2 +- .../cicada/server/route/RouterScanner.java | 84 ++++++++++++++----- .../route/register/RequestRouteInfo.java | 48 +++++++++++ .../route/register/RouterMethodInfo.java | 53 ++++++++++++ 7 files changed, 200 insertions(+), 23 deletions(-) create mode 100644 cicada-core/src/main/java/top/crossoverjie/cicada/server/enums/HttpMethod.java create mode 100644 cicada-core/src/main/java/top/crossoverjie/cicada/server/route/register/RequestRouteInfo.java create mode 100644 cicada-core/src/main/java/top/crossoverjie/cicada/server/route/register/RouterMethodInfo.java diff --git a/cicada-core/src/main/java/top/crossoverjie/cicada/server/annotation/CicadaRoute.java b/cicada-core/src/main/java/top/crossoverjie/cicada/server/annotation/CicadaRoute.java index b9378c2..0f2dfa0 100644 --- a/cicada-core/src/main/java/top/crossoverjie/cicada/server/annotation/CicadaRoute.java +++ b/cicada-core/src/main/java/top/crossoverjie/cicada/server/annotation/CicadaRoute.java @@ -1,6 +1,8 @@ package top.crossoverjie.cicada.server.annotation; +import top.crossoverjie.cicada.server.enums.HttpMethod; + import java.lang.annotation.*; @Target(ElementType.METHOD) @@ -9,4 +11,6 @@ public @interface CicadaRoute { String value() default "" ; + + HttpMethod[] method() default {}; } diff --git a/cicada-core/src/main/java/top/crossoverjie/cicada/server/enums/HttpMethod.java b/cicada-core/src/main/java/top/crossoverjie/cicada/server/enums/HttpMethod.java new file mode 100644 index 0000000..1869a2f --- /dev/null +++ b/cicada-core/src/main/java/top/crossoverjie/cicada/server/enums/HttpMethod.java @@ -0,0 +1,30 @@ +package top.crossoverjie.cicada.server.enums; + +import java.util.HashMap; +import java.util.Map; + +public enum HttpMethod { + + POST, + + GET, + + PUT, + + PATCH, + + DELETED; + + private static final Map mappings = new HashMap<>(16); + + static { + for (HttpMethod httpMethod : values()) { + mappings.put(httpMethod.name(), httpMethod); + } + } + + public static HttpMethod resolve(String method) { + return (method != null ? mappings.get(method) : null); + } + +} diff --git a/cicada-core/src/main/java/top/crossoverjie/cicada/server/enums/StatusEnum.java b/cicada-core/src/main/java/top/crossoverjie/cicada/server/enums/StatusEnum.java index 2e92d1f..0be5a53 100644 --- a/cicada-core/src/main/java/top/crossoverjie/cicada/server/enums/StatusEnum.java +++ b/cicada-core/src/main/java/top/crossoverjie/cicada/server/enums/StatusEnum.java @@ -18,6 +18,8 @@ public enum StatusEnum { /** empty of package */ NULL_PACKAGE("8000", "Your main class is empty of package"), + REPEAT_ROUTE("8000","Request correspond multiple method"), + /** 404 */ NOT_FOUND("404", "Need to declare a method by using @CicadaRoute!"), diff --git a/cicada-core/src/main/java/top/crossoverjie/cicada/server/handle/HttpDispatcher.java b/cicada-core/src/main/java/top/crossoverjie/cicada/server/handle/HttpDispatcher.java index 3a72a4d..be95717 100644 --- a/cicada-core/src/main/java/top/crossoverjie/cicada/server/handle/HttpDispatcher.java +++ b/cicada-core/src/main/java/top/crossoverjie/cicada/server/handle/HttpDispatcher.java @@ -84,7 +84,7 @@ public void channelRead0(ChannelHandlerContext ctx, DefaultHttpRequest httpReque } // execute Method - Method method = routerScanner.routeMethod(queryStringDecoder); + Method method = routerScanner.routeMethod(cicadaRequest.getMethod(),queryStringDecoder); routeProcess.invoke(method,queryStringDecoder) ; diff --git a/cicada-core/src/main/java/top/crossoverjie/cicada/server/route/RouterScanner.java b/cicada-core/src/main/java/top/crossoverjie/cicada/server/route/RouterScanner.java index 550c187..74f1b32 100644 --- a/cicada-core/src/main/java/top/crossoverjie/cicada/server/route/RouterScanner.java +++ b/cicada-core/src/main/java/top/crossoverjie/cicada/server/route/RouterScanner.java @@ -5,14 +5,15 @@ import top.crossoverjie.cicada.server.annotation.CicadaRoute; import top.crossoverjie.cicada.server.config.AppConfig; import top.crossoverjie.cicada.server.context.CicadaContext; +import top.crossoverjie.cicada.server.enums.HttpMethod; import top.crossoverjie.cicada.server.enums.StatusEnum; import top.crossoverjie.cicada.server.exception.CicadaException; import top.crossoverjie.cicada.server.reflect.ClassScanner; +import top.crossoverjie.cicada.server.route.register.RouterMethodInfo; +import top.crossoverjie.cicada.server.route.register.RequestRouteInfo; import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * Function: @@ -23,7 +24,10 @@ */ public class RouterScanner { - private static Map routes = null; + //private static Map routes = null; + + private static Map routes = new HashMap<>(16); + private volatile static RouterScanner routerScanner; @@ -45,21 +49,24 @@ public static RouterScanner getInstance() { return routerScanner; } - private RouterScanner() { + private RouterScanner(){ + try { + registerRouter(appConfig.getRootPackageName()); + }catch (Exception e){ + e.printStackTrace(); + } + } /** - * get route method + * get route method * + * @param method http method * @param queryStringDecoder * @return * @throws Exception */ - public Method routeMethod(QueryStringDecoder queryStringDecoder) throws Exception { - if (routes == null) { - routes = new HashMap<>(16); - loadRouteMethods(appConfig.getRootPackageName()); - } + public Method routeMethod(String method, QueryStringDecoder queryStringDecoder) throws Exception { //default response boolean defaultResponse = defaultResponse(queryStringDecoder.path()); @@ -68,15 +75,12 @@ public Method routeMethod(QueryStringDecoder queryStringDecoder) throws Exceptio return null; } - Method method = routes.get(queryStringDecoder.path()); - - if (method == null) { + RequestRouteInfo info = new RequestRouteInfo(queryStringDecoder.path(), HttpMethod.resolve(method)); + boolean isContains = routes.containsKey(info); + if (!isContains){ throw new CicadaException(StatusEnum.NOT_FOUND); } - - return method; - - + return routes.get(info); } private boolean defaultResponse(String path) { @@ -88,21 +92,57 @@ private boolean defaultResponse(String path) { return false; } - - private void loadRouteMethods(String packageName) throws Exception { + private void registerRouter(String packageName) throws Exception { Set> classes = ClassScanner.getClasses(packageName); + if (routes == null){ + routes = new HashMap<>(16); + } + + Set defaultRouterMethod = new HashSet<>(16); for (Class aClass : classes) { Method[] declaredMethods = aClass.getMethods(); + CicadaAction cicadaAction = aClass.getAnnotation(CicadaAction.class); for (Method method : declaredMethods) { CicadaRoute annotation = method.getAnnotation(CicadaRoute.class); if (annotation == null) { continue; } + HttpMethod[] methods = annotation.method(); + String url = appConfig.getRootPath() + "/" + cicadaAction.value() + "/" + annotation.value(); + + if (methods.length <= 0){ + RouterMethodInfo info = new RouterMethodInfo(url,method); + //判断是否重复标记 + if (defaultRouterMethod.contains(info)){ + throw new CicadaException(StatusEnum.REPEAT_ROUTE); + } + defaultRouterMethod.add(info); + }else { + for (HttpMethod httpMethod : methods) { + + RequestRouteInfo info = new RequestRouteInfo(url,httpMethod); + if (routes.containsKey(info)){ + throw new CicadaException(StatusEnum.REPEAT_ROUTE); + } + routes.put(info,method); + } + } + } + } + + for (RouterMethodInfo routerMethodInfo : defaultRouterMethod) { + String url = routerMethodInfo.getPath(); + Method method = routerMethodInfo.getMethod(); + HttpMethod[] methods = HttpMethod.values(); - CicadaAction cicadaAction = aClass.getAnnotation(CicadaAction.class); - routes.put(appConfig.getRootPath() + "/" + cicadaAction.value() + "/" + annotation.value(), method); + for (HttpMethod httpMethod : methods) { + RequestRouteInfo info = new RequestRouteInfo(url,httpMethod); + if (routes.containsKey(info)){ + continue; + } + routes.put(info,method); } } } diff --git a/cicada-core/src/main/java/top/crossoverjie/cicada/server/route/register/RequestRouteInfo.java b/cicada-core/src/main/java/top/crossoverjie/cicada/server/route/register/RequestRouteInfo.java new file mode 100644 index 0000000..66c3cd7 --- /dev/null +++ b/cicada-core/src/main/java/top/crossoverjie/cicada/server/route/register/RequestRouteInfo.java @@ -0,0 +1,48 @@ +package top.crossoverjie.cicada.server.route.register; + +import com.google.common.base.Objects; +import top.crossoverjie.cicada.server.enums.HttpMethod; + +public class RequestRouteInfo { + + private HttpMethod httpMethods; + + private String path; + + public RequestRouteInfo(String path, HttpMethod httpMethods) { + this.httpMethods = httpMethods; + this.path = path; + } + + public RequestRouteInfo(){} + + public HttpMethod getHttpMethods() { + return httpMethods; + } + + public void setHttpMethods(HttpMethod httpMethods) { + this.httpMethods = httpMethods; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RequestRouteInfo that = (RequestRouteInfo) o; + return httpMethods == that.httpMethods && + Objects.equal(path, that.path); + } + + @Override + public int hashCode() { + return Objects.hashCode(httpMethods, path); + } +} diff --git a/cicada-core/src/main/java/top/crossoverjie/cicada/server/route/register/RouterMethodInfo.java b/cicada-core/src/main/java/top/crossoverjie/cicada/server/route/register/RouterMethodInfo.java new file mode 100644 index 0000000..483bcd3 --- /dev/null +++ b/cicada-core/src/main/java/top/crossoverjie/cicada/server/route/register/RouterMethodInfo.java @@ -0,0 +1,53 @@ +package top.crossoverjie.cicada.server.route.register; + +import com.google.common.base.Objects; + +import java.lang.reflect.Method; + +/** + * @author TANG + */ +public class RouterMethodInfo { + + private String path; + + private Method method; + + public RouterMethodInfo(String path, Method method) { + this.path = path; + this.method = method; + } + + public RouterMethodInfo() { + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Method getMethod() { + return method; + } + + public void setMethod(Method method) { + this.method = method; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RouterMethodInfo that = (RouterMethodInfo) o; + return Objects.equal(path, that.path) && + Objects.equal(method, that.method); + } + + @Override + public int hashCode() { + return Objects.hashCode(path, method); + } +} From f4307bbe8efd0cc5b68cb19e4cb2eb536192a220 Mon Sep 17 00:00:00 2001 From: tangtj Date: Sun, 8 Mar 2020 17:00:45 +0800 Subject: [PATCH 2/2] add example --- .../top/crossoverjie/cicada/example/action/RouteAction.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cicada-example/src/main/java/top/crossoverjie/cicada/example/action/RouteAction.java b/cicada-example/src/main/java/top/crossoverjie/cicada/example/action/RouteAction.java index fec0557..402209d 100644 --- a/cicada-example/src/main/java/top/crossoverjie/cicada/example/action/RouteAction.java +++ b/cicada-example/src/main/java/top/crossoverjie/cicada/example/action/RouteAction.java @@ -10,6 +10,7 @@ import top.crossoverjie.cicada.server.annotation.CicadaRoute; import top.crossoverjie.cicada.server.bean.CicadaBeanManager; import top.crossoverjie.cicada.server.context.CicadaContext; +import top.crossoverjie.cicada.server.enums.HttpMethod; /** * Function: @@ -70,4 +71,9 @@ public void test(CicadaContext context){ context.html("

12345

"); } + @CicadaRoute(value = "method",method = HttpMethod.POST) + public void methodSupport(CicadaContext context){ + context.text("POST only"); + } + }