• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • jersey訪問路徑是如何匹配并訪問的(一)

    上周同事遇到了一個問題,就是明明路徑存在,但是卻報出404未找到路徑,但是不是所有的路徑都404,網上查了很多關于jersey的資料,好像也沒說全,這次就自己查看一下源碼,看看它到底是怎么去匹配的。

    舉一個例子:

    http:127.0.0.1:8080/dsj/dsjql/v1/UnittypeCount/getList能訪問成功;

    http:127.0.0.1:8080/dsj/dsjql/v1/bmsx/areacode訪問404。

    這里說一個題外話,就是一開始的思考路線錯了,往網絡方面那邊走了,導致浪費了點時間。需要知道jersey怎么匹配的,那么首先要知道它是怎么初始化并加載的。

    因為我們公司平臺把jersey和spring整合了,那么先看入口類ResteasyDeployment的start方法吧。

    public void start()
        {
            Map contextDataMap;
            if(providerFactory == null)
                providerFactory = new ResteasyProviderFactory();
            providerFactory.setRegisterBuiltins(registerBuiltin);
            if(deploymentSensitiveFactoryEnabled)
            {
                if(!(providerFactory instanceof ThreadLocalResteasyProviderFactory) && (ResteasyProviderFactory.peekInstance() == null || !(ResteasyProviderFactory.peekInstance() instanceof ThreadLocalResteasyProviderFactory)))
                {
                    threadLocalProviderFactory = new ThreadLocalResteasyProviderFactory(providerFactory);
                    ResteasyProviderFactory.setInstance(threadLocalProviderFactory);
                }
            } else
            {
                ResteasyProviderFactory.setInstance(providerFactory);
            }
            if(asyncJobServiceEnabled)
            {
                AsynchronousDispatcher asyncDispatcher = new AsynchronousDispatcher(providerFactory);
                asyncDispatcher.setMaxCacheSize(asyncJobServiceMaxJobResults);
                asyncDispatcher.setMaxWaitMilliSeconds(asyncJobServiceMaxWait);
                asyncDispatcher.setThreadPoolSize(asyncJobServiceThreadPoolSize);
                asyncDispatcher.setBasePath(asyncJobServiceBasePath);
                asyncDispatcher.getUnwrappedExceptions().addAll(unwrappedExceptions);
                dispatcher = asyncDispatcher;
                asyncDispatcher.start();
            } else
            if(dispatcher == null)
            {
                SynchronousDispatcher dis = new SynchronousDispatcher(providerFactory);
                dis.getUnwrappedExceptions().addAll(unwrappedExceptions);
                dispatcher = dis;
            }
            registry = dispatcher.getRegistry();
            if(widerRequestMatching)
                ((ResourceMethodRegistry)registry).setWiderMatching(widerRequestMatching);
            dispatcher.getDefaultContextObjects().putAll(defaultContextObjects);
            dispatcher.getDefaultContextObjects().put(javax/ws/rs/core/Configurable, providerFactory);
            dispatcher.getDefaultContextObjects().put(javax/ws/rs/core/Configuration, providerFactory);
            dispatcher.getDefaultContextObjects().put(javax/ws/rs/ext/Providers, providerFactory);
            dispatcher.getDefaultContextObjects().put(org/jboss/resteasy/spi/Registry, registry);
            dispatcher.getDefaultContextObjects().put(org/jboss/resteasy/core/Dispatcher, dispatcher);
            dispatcher.getDefaultContextObjects().put(org/jboss/resteasy/spi/InternalDispatcher, InternalDispatcher.getInstance());
            contextDataMap = ResteasyProviderFactory.getContextDataMap();
            contextDataMap.putAll(dispatcher.getDefaultContextObjects());
            if(injectorFactoryClass != null)
            {
                InjectorFactory injectorFactory;
                try
                {
                    Class clazz = Thread.currentThread().getContextClassLoader().loadClass(injectorFactoryClass);
                    injectorFactory = (InjectorFactory)clazz.newInstance();
                }
                catch(ClassNotFoundException cnfe)
                {
                    throw new RuntimeException(Messages.MESSAGES.unableToFindInjectorFactory(), cnfe);
                }
                catch(Exception e)
                {
                    throw new RuntimeException(Messages.MESSAGES.unableToInstantiateInjectorFactory(), e);
                }
                providerFactory.setInjectorFactory(injectorFactory);
            }
            if(constructedDefaultContextObjects != null && constructedDefaultContextObjects.size() > 0)
            {
                Class key;
                Object obj;
                for(Iterator iterator = constructedDefaultContextObjects.entrySet().iterator(); iterator.hasNext(); contextDataMap.put(key, obj))
                {
                    java.util.Map.Entry entry = (java.util.Map.Entry)iterator.next();
                    key = null;
                    try
                    {
                        key = Thread.currentThread().getContextClassLoader().loadClass((String)entry.getKey());
                    }
                    catch(ClassNotFoundException e)
                    {
                        throw new RuntimeException(Messages.MESSAGES.unableToInstantiateContextObject((String)entry.getKey()), e);
                    }
                    obj = createFromInjectorFactory((String)entry.getValue(), providerFactory);
                    LogMessages.LOGGER.creatingContextObject((String)entry.getKey(), (String)entry.getValue());
                    defaultContextObjects.put(key, obj);
                    dispatcher.getDefaultContextObjects().put(key, obj);
                }
    
            }
            if(interceptorPrecedences != null)
            {
                String precedence;
                for(Iterator iterator1 = interceptorPrecedences.iterator(); iterator1.hasNext(); providerFactory.appendInterceptorPrecedence(precedence.trim()))
                    precedence = (String)iterator1.next();
    
            }
            if(interceptorBeforePrecedences != null)
            {
                java.util.Map.Entry ext;
                for(Iterator iterator2 = interceptorBeforePrecedences.entrySet().iterator(); iterator2.hasNext(); providerFactory.insertInterceptorPrecedenceBefore(((String)ext.getKey()).trim(), ((String)ext.getValue()).trim()))
                    ext = (java.util.Map.Entry)iterator2.next();
    
            }
            if(interceptorAfterPrecedences != null)
            {
                java.util.Map.Entry ext;
                for(Iterator iterator3 = interceptorAfterPrecedences.entrySet().iterator(); iterator3.hasNext(); providerFactory.insertInterceptorPrecedenceAfter(((String)ext.getKey()).trim(), ((String)ext.getValue()).trim()))
                    ext = (java.util.Map.Entry)iterator3.next();
    
            }
            if(securityEnabled)
                providerFactory.register(org/jboss/resteasy/plugins/interceptors/RoleBasedSecurityFeature);
            if(registerBuiltin)
            {
                providerFactory.setRegisterBuiltins(true);
                RegisterBuiltin.register(providerFactory);
                providerFactory.registerProviderInstance(new ServerFormUrlEncodedProvider(useContainerFormParams), null, null, true);
            } else
            {
                providerFactory.setRegisterBuiltins(false);
            }
            if(applicationClass != null)
                application = createApplication(applicationClass, dispatcher, providerFactory);
            registration();
            if(paramMapping != null)
                providerFactory.getContainerRequestFilterRegistry().registerSingleton(new AcceptParameterHttpPreprocessor(paramMapping));
            AcceptHeaderByFileSuffixFilter suffixNegotiationFilter = null;
            if(mediaTypeMappings != null)
            {
                Map extMap = new HashMap();
                java.util.Map.Entry ext;
                String value;
                for(Iterator iterator4 = mediaTypeMappings.entrySet().iterator(); iterator4.hasNext(); extMap.put(((String)ext.getKey()).trim(), MediaType.valueOf(value.trim())))
                {
                    ext = (java.util.Map.Entry)iterator4.next();
                    value = (String)ext.getValue();
                }
    
                if(suffixNegotiationFilter == null)
                {
                    suffixNegotiationFilter = new AcceptHeaderByFileSuffixFilter();
                    providerFactory.getContainerRequestFilterRegistry().registerSingleton(suffixNegotiationFilter);
                }
                suffixNegotiationFilter.setMediaTypeMappings(extMap);
            }
            if(languageExtensions != null)
            {
                if(suffixNegotiationFilter == null)
                {
                    suffixNegotiationFilter = new AcceptHeaderByFileSuffixFilter();
                    providerFactory.getContainerRequestFilterRegistry().registerSingleton(suffixNegotiationFilter);
                }
                suffixNegotiationFilter.setLanguageMappings(languageExtensions);
            }
            ResteasyProviderFactory.removeContextDataLevel();
            break MISSING_BLOCK_LABEL_1186;
            Exception exception;
            exception;
            ResteasyProviderFactory.removeContextDataLevel();
            throw exception;
        }

    這里不多說了,都是在初始化它的上下文環境,然后注冊,直接點開registration();

    public void registration()
        {
            boolean useScanning = true;
            if(application != null)
            {
                dispatcher.getDefaultContextObjects().put(javax/ws/rs/core/Application, application);
                ResteasyProviderFactory.getContextDataMap().put(javax/ws/rs/core/Application, application);
                if(processApplication(application))
                    useScanning = false;
            }
            if(useScanning && scannedProviderClasses != null)
            {
                String provider;
                for(Iterator iterator = scannedProviderClasses.iterator(); iterator.hasNext(); registerProvider(provider))
                    provider = (String)iterator.next();
    
            }
            if(providerClasses != null)
            {
                String provider;
                for(Iterator iterator1 = providerClasses.iterator(); iterator1.hasNext(); registerProvider(provider))
                    provider = (String)iterator1.next();
    
            }
            if(providers != null)
            {
                Object provider;
                for(Iterator iterator2 = providers.iterator(); iterator2.hasNext(); providerFactory.registerProviderInstance(provider))
                    provider = iterator2.next();
    
            }
            Class actualProviderClass;
            for(Iterator iterator3 = actualProviderClasses.iterator(); iterator3.hasNext(); providerFactory.registerProvider(actualProviderClass))
                actualProviderClass = (Class)iterator3.next();
    
            if(useScanning && scannedJndiComponentResources != null)
            {
                String resource;
                for(Iterator iterator4 = scannedJndiComponentResources.iterator(); iterator4.hasNext(); registerJndiComponentResource(resource))
                    resource = (String)iterator4.next();
    
            }
            if(jndiComponentResources != null)
            {
                String resource;
                for(Iterator iterator5 = jndiComponentResources.iterator(); iterator5.hasNext(); registerJndiComponentResource(resource))
                    resource = (String)iterator5.next();
    
            }
            if(jndiResources != null)
            {
                String resource;
                for(Iterator iterator6 = jndiResources.iterator(); iterator6.hasNext(); registry.addJndiResource(resource.trim()))
                    resource = (String)iterator6.next();
    
            }
            if(useScanning && scannedResourceClasses != null)
            {
                Class clazz;
                for(Iterator iterator7 = scannedResourceClasses.iterator(); iterator7.hasNext(); registry.addPerRequestResource(clazz))
                {
                    String resource = (String)iterator7.next();
                    clazz = null;
                    try
                    {
                        clazz = Thread.currentThread().getContextClassLoader().loadClass(resource.trim());
                    }
                    catch(ClassNotFoundException e)
                    {
                        throw new RuntimeException(e);
                    }
                }
    
            }
            if(resourceClasses != null)
            {
                Class clazz;
                for(Iterator iterator8 = resourceClasses.iterator(); iterator8.hasNext(); registry.addPerRequestResource(clazz))
                {
                    String resource = (String)iterator8.next();
                    clazz = null;
                    try
                    {
                        clazz = Thread.currentThread().getContextClassLoader().loadClass(resource.trim());
                    }
                    catch(ClassNotFoundException e)
                    {
                        throw new RuntimeException(e);
                    }
                }
    
            }
            if(resources != null)
            {
                Object obj;
                for(Iterator iterator9 = resources.iterator(); iterator9.hasNext(); registry.addSingletonResource(obj))
                    obj = iterator9.next();
    
            }
            Class actualResourceClass;
            for(Iterator iterator10 = actualResourceClasses.iterator(); iterator10.hasNext(); registry.addPerRequestResource(actualResourceClass))
                actualResourceClass = (Class)iterator10.next();
    
            ResourceFactory factory;
            for(Iterator iterator11 = resourceFactories.iterator(); iterator11.hasNext(); registry.addResourceFactory(factory))
                factory = (ResourceFactory)iterator11.next();
    
        }

    這里注冊它的bean,直接看最后的registry.addResourceFactory(factory)

    public void addResourceFactory(ResourceFactory ref)
        {
            addResourceFactory(ref, null);
        }
    public void addResourceFactory(ResourceFactory ref, String base)
        {
            Class clazz = ref.getScannableClass();
            Class restful = GetRestful.getRootResourceClass(clazz);
            if(restful == null)
            {
                String msg = Messages.MESSAGES.classIsNotRootResource(clazz.getName());
                Class aclass[] = clazz.getInterfaces();
                int i = aclass.length;
                for(int j = 0; j < i; j++)
                {
                    Class intf = aclass[j];
                    msg = (new StringBuilder()).append(msg).append(" ").append(intf.getName()).toString();
                }
    
                throw new RuntimeException(msg);
            } else
            {
                addResourceFactory(ref, base, restful);
                return;
            }
        }

    看這一行Class restful = GetRestful.getRootResourceClass(clazz);

    public static Class getRootResourceClass(Class clazz)
        {
            return AnnotationResolver.getClassWithAnnotation(clazz, javax/ws/rs/Path);
        }
    public static Class getClassWithAnnotation(Class clazz, Class annotation)
        {
            if(clazz.isAnnotationPresent(annotation))
                return clazz;
            Class aclass[] = clazz.getInterfaces();
            int i = aclass.length;
            for(int j = 0; j < i; j++)
            {
                Class intf = aclass[j];
                if(intf.isAnnotationPresent(annotation))
                    return intf;
            }
    
            Class superClass = clazz.getSuperclass();
            if(superClass != java/lang/Object && superClass != null)
                return getClassWithAnnotation(superClass, annotation);
            else
                return null;
        }

    很明確,就是根據@Path注解返回相應的類。

    然后跳出再看addResourceFactory(ref, base, restful);

    public void addResourceFactory(ResourceFactory ref, String base, Class clazz)
        {
            Class classes[] = {
                clazz
            };
            addResourceFactory(ref, base, classes);
            if(ref != null)
                ref.registered(providerFactory);
        }

    先進入addResourceFactory(ref, base, classes);

    public void addResourceFactory(ResourceFactory ref, String base, Class classes[])
        {
            if(ref != null)
                ref.registered(providerFactory);
            Class aclass[] = classes;
            int i = aclass.length;
            for(int j = 0; j < i; j++)
            {
                Class clazz = aclass[j];
                if(Proxy.isProxyClass(clazz))
                {
                    Class aclass1[] = clazz.getInterfaces();
                    int l = aclass1.length;
                    for(int j1 = 0; j1 < l; j1++)
                    {
                        Class intf = aclass1[j1];
                        ResourceClass resourceClass = ResourceBuilder.rootResourceFromAnnotations(intf);
                        register(ref, base, resourceClass);
                    }
    
                } else
                {
                    ResourceClass resourceClass = ResourceBuilder.rootResourceFromAnnotations(clazz);
                    register(ref, base, resourceClass);
                }
            }
    
            aclass = classes;
            i = aclass.length;
            for(int k = 0; k < i; k++)
            {
                Class clazz = aclass[k];
                Method amethod[] = clazz.getDeclaredMethods();
                int i1 = amethod.length;
                for(int k1 = 0; k1 < i1; k1++)
                {
                    Method method = amethod[k1];
                    Method _method = findAnnotatedMethod(clazz, method);
                    if(_method != null && !Modifier.isPublic(_method.getModifiers()))
                        LogMessages.LOGGER.JAXRSAnnotationsFoundAtNonPublicMethod(method.getDeclaringClass().getName(), method.getName());
                }
    
            }
    
        }

    直接看ResourceClass resourceClass = ResourceBuilder.rootResourceFromAnnotations(clazz);

    public static ResourceClass rootResourceFromAnnotations(Class clazz)
        {
            return fromAnnotations(false, clazz);
        }
    private static ResourceClass fromAnnotations(boolean isLocator, Class clazz)
        {
            if(!clazz.isInterface() && clazz.getSuperclass() != null && !clazz.getSuperclass().equals(java/lang/Object) && isWeldProxy(clazz))
                clazz = clazz.getSuperclass();
            ResourceClassBuilder builder = null;
            if(isLocator)
            {
                builder = locator(clazz);
            } else
            {
                Path path = (Path)clazz.getAnnotation(javax/ws/rs/Path);
                if(path == null)
                    builder = rootResource(clazz, null);
                else
                    builder = rootResource(clazz, path.value());
            }
            Method amethod[] = clazz.getMethods();
            int i = amethod.length;
            for(int j = 0; j < i; j++)
            {
                Method method = amethod[j];
                if(!method.isSynthetic() && !method.getDeclaringClass().equals(java/lang/Object))
                    processMethod(isLocator, builder, clazz, method);
            }
    
            if(!clazz.isInterface())
                processFields(builder, clazz);
            processSetters(builder, clazz);
            return builder.buildClass();
        }

    這里就是根據@path的類去初始化它的資源類,進入builder = rootResource(clazz, path.value());

    public static ResourceClassBuilder rootResource(Class root, String path)
        {
            return new ResourceClassBuilder(root, path);
        }
    public ResourceClassBuilder(Class root, String path)
            {
                fields = new ArrayList();
                setters = new ArrayList();
                resourceMethods = new ArrayList();
                resourceLocators = new ArrayList();
                resourceClass = new ResourceClass(root, path);
            }
    public ResourceClass(Class clazz, String path)
        {
            fields = EMPTY_FIELD_PARAMS;
            setters = EMPTY_SETTER_PARAMETERS;
            resourceMethods = EMPTY_RESOURCE_METHODS;
            resourceLocators = EMPTY_RESOURCE_LOCATORS;
            this.clazz = clazz;
            this.path = path;
        }

    然后跳出繼續看builder = rootResource(clazz, path.value())后面的方法,上面已截圖這里就不截圖了,就是初始化處理方法,字段那些東西,最后再builder.buildClass();

    public ResourceClass buildClass()
            {
                resourceClass.fields = (FieldParameter[])fields.toArray(new FieldParameter[fields.size()]);
                resourceClass.setters = (SetterParameter[])setters.toArray(new SetterParameter[setters.size()]);
                resourceClass.resourceMethods = (ResourceMethod[])resourceMethods.toArray(new ResourceMethod[resourceMethods.size()]);
                resourceClass.resourceLocators = (ResourceLocator[])resourceLocators.toArray(new ResourceLocator[resourceLocators.size()]);
                return resourceClass;
            }

    到這里,一個resourceClass就已經創建好了。

    然后跳出來進入register(ref, base, resourceClass);

    protected void register(ResourceFactory rf, String base, ResourceClass resourceClass)
        {
            Object aobj[] = resourceClass.getResourceMethods();
            int i = aobj.length;
            for(int j = 0; j < i; j++)
            {
                ResourceMethod method = aobj[j];
                processMethod(rf, base, method);
            }
    
            aobj = resourceClass.getResourceLocators();
            i = aobj.length;
            for(int k = 0; k < i; k++)
            {
                ResourceLocator method = aobj[k];
                processMethod(rf, base, method);
            }
    
        }

    進入processMethod(rf, base, method);

    protected void processMethod(ResourceFactory rf, String base, ResourceLocator method)
        {
            ResteasyUriBuilder builder = new ResteasyUriBuilder();
            if(base != null)
                builder.path(base);
            builder.path(method.getFullpath());
            String fullpath = builder.getPath();
            if(fullpath == null)
                fullpath = "";
            builder = new ResteasyUriBuilder();
            if(base != null)
                builder.path(base);
            builder.path(method.getResourceClass().getPath());
            String classExpression = builder.getPath();
            if(classExpression == null)
                classExpression = "";
            InjectorFactory injectorFactory = providerFactory.getInjectorFactory();
            if(method instanceof ResourceMethod)
            {
                ResourceMethodInvoker invoker = new ResourceMethodInvoker((ResourceMethod)method, injectorFactory, rf, providerFactory);
                if(widerMatching)
                    rootNode.addInvoker(fullpath, invoker);
                else
                    root.addInvoker(classExpression, fullpath, invoker);
            } else
            {
                ResourceLocatorInvoker locator = new ResourceLocatorInvoker(rf, injectorFactory, providerFactory, method);
                if(widerMatching)
                    rootNode.addInvoker(fullpath, locator);
                else
                    root.addInvoker(classExpression, fullpath, locator);
            }
        }

    感覺也沒啥好說的,就是根據全路徑fullpath(整個請求的url),類路徑classExpression(class上的@path的值),然后根據不同情況在rootClassNode或者rootNode上增加一個invoker類。widerMatching直譯泛匹配,沒有去細看,是ResteasyDeployment的一個屬性,然后set到ResourceMethodRegistry里,默認false。

    進入root.addInvoker(classExpression, fullpath, locator);

    public void addInvoker(String classExpression, String fullpath, ResourceInvoker invoker)
        {
            if(classExpression.startsWith("/"))
                classExpression = classExpression.substring(1);
            if(classExpression.endsWith("/"))
                classExpression = classExpression.substring(0, classExpression.length() - 1);
            ClassExpression newce = new ClassExpression(classExpression);
            String regex = newce.getRegex();
            ClassExpression existing = (ClassExpression)bounded.get(regex);
            if(existing == null)
            {
                newce.getRoot().addInvoker(fullpath, invoker);
                addExpression(classExpression, newce);
                bounded.put(regex, newce);
            } else
            {
                existing.getRoot().addInvoker(fullpath, invoker);
            }
        }

    看到這代碼說明,我們在@path注解里寫路徑,開頭和結尾沒必要寫斜杠,反正會截取掉的,然后創建一個ClassExpression,得到一個root。

    public ClassExpression(String segment)
        {
            super(segment, "".equals(segment) ? "(.*)" : "(/.+)?");
            root = new RootNode();
        }
    public RootNode()
        {
            root = new SegmentNode("");
            size = 0;
            bounded = new MultivaluedHashMap();
        }
    public SegmentNode(String segment)
        {
            children = new HashMap();
            targets = new ArrayList();
            this.segment = segment;
        }

    這里的數據結構很重要,后面會再說。然后回頭看super(segment, "".equals(segment) ? "(.*)" : "(/.+)?");

    ClassExpression繼承了Expression

    public Expression(String segment, String additionalRegex)
        {
            groups = new ArrayList();
            pathExpression = segment;
            String replacedCurlySegment = PathHelper.replaceEnclosedCurlyBraces(segment);
            literalCharacters = PathHelper.URI_PARAM_PATTERN.matcher(replacedCurlySegment).replaceAll("").length();
            String split[] = PathHelper.URI_PARAM_PATTERN.split(replacedCurlySegment);
            Matcher withPathParam = PathHelper.URI_PARAM_PATTERN.matcher(replacedCurlySegment);
            int i = 0;
            StringBuffer buffer = new StringBuffer();
            if(i < split.length)
                buffer.append(Pattern.quote(split[i++]));
            int groupNumber = 1;
            do
            {
                if(!withPathParam.find())
                    break;
                String name = withPathParam.group(1);
                buffer.append("(");
                if(withPathParam.group(3) == null)
                {
                    buffer.append("[^/]+");
                    groups.add(new Group(groupNumber++, name, true));
                } else
                {
                    String expr = withPathParam.group(3);
                    expr = PathHelper.recoverEnclosedCurlyBraces(expr);
                    buffer.append(expr);
                    numNonDefaultGroups++;
                    groups.add(new Group(groupNumber++, name));
                    groupNumber += groupCount(expr);
                }
                buffer.append(")");
                if(i < split.length)
                    buffer.append(Pattern.quote(split[i++]));
            } while(true);
            if(additionalRegex != null)
                buffer.append(additionalRegex);
            regex = buffer.toString();
            pattern = Pattern.compile(getRegex());
        }

    這里就是初始化ClassExpression的屬性,groups那些是關于@path的值有正則表達式的東西

    回頭看addInvoker方法,ClassExpression existing = (ClassExpression)bounded.get(regex);

    bounded是一個成員變量Map,里面存有各種class的@path的值(@path的值是key,對應生成的ClassExpression是value),后面邏輯很簡單,有就直接去增加invoker,為null就新增加invoer,并增加該ClassExpression,并存入bounded中。

    繼續后面的邏輯

    public void addInvoker(String path, ResourceInvoker invoker)
        {
            MethodExpression expression = addExpression(path, invoker);
            size++;
            bounded.add(path, expression);
        }
    protected MethodExpression addExpression(String path, ResourceInvoker invoker)
        {
            if(path.startsWith("/"))
                path = path.substring(1);
            if(path.endsWith("/"))
                path = path.substring(0, path.length() - 1);
            MethodExpression expression;
            if("".equals(path))
                if(invoker instanceof ResourceMethodInvoker)
                {
                    expression = new MethodExpression(root, "", invoker);
                    root.addExpression(expression);
                    return expression;
                } else
                {
                    expression = new MethodExpression(root, "", invoker, "(.*)");
                    root.addExpression(expression);
                    return expression;
                }
            expression = null;
            int expidx = path.indexOf('{');
            MethodExpression exp;
            if(expidx > -1)
            {
                int i;
                for(i = expidx; i - 1 > -1 && path.charAt(i - 1) != '/'; i--);
                String staticPath = null;
                if(i > 0)
                    staticPath = path.substring(0, i - 1);
                SegmentNode node = root;
                if(staticPath != null)
                {
                    String split[] = staticPath.split("/");
                    String as1[] = split;
                    int l = as1.length;
                    for(int i1 = 0; i1 < l; i1++)
                    {
                        String segment = as1[i1];
                        SegmentNode tmp = (SegmentNode)node.children.get(segment);
                        if(tmp == null)
                        {
                            tmp = new SegmentNode(segment);
                            node.children.put(segment, tmp);
                        }
                        node = tmp;
                    }
    
                }
                if(invoker instanceof ResourceMethodInvoker)
                    exp = new MethodExpression(node, path, invoker);
                else
                    exp = new MethodExpression(node, path, invoker, "(/.+)?");
                node.addExpression(exp);
            } else
            {
                String split[] = path.split("/");
                SegmentNode node = root;
                String as[] = split;
                int j = as.length;
                for(int k = 0; k < j; k++)
                {
                    String segment = as[k];
                    SegmentNode tmp = (SegmentNode)node.children.get(segment);
                    if(tmp == null)
                    {
                        tmp = new SegmentNode(segment);
                        node.children.put(segment, tmp);
                    }
                    node = tmp;
                }
    
                if(invoker instanceof ResourceMethodInvoker)
                {
                    exp = new MethodExpression(node, path, invoker);
                    node.addExpression(exp);
                } else
                {
                    exp = new MethodExpression(node, path, invoker, "(.*)");
                    node.addExpression(exp);
                }
            }
            return exp;
        }

    在RootNode上的2個方法,就是創建MethodExpression,對應完整url請求,并添加到相應的節點node,并且有正則匹配路徑特殊處理。而且根據斜杠分割path,每一節是一個segment,分別put到rootNood的children里(一個map集合)。

    到這里,容器初始化完成。根據@path注解生成的各個組件類也都已初始化。

     

    版權聲明:本文為qq_38392542原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/qq_38392542/article/details/103456968

    智能推薦

    springboot靜態資源訪問路徑

    在springboot中約定大于配置,當然對靜態資源也有默認的約定。 Spring Boot 默認將 /** 所有訪問映射到以下目錄: 所以大家在訪問靜態資源時就不需要加/static,/public這些前綴了,人家springboot都給你默認映射了,你再添加不是畫蛇添足嗎? 下面我將通過一個小demo來給大家展示一下 項目路徑 index.ftl controller 在瀏覽器地址欄輸入&nb...

    linux中nginx配置訪問路徑

    Linux中,配置nginx訪問home文件夾匯總的eakom文件夾,其配置如下 訪問是出現異常 查看nginx日志error.log日志 日志中顯示,訪問http://192.168.158.99/eakom/時,自動跳到Linux安裝目錄根路徑下htm文件中,注意:其中htm路徑為nginx默認配置的路徑,其配置代碼如下 nginx的nginx.conf配置文件默認配置user nobody ...

    jeecms 修改后臺訪問路徑

        我使用的是jeecmsV8版本。    1.修改web.xml(/jeecms/WebContent/WEB-INF/web.xml)     修改JeeCmsAdmin這個servlet,把/jeeadmin/jeecms/*替換成你想要的后臺訪問路徑。     注:此處替換的路...

    jersey訪問路徑是如何匹配并訪問的(一)

    上周同事遇到了一個問題,就是明明路徑存在,但是卻報出404未找到路徑,但是不是所有的路徑都404,網上查了很多關于jersey的資料,好像也沒說全,這次就自己查看一下源碼,看看它到底是怎么去匹配的。 舉一個例子: http:127.0.0.1:8080/dsj/dsjql/v1/UnittypeCount/getList能訪問成功; http:127.0.0.1:8080/dsj/dsjql/v1...

    MINIO分布式集群搭建

    搭建分布式集群 使用docker-compose 中文文檔:https://docs.min.io/cn/deploy-minio-on-docker-compose.html Docker Compose允許定義和運行單主機,多容器Docker應用程序。 使用Compose,您可以使用Compose文件來配置MinIO服務。 然后,使用單個命令,您可以通過你的配置創建并啟動所有分布式MinIO實...

    猜你喜歡

    LINUX設備驅動模型分析之五 總線-設備-驅動模塊總結

    前面幾篇文章我們對bus-device-driver模型進行了單獨介紹,本篇文章我們對這三部分進行總結,同時對之前文章中未細化的部分進行詳細說明。 bus-device-driver相關結構體關聯 如下圖是包含bus-device-driver的關聯圖,我們根據該流程圖再次進行一下說明。   1.devices_kset集合說明 內核系統中在device模塊的初始化接口中,創建了一個ks...

    python 爬蟲實踐 (爬取鏈家成交房源信息和價格)

    簡單介紹 pi: 簡單介紹下,我們需要用到的技術,python 版本是用的pyhon3,系統環境是linux,開發工具是vscode;工具包:request 爬取頁面數據,然后redis 實現數據緩存,lxml 實現頁面數據的分析,提取我們想要的數據,然后多線程和多進程提升爬取速度,最后,通過celery 框架實現分布式爬取,并實際部署下,下面就按這個邏輯順序,進行介紹 request爬取頁面數據...

    從NIO編程到Netty的使用

    我們在網絡編程——NIO編程中,就曾介紹過直接使用NIO進行編程,這里我們介紹下如何使用Netty框架,來完成我們之前直接使用NIO完成的功能,就是一個簡單的客戶端和服務端的通信。 在這之前,我們先來簡單了解一下Netty框架的核心組件: Channel Channel 是Java NIO 的一個基本構造。它代表一個到實體(如一個硬件設備、一個文件、一個網絡套接字或者一個能...

    小魚的Pytorch撞墻到撞墻墻到撞墻墻墻的精通之路二:自動微分

    自動微分篇 autograd requires_grad && grad_fn tensor.backward && tesnor.grad 總結&&參考文獻 基于官方教程,記載小魚的個人理解,記錄些許項目,以及不斷遇到的離奇的bug及殺蟲方法。 autograd autograd是pytorch之中的一個核心計算,提供了自動計算微分、跟蹤微分過程、...

    spring cloud + nacos入門案列

    一:簡介    Spring Cloud是一系列框架的有序集合。它利用Spring Boot的開發便利性巧妙地簡化了分布式系統基礎設施的開發,如服務發現注冊、配置中心、消息總線、負載均衡、斷路器、數據監控等,都可以用Spring Boot的開發風格做到一鍵啟動和部署。Spring Cloud并沒有重復制造輪子,它只是將各家公司開發的比較成熟、經得起實際考驗的服務框架組合起來,通...

    精品国产乱码久久久久久蜜桃不卡