All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.cybermkd.route.core.RouteBuilder Maven / Gradle / Ivy

package com.cybermkd.route.core;

import com.cybermkd.common.entity.CaseInsensitiveMap;
import com.cybermkd.common.http.HttpMethod;
import com.cybermkd.common.spring.SpringBuilder;
import com.cybermkd.common.spring.SpringHolder;
import com.cybermkd.common.util.analysis.ParamAttribute;
import com.cybermkd.common.util.analysis.ParamNamesScaner;
import com.cybermkd.route.annotation.*;
import com.cybermkd.route.config.InterceptorLoader;
import com.cybermkd.route.config.ResourceLoader;
import com.cybermkd.route.core.multipart.FILE;
import com.cybermkd.route.core.multipart.MultipartBuilder;
import com.cybermkd.route.interceptor.Interceptor;
import com.cybermkd.route.interceptor.InterceptorBuilder;
import com.cybermkd.route.valid.Validator;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * Route Mapping
 */
public final class RouteBuilder {

    private ResourceLoader resourceLoader;
    private InterceptorLoader interceptorLoader;

    //对routes排序
    private Map>> routesMap = new CaseInsensitiveMap>>();

    public RouteBuilder(ResourceLoader resourceLoader, InterceptorLoader interceptorLoader) {
        this.resourceLoader = resourceLoader;
        this.interceptorLoader = interceptorLoader;
    }

    /**
     * 添加route
     */
    private void addRoute(String httpMethod, String apiPath, String methodPath, String des, MultipartBuilder multipartBuilder, Map headers, Interceptor[] routeInters, Map classParamNames, Class[] validClasses, Class resourceClazz, Method method) {
        Route route = new Route(resourceClazz, ParamNamesScaner.getParamNames(method, classParamNames), httpMethod, getApi(apiPath, methodPath), method, routeInters,
                des, getValidators(validClasses), multipartBuilder, headers);
        //资源的标志
        if (apiPath.contains(Route.PARAM_PATTERN)) {
            throw new IllegalArgumentException("Api path could not contains pattern. Because this is a resource url.");
        }
        //httpMethod区分
        if (routesMap.containsKey(httpMethod)) {
            Map> routesHttpMethodMap = routesMap.get(httpMethod);
            //url区分
            if (routesHttpMethodMap.containsKey(apiPath)) {
                Set routes = routesHttpMethodMap.get(apiPath);
                //判断重复
                for (Route r : routes) {
                    if (r.getHttpMethod().equals(route.getHttpMethod()) && r.getPattern().equals(route.getPattern()) && matchHeaders(r.getHeaders(), route.getHeaders())) {
                        throw new IllegalArgumentException("Same path pattern '" + route.getHttpMethod() + " " + route.getPattern() + "' (" + route.getResourceClass().getSimpleName() + ".java:" + route.getAllLineNumbers()[0] + ")");
                    }
                }
                routesMap.get(httpMethod).get(apiPath).add(route);
            } else {
                routesMap.get(httpMethod).put(apiPath, newRouteDESCSet(route));
            }
        } else {
            routesMap.put(httpMethod, newRouteMap(apiPath, route));
        }
    }

    /**
     * 判断header是否相同
     *
     * @param source
     * @param dist
     * @return
     */
    public boolean matchHeaders(Map source, Map dist) {
        boolean result = true;
        if (source.size() == dist.size()) {
            for (Map.Entry sourceEntry : source.entrySet()) {
                if (!sourceEntry.getValue().equals(dist.get(sourceEntry.getKey()))) {
                    result = false;
                }
            }
        } else {
            result = false;
        }
        return result;
    }


    public void build() {
        InterceptorBuilder interceptorBuilder = new InterceptorBuilder();
        Interceptor[] defaultInters = interceptorLoader.getInterceptorArray();
        interceptorBuilder.addToInterceptorsMap(defaultInters);

        //文件上传的注解
        FILE file = null;
        DELETE delete = null;
        GET get = null;
        POST post = null;
        PUT put = null;
        PATCH patch = null;
        String apiPath = "";

        //文件上传构建器
        MultipartBuilder multipartBuilder = null;
        Interceptor[] methodInters;
        //当前路由所有的拦截器 包括resource的和method的
        Interceptor[] routeInters;
        //resource的拦截器
        Interceptor[] resourceInters;
        //获取参数
        Map classParamNames;
        //当前resource的方法
        Method[] methods;

        //addResources
        for (Class resourceClazz : resourceLoader.getResources()) {
            if (SpringHolder.alive) {
                SpringBuilder.register(resourceClazz);//如果spring plugin init注入到spring容器
            }
            resourceInters = interceptorBuilder.buildResourceInterceptors(resourceClazz);
            classParamNames = ParamNamesScaner.getParamNames(resourceClazz);

            apiPath = getApi(resourceClazz);
            //自己的方法
            if (Modifier.isAbstract(resourceClazz.getSuperclass().getModifiers())) {
                methods = resourceClazz.getMethods();
            } else {
                methods = resourceClazz.getDeclaredMethods();
            }
            //遍历方法看是不是 restful api
            for (Method method : methods) {
                //文件上传 构建器
                file = method.getAnnotation(FILE.class);
                if (file != null) {
                    multipartBuilder = new MultipartBuilder(file.dir(), file.overwrite(), file.renamer(), file.max(), file.encoding(), file.allows());
                } else {
                    multipartBuilder = null;
                }

                //delete 请求
                delete = method.getAnnotation(DELETE.class);
                if (delete != null) {

                    methodInters = interceptorBuilder.buildMethodInterceptors(method);
                    routeInters = interceptorBuilder.buildRouteInterceptors(defaultInters, resourceInters, resourceClazz, methodInters, method);

                    addRoute(HttpMethod.DELETE, apiPath, delete.value(), delete.des(), multipartBuilder, getApiHeader(resourceClazz, delete), routeInters, classParamNames, delete.valid(), resourceClazz, method);
                    continue;
                }
                //get 请求
                get = method.getAnnotation(GET.class);
                if (get != null) {

                    methodInters = interceptorBuilder.buildMethodInterceptors(method);
                    routeInters = interceptorBuilder.buildRouteInterceptors(defaultInters, resourceInters, resourceClazz, methodInters, method);

                    addRoute(HttpMethod.GET, apiPath, get.value(), get.des(), multipartBuilder, getApiHeader(resourceClazz, get), routeInters, classParamNames, get.valid(), resourceClazz, method);
                    continue;
                }
                //post 请求
                post = method.getAnnotation(POST.class);
                if (post != null) {

                    methodInters = interceptorBuilder.buildMethodInterceptors(method);
                    routeInters = interceptorBuilder.buildRouteInterceptors(defaultInters, resourceInters, resourceClazz, methodInters, method);

                    addRoute(HttpMethod.POST, apiPath, post.value(), post.des(), multipartBuilder, getApiHeader(resourceClazz, post), routeInters, classParamNames, post.valid(), resourceClazz, method);
                    continue;
                }
                //put 请求
                put = method.getAnnotation(PUT.class);
                if (put != null) {

                    methodInters = interceptorBuilder.buildMethodInterceptors(method);
                    routeInters = interceptorBuilder.buildRouteInterceptors(defaultInters, resourceInters, resourceClazz, methodInters, method);

                    addRoute(HttpMethod.PUT, apiPath, put.value(), put.des(), multipartBuilder, getApiHeader(resourceClazz, put), routeInters, classParamNames, put.valid(), resourceClazz, method);
                    continue;
                }
                //patch 请求
                patch = method.getAnnotation(PATCH.class);
                if (patch != null) {

                    methodInters = interceptorBuilder.buildMethodInterceptors(method);
                    routeInters = interceptorBuilder.buildRouteInterceptors(defaultInters, resourceInters, resourceClazz, methodInters, method);

                    addRoute(HttpMethod.PATCH, apiPath, patch.value(), patch.des(), multipartBuilder, getApiHeader(resourceClazz, patch), routeInters, classParamNames, patch.valid(), resourceClazz, method);
                    continue;
                }
            }
        }
    }


    /**
     * 获取所有验证器
     *
     * @param validClasses 验证器的class
     * @return Valid[]
     */
    private Validator[] getValidators(Class[] validClasses) {
        Validator[] validators = new Validator[validClasses.length];
        if (validClasses.length > 0) {
            int i = 0;
            for (Class valid : validClasses) {
                try {
                    validators[i] = valid.newInstance();
                } catch (InstantiationException e) {
                    throw new RuntimeException(e.getMessage(), e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e.getMessage(), e);
                }
                i++;
            }
        }
        return validators;
    }

    /**
     * 获取api部分
     *
     * @param resourceClazz resource class
     * @return url apiPath
     */
    private String getApi(Class resourceClazz) {
        API api;
        String apiPath = "";
        api = resourceClazz.getAnnotation(API.class);
        if (api != null) {
            apiPath = api.value();
            if (!apiPath.equals("")) {
                if (!apiPath.startsWith("/")) {
                    apiPath = "/" + apiPath;
                }
            }
        }
        Class superClazz = resourceClazz.getSuperclass();
        if (Resource.class.isAssignableFrom(superClazz)) {
            apiPath = getApi((Class) superClazz) + apiPath;
        }
        return apiPath;
    }

    /**
     * 最终生成的apiPath
     *
     * @param apiPath
     * @param methodPath
     * @return
     */
    private String getApi(String apiPath, String methodPath) {
        if (!methodPath.equals("")) {
            if (!methodPath.startsWith("/")) {
                apiPath = apiPath + "/" + methodPath;
            } else {
                apiPath = apiPath + methodPath;
            }
        }
        return apiPath;
    }

    private Map getApiHeader(Class resourceClazz) {
        API api;
        Map apiHeaders = new HashMap();
        api = resourceClazz.getAnnotation(API.class);
        if (api != null) {
            String[] apiHeaderValue = api.headers();
            apiHeaders.putAll(getApiHeaderValue(apiHeaderValue));
        }
        Class superClazz = resourceClazz.getSuperclass();
        if (Resource.class.isAssignableFrom(superClazz)) {
            apiHeaders.putAll(getApiHeader((Class) superClazz));
        }
        return apiHeaders;
    }

    private Map getApiHeaderValue(String[] apiHeaderValue) {
        Map apiHeaders = new HashMap();
        if (apiHeaderValue.length > 0) {
            String[] apiHeaderArr;
            for (String apiHeader : apiHeaderValue) {
                apiHeaderArr = apiHeader.split(":");
                apiHeaders.put(apiHeaderArr[0].trim(), apiHeaderArr[1].trim());
            }
        }
        return apiHeaders;
    }

    private Map getApiHeader(Class resourceClazz, POST post) {
        Map apiHeaders = getApiHeader(resourceClazz);

        String[] apiHeaderValue = post.headers();
        apiHeaders.putAll(getApiHeaderValue(apiHeaderValue));
        return apiHeaders;
    }

    private Map getApiHeader(Class resourceClazz, DELETE delete) {
        Map apiHeaders = getApiHeader(resourceClazz);

        String[] apiHeaderValue = delete.headers();
        apiHeaders.putAll(getApiHeaderValue(apiHeaderValue));
        return apiHeaders;
    }

    private Map getApiHeader(Class resourceClazz, PUT put) {
        Map apiHeaders = getApiHeader(resourceClazz);

        String[] apiHeaderValue = put.headers();
        apiHeaders.putAll(getApiHeaderValue(apiHeaderValue));
        return apiHeaders;
    }

    private Map getApiHeader(Class resourceClazz, GET get) {
        Map apiHeaders = getApiHeader(resourceClazz);

        String[] apiHeaderValue = get.headers();
        apiHeaders.putAll(getApiHeaderValue(apiHeaderValue));
        return apiHeaders;
    }

    private Map getApiHeader(Class resourceClazz, PATCH patch) {
        Map apiHeaders = getApiHeader(resourceClazz);

        String[] apiHeaderValue = patch.headers();
        apiHeaders.putAll(getApiHeaderValue(apiHeaderValue));
        return apiHeaders;
    }

    public Map>> getRoutesMap() {
        return Collections.unmodifiableMap(routesMap);
    }

    /**
     * 创建一个对key排序的map
     *
     * @param apiPath apiPath
     * @param route   route
     * @return map
     */
    public Map> newRouteMap(final String apiPath, final Route route) {
        return new TreeMap>(new Comparator() {
            public int compare(String k1, String k2) {
                int result = k2.length() - k1.length();
                if (result == 0) {
                    return k1.compareTo(k2);
                }
                return result;
            }
        }) {{
            put(apiPath, newRouteDESCSet(route));
        }};
    }

    /**
     * 创建一个倒排序的route
     *
     * @param route route
     * @return Set
     */
    public Set newRouteDESCSet(final Route route) {
        return new TreeSet(
                new Comparator() {
                    public int compare(Route a, Route b) {
                        String one = a.getPattern().replace("/" + Route.PARAM_PATTERN, "");
                        String two = b.getPattern().replace("/" + Route.PARAM_PATTERN, "");
                        int result = two.length() - one.length();
                        if (result == 0) {
                            result = a.getHttpMethod().compareTo(b.getHttpMethod());
                            if (result == 0) {
                                return a.getPathPattern().compareTo(b.getPathPattern());
                            }
                        }
                        return result;
                    }
                }) {{
            add(route);
        }};
    }
}









© 2015 - 2025 Weber Informatics LLC | Privacy Policy