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 ...
随机推荐
- udp协议的数据接收与发送的代码
我想基于lwIP协议中的UDP协议,用单片机做一个服务器,接受电脑的指令然后返回数据.以下是我的代码 /************************************************ ...
- vxi总线
20世纪80年代后期,仪器制造商发现GPIB总线和VME总线产品无法再满足军用测控系统的需求了.在这种情况下,HP.Tekronix等五家国际著名的仪器公司成立了VXIbus联合体,并于1987年发布 ...
- es6的新特性--模板字符串
这几天简单看了一下深入浅出es6这本书,感觉特实用,学习了一个新特性---模板字符串在项目开发中,拼接字符串是不可缺少的,动态创建dom元素以及js操作数据都要拼接字符串,在es6出来之前,我们都通常 ...
- Blending, Bootstrap
听林轩田老师的<机器学习技法>,Lecture 7讲到model的blending. 理解了一个之前一直模棱两可的概念:bootstrap. 先说一下什么是blending.在机器学习中, ...
- ASP.NET CORE入门之读取Json配置文件
首先新建一.net core控制台项目,命名为jsonReader 然后选中引用,选择NuGet包管理器,点击浏览引入mircosoft.aspnetcore.all并安装 选中解决方案,填加,新建项 ...
- Python 学习笔记(二)开发环境的搭建
安装Python windows 下安装: 下载地址:https://www.python.org/downloads Python的版本 3.x 是趋势 2.x 还在被大量使用 至于使用2.x 还是 ...
- 零基础新手学习Java必须知道的市场行情
Java如今的市场不如从前,竞争很大,工资非常高,标准非常高,想要胜任一份高薪的工作不是那么容易,只有掌握最新的行情才能更好的了解Java,才能更好的在这个领取发展,让新手小白了解Java市场行情如下 ...
- A Dream (PKUWC 2018)
A Dream (PKUWC 2018) 这是一个梦. 从没有几分节日气氛的圣诞,做到了大雪纷飞的数九寒天. 忘了罢! 不记得时间,不记得地点.随着记忆的褪去,一切也只会不复存在. Day-34? D ...
- 【SPOJ】Longest Common Substring(后缀自动机)
[SPOJ]Longest Common Substring(后缀自动机) 题面 Vjudge 题意:求两个串的最长公共子串 题解 \(SA\)的做法很简单 不再赘述 对于一个串构建\(SAM\) 另 ...
- 【HNOI2011】数学作业
分段矩乘即可 # include <stdio.h> # include <stdlib.h> # include <iostream> # include < ...