Spring MVC的handlermapping之BeanNameUrlHandlerMapping初始化
先介绍一下:
BeanNameUrlHandlerMapping是基于配置文件的方式; 所有处理器需要在XML文件中,以Bean的形式配置。
缺点:配置繁琐; 如果多个URL对应同一个处理器,那么需要配置多条,同时也会实例化多个对象等等。。。
因为springmvc 是基于spring的,所以他的初始化肯定是在spring容器初始化之后才进行的。
先上类图:

可以看到BeanNameUrlHandlerMapping父类最终实现了ApplicationContextAware接口,所以Spring容器会自动注入ApplicationContext,方法为:
public final void setApplicationContext(ApplicationContext context) throws BeansException {
if (context == null && !this.isContextRequired()) {
this.applicationContext = null;
this.messageSourceAccessor = null;
} else if (this.applicationContext == null) {
if (!this.requiredContextClass().isInstance(context)) {
throw new ApplicationContextException("Invalid application context: needs to be of type [" + this.requiredContextClass().getName() + "]");
}
this.applicationContext = context;
this.messageSourceAccessor = new MessageSourceAccessor(context);
this.initApplicationContext(context); //这块实际上是一个钩子方法,供子类去覆盖! 进行初始化工作
} else if (this.applicationContext != context) {
throw new ApplicationContextException("Cannot reinitialize with different application context: current one is [" + this.applicationContext + "], passed-in one is [" + context + "]");
}
}
AbstractHandlerMapping: 这个类就是复写了这个方法 进行了拦截器的初始化
protected void initApplicationContext() throws BeansException {
this.extendInterceptors(this.interceptors); //供子类扩展拦截器
this.detectMappedInterceptors(this.mappedInterceptors);//扫描应用下的MappedInterceptor,并添加到mappedInterceptors
this.initInterceptors();//归集MappedInterceptor,并适配HandlerInterceptor和WebRequestInterceptor
}
AbstractDetectingUrlHandlerMapping :同样重写这个方法,实现自己的逻辑
public void initApplicationContext() throws ApplicationContextException {
super.initApplicationContext();
this.detectHandlers();
}
protected void detectHandlers() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Looking for URL mappings in application context: " + this.getApplicationContext());
}
// 扫描应用下所有的Object类
String[] beanNames = this.detectHandlersInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.getApplicationContext(), Object.class) : this.getApplicationContext().getBeanNamesForType(Object.class);
String[] arr$ = beanNames;
int len$ = beanNames.length;
for(int i$ = ; i$ < len$; ++i$) { //遍历每一个扫描出来的类
String beanName = arr$[i$];
String[] urls = this.determineUrlsForHandler(beanName); //钩子方法,让子类去实现,通过handler解析url
if (!ObjectUtils.isEmpty(urls)) {
this.registerHandler(urls, beanName); //返回的URL进行注册,实际上就是放到AbstractUrlHandlerMapping的一个map中
} else if (this.logger.isDebugEnabled()) {
this.logger.debug("Rejected bean name '" + beanName + "': no URL paths identified");
}
}
}
BeanNameUrlHandlerMapping:实际上就实现了determineUrlsForHandler这个方法:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package org.springframework.web.servlet.handler; import java.util.ArrayList;
import java.util.List;
import org.springframework.util.StringUtils; public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {
public BeanNameUrlHandlerMapping() {
} protected String[] determineUrlsForHandler(String beanName) {
List<String> urls = new ArrayList();
if (beanName.startsWith("/")) { //只有一点需要注意 就是bean id 必须是以'/'开头
urls.add(beanName);
} String[] aliases = this.getApplicationContext().getAliases(beanName);
String[] arr$ = aliases;
int len$ = aliases.length; for(int i$ = ; i$ < len$; ++i$) {
String alias = arr$[i$];
if (alias.startsWith("/")) {
urls.add(alias);
}
} return StringUtils.toStringArray(urls);
}
}
AbstractUrlHandlerMappin:中注册处理器的方法:
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;
if (!this.lazyInitHandlers && handler instanceof String) {
String handlerName = (String)handler;
if (this.getApplicationContext().isSingleton(handlerName)) {
resolvedHandler = this.getApplicationContext().getBean(handlerName);
}
}
Object mappedHandler = this.handlerMap.get(urlPath);
if (mappedHandler != null) {
if (mappedHandler != resolvedHandler) { //不允许存在相同url不同handler,否则抛异常
throw new IllegalStateException("Cannot map " + this.getHandlerDescription(handler) + " to URL path [" + urlPath + "]: There is already " + this.getHandlerDescription(mappedHandler) + " mapped.");
}
} else if (urlPath.equals("/")) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Root mapping to " + this.getHandlerDescription(handler));
}
this.setRootHandler(resolvedHandler);
} else if (urlPath.equals("/*")) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Default mapping to " + this.getHandlerDescription(handler));
}
this.setDefaultHandler(resolvedHandler);
} else { //这才是正常的存储逻辑
this.handlerMap.put(urlPath, resolvedHandler);
if (this.logger.isInfoEnabled()) {
this.logger.info("Mapped URL path [" + urlPath + "] onto " + this.getHandlerDescription(handler));
}
}
}
到这里实际上处理器映射器的保存工作就算完事了。
实际上handlerMapping这一块,主要思路就是 写一个模板类,来处理公共的方法,如初始化拦截器,然后留下钩子方法,让子类去实现自己的逻辑就好了。
Spring MVC的handlermapping之BeanNameUrlHandlerMapping初始化的更多相关文章
- Spring MVC的handlermapping之SimpleUrlHandlerMapping初始化
前面信息同BeanNameUrlHandlerMapping,这里不再过多分析,详情请看 :Spring MVC的handlermapping之BeanNameUrlHandlerMapping初始化 ...
- Spring MVC的handlermapping之RequestMappingHandlerMapping初始化
RequestMappingHandlerMapping:这个handlerMapping是基于注解的同样,先上类图: 通过类图可以看到,同样是继承父类 AbstractHandlerMapping来 ...
- Spring MVC的handlermapping之请求分发如何找到正确的Handler(BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping)
本文讲的是Spring MVC如何找到正确的handler, 前面请求具体怎么进入到下面的方法,不再细说. 大概就是Spring mvc通过servlet拦截请求,实现doService方法,然后进入 ...
- Spring MVC 梳理 - handlerMapping和handlerAdapter分析
参考图片 综上所述我们来猜测一下spring mvc 中根据URL找到处理器Controller中相应方法的流程 ①:获取Request的URL ②:从UrlLookup这个map中找到相应的requ ...
- spring mvc(4) HandlerMapping
在前面一节里提到,DispatcherServlet在接收到请求后,通过HandlerMapping找到处理请求对应的Controller(其实处理请求器并不一定是Controller,还可以是Htt ...
- spring mvc 自定义Handlermapping
上次大概写了个可以解决velocity 多视图的东西. 但是实际运用过程中又到处找了些资料看了下.这里 小计下: DispatcherServlet解析过程: ..1..HandlerMapping. ...
- Spring MVC:HandlerMapping
HandlerMapping 的类图 Spring中存在两种类型的handlers.第一种是 handler mappings(处理程序映射).它们的角色定位与前面所描述的功能完全相同.它们尝试将当前 ...
- Spring MVC 上下文(ApplicationContext)初始化入口
Spring 常用上下文容器有哪些 ApplicationContext ClassPathXmlApplicationContext ApplicationContext context = new ...
- Spring MVC的handlermapping之请求分发如何找到正确的Handler(RequestMappingHandlerMapping)
这个思路同样是通过在AbstractHandlerMethodMapping里面来实现getHandlerInternal()实现自己的方法来处理寻找正确的处理器,不懂得请看上一篇. protecte ...
随机推荐
- 【mongodb系统学习之六】mongodb配置文件方式启动
六.mongodb可以用配置文件启动,配置文件配好后,每次指定文件就好,而不用每次写一长串: 1).创建配置文件: 2).配置(例如指定数据存储目录,日志存储文件,后台进程,端口号等): 3).配置文 ...
- zTree实现地市县三级级联Service接口测试
zTree实现地市县三级级联Service接口测试 ProvinceServiceTest.java: /** * @Title:ProvinceServiceTest.java * @Package ...
- java.lang.ArrayIndexOutOfBoundsException
1.错误描述 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0 at com.you.m ...
- Flex动态获取数据,服务中断报错
1.错误原因 2.错误原因 由上面提示可知,软件引起的链接中断,导致出错 3.解决办法 检查数据库链接,重新启动服务
- hihocoder Challenge 29 D. 不上升序列
这场爆零比赛题目还是要补的 这道题据说是出烂掉的原题,我找了下 CF13.C/ CF371 div1 C,一模一样 我服这群原题大佬 为 当时,使 不严格递增的最小步数,那么 Otherwise 显然 ...
- [UOJ207]共价大爷游长沙
UOJ sol 这题真是太神啦! 对于S集合中的每个点对,给他们随机附上一个相同权值. 两个点在边(x,y)的两侧当且仅当一个点在x的子树中,另一个点不在x的子树中(假设x是y的儿子) 维护一下子树点 ...
- 关于C++ const 的全面总结《转》
C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,本人根据各方面查到的资料进行总结如下,期望对朋友们有所帮助. Const 是C++中常用的类型修饰符,常类型是指使用类 ...
- 大三小学期 Android开发的一些经验
1.同一个TextView几种颜色的设置: build=(TextView)findViewById(R.id.building); SpannableStringBuilder style = ne ...
- 通过返回动态改变textview和imageview
//获取并显示优惠券ID Intent intent = getIntent(); awardID=(TextView)findViewById(R.id.awardID); String id = ...
- Bond UVA - 11354(LCA应用题)
Once again, James Bond is on his way to saving the world. Bond's latest mission requires him to trav ...