BeanNameUrlHandlerMapping处理器

2023-07-30  本文已影响0人  程序员札记

BeanNameUrlHandlerMapping是什么

其实这个就是在用bean注解方法的时候填写的名字作为uri和bean处理器映射。先看例子,比如我定义了两种老的写法的处理器:

image.png image.png

然后我在配置文件中注入他们,都命名了:


image.png

然后访问:


image.png image.png

好像也挺方便哦,但是都要实现接口,而且方法参数是死的,无法做到直接获取需要的参数值,而ResourceHttpRequestHandler更强大,他可以任意传参数,只要能匹配的上都可以匹配,等于定制化,灵活,你可以实现任何你想要的参数类型,只要你编写解析器。我们来说说原理吧。

BeanNameUrlHandlerMapping初始化

他也是EnableWebMvcConfiguration创建的:

image.png

AbstractDetectingUrlHandlerMapping的detectHandlers

但是在ApplicationContextAwareProcessor的初始化之前的方法postProcessBeforeInitialization中,最后进行了处理器探测detectHandlers

protected void detectHandlers() throws BeansException {
        ApplicationContext applicationContext = obtainApplicationContext();
        String[] beanNames = (this.detectHandlersInAncestorContexts ?
                BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
                applicationContext.getBeanNamesForType(Object.class));

        // 遍历所有容器里的beanName,找出beanName有uri的注册进去
        for (String beanName : beanNames) {
            String[] urls = determineUrlsForHandler(beanName);
            if (!ObjectUtils.isEmpty(urls)) {
                // URL paths found: Let's consider it a handler.
                registerHandler(urls, beanName);
            }
        }

        if ((logger.isDebugEnabled() && !getHandlerMap().isEmpty()) || logger.isTraceEnabled()) {
            logger.debug("Detected " + getHandlerMap().size() + " mappings in " + formatMappingName());
        }
    }

BeanNameUrlHandlerMapping的determineUrlsForHandler

名字或者别名以/开头的都放入url集合里。

@Override
    protected String[] determineUrlsForHandler(String beanName) {
        List<String> urls = new ArrayList<>();
        if (beanName.startsWith("/")) {
            urls.add(beanName);
        }
        String[] aliases = obtainApplicationContext().getAliases(beanName);
        for (String alias : aliases) {
            if (alias.startsWith("/")) {
                urls.add(alias);
            }
        }
        return StringUtils.toStringArray(urls);
    }

AbstractUrlHandlerMapping的registerHandler注册处理器

    protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException {
        Assert.notNull(urlPaths, "URL path array must not be null");
        for (String urlPath : urlPaths) {
            registerHandler(urlPath, beanName);
        }
    }

首先看不是懒初始化的单例且处理器只是个名字的话就直接实例化,然后判断重复,根据url的不同,设置不同的处理器,一般的就是放入url和处理器的映射集合。

    protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
        Assert.notNull(urlPath, "URL path must not be null");
        Assert.notNull(handler, "Handler object must not be null");
        Object resolvedHandler = handler;

        // Eagerly resolve handler if referencing singleton via name.
        if (!this.lazyInitHandlers && handler instanceof String) {
            String handlerName = (String) handler;
            ApplicationContext applicationContext = obtainApplicationContext();
            if (applicationContext.isSingleton(handlerName)) {
                resolvedHandler = applicationContext.getBean(handlerName);
            }
        }

        Object mappedHandler = this.handlerMap.get(urlPath);
        if (mappedHandler != null) {
            if (mappedHandler != resolvedHandler) {
                throw new IllegalStateException(
                        "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
                        "]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
            }
        }
        else {
            if (urlPath.equals("/")) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Root mapping to " + getHandlerDescription(handler));
                }
                setRootHandler(resolvedHandler);
            }
            else if (urlPath.equals("/*")) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Default mapping to " + getHandlerDescription(handler));
                }
                setDefaultHandler(resolvedHandler);
            }
            else {
                this.handlerMap.put(urlPath, resolvedHandler);
                if (logger.isTraceEnabled()) {
                    logger.trace("Mapped [" + urlPath + "] onto " + getHandlerDescription(handler));
                }
            }
        }
    }

处理原理

至于他的处理原理,还是获取处理器的方法lookupHandler,其实他和SimpleUrlHandlerMapping一样,都是AbstractDetectingUrlHandlerMapping的子类,所以实现是一样的,都是AbstractDetectingUrlHandlerMapping实现的,这个上几篇有讲过了,就不多说了。

image.png
上一篇 下一篇

猜你喜欢

热点阅读