跳至主要內容

9. BeanNameUrlHandlerMapping

安图新大约 2 分钟

9. BeanNameUrlHandlerMapping

前言

BeanNameUrlHandlerMapping 处理容器中以/开头的 bean

一、初始化

BeanNameUrlHandlerMapping 间接继承了 ApplicationContextAware,因此创建 bean 的过程中会回调
initApplicationContext( )

(1)initApplicationContext( )

public void initApplicationContext() throws ApplicationContextException {


		super.initApplicationContext();
		//找/开头的handler
		detectHandlers();
	}

(2)detectHandlers()

protected void detectHandlers() throws BeansException {


		//获取ApplicationContext
		ApplicationContext applicationContext = obtainApplicationContext();
		//获取容器中所有的beanNames
		String[] beanNames = (this.detectHandlersInAncestorContexts ?
				BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
				applicationContext.getBeanNamesForType(Object.class));

		// Take any bean name that we can determine URLs for.
		for (String beanName : beanNames) {


			//找/开头的url或alials
			String[] urls = determineUrlsForHandler(beanName);
			if (!ObjectUtils.isEmpty(urls)) {


				// URL paths found: Let's consider it a handler.
				//注册到缓存中
				registerHandler(urls, beanName);
			}
		}

		if (mappingsLogger.isDebugEnabled()) {


			mappingsLogger.debug(formatMappingName() + " " + getHandlerMap());
		}
		else if ((logger.isDebugEnabled() && !getHandlerMap().isEmpty()) || logger.isTraceEnabled()) {


			logger.debug("Detected " + getHandlerMap().size() + " mappings in " + formatMappingName());
		}
	}

(3)determineUrlsForHandler( )

protected String[] determineUrlsForHandler(String beanName) {


		List<String> urls = new ArrayList<>();
		if (beanName.startsWith("/")) {


			//beanName以/开头
			urls.add(beanName);
		}
		String[] aliases = obtainApplicationContext().getAliases(beanName);
		for (String alias : aliases) {


			if (alias.startsWith("/")) {


				//别名以/开头
				urls.add(alias);
			}
		}
		return StringUtils.toStringArray(urls);
	}

(4)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);
		}
	}

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)) {


				//初始化bean
				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 (getPatternParser() != null) {


					this.pathPatternHandlerMap.put(getPatternParser().parse(urlPath), resolvedHandler);
				}
				if (logger.isTraceEnabled()) {


					logger.trace("Mapped [" + urlPath + "] onto " + getHandlerDescription(handler));
				}
			}
		}
	}

二、使用

创建 controller,继承 springmvc 的 AbstractController ,重写 handleRequestInternal( )方法,
当请求访问/beanName 路径时,会回调 handleRequestInternal( )

@Controller("/beanName")
public class BeanNameUrlController extends AbstractController {


    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {


        System.out.println("BeanNameUrlController");
        return null;
    }
}