SpringMVC源码情操陶冶-AbstractUrlHandlerMapping
承接前文SpringMVC源码情操陶冶-AbstractHandlerMapping,前文主要讲解了如何获取handler处理对象,本文将针对beanName注册为handler对象作下解析
AbstractUrlHandlerMapping#registerHandler()-注册handler对象
内部含有两个此方法的重载,分别作简单的介绍
AbstractUrlHandlerMapping#registerHandler(String[] urlPaths, String beanName)-多路径绑定一个bean
多个路径绑定同一个bean,源码奉上
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);
}
}
AbstractUrlHandlerMapping#registerHandler(String urlPath,Object handler)-请求路径绑定bean
注意此处的urlPath参数可以为ant-style模式的值,源码奉上
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;
if (getApplicationContext().isSingleton(handlerName)) {
resolvedHandler = getApplicationContext().getBean(handlerName);
}
}
//是否已存在对应的handler
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("/")) {
//"/"-->设置为roothandler
setRootHandler(resolvedHandler);
}
else if (urlPath.equals("/*")) {
//对"/*"的匹配设置默认的handler
setDefaultHandler(resolvedHandler);
}
else {
//其余的路径绑定关系则存入handlerMap
this.handlerMap.put(urlPath, resolvedHandler);
}
}
}
}
主要的目的只是将绑定关系通过handlerMap存储罢了,那么我们肯定想知道这个registerHandler方法是如何被调用的,且看下文
SimpleUrlHandlerMapping-直接实现类
简单的路径映射处理类,我们先看下其在springmvc中的使用
<bean id="simpleBean" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<pros>
<pro key="/up">up</pro>
<pro key="/down">down</pro>
<pro key="/left">left</pro>
<pro key="/right">right</pro>
</pros>
</property>
</bean>
<bean id="up" class="com.jing.springmvc.test.controller.UpController">
<bean id="down" class="com.jing.springmvc.test.controller.DownController">
<bean id="left" class="com.jing.springmvc.test.controller.LeftController">
<bean id="right" class="com.jing.springmvc.test.controller.RightController">
设置了上述属性后,实例后其会调用SimpleUrlHandlerMapping#setMappings()
public void setMappings(Properties mappings) {
CollectionUtils.mergePropertiesIntoMap(mappings, this.urlMap);
}
在设置了上述的配置以后,SimpleUrlHandlerMapping则会调用AbstractHandlerMapping复写的方法initApplicationContext(),源码奉上
@Override
public void initApplicationContext() throws BeansException {
//这在前文已知主要是获取interceptors
super.initApplicationContext();
//这里便是将上述的配置注册到AbstractUrlHandlerMapping#handlerMap中的入口
registerHandlers(this.urlMap);
}
转而看下上述的SimpleUrlHandlerMapping#registerHandlers(Map urlMap)方法
protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
//urlMap不可为空
if (urlMap.isEmpty()) {
logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
}
else {
for (Map.Entry<String, Object> entry : urlMap.entrySet()) {
String url = entry.getKey();
Object handler = entry.getValue();
// Prepend with slash if not already present.
if (!url.startsWith("/")) {
url = "/" + url;
}
// Remove whitespace from handler bean name.
if (handler instanceof String) {
handler = ((String) handler).trim();
}
//调用父类的注册方法
registerHandler(url, handler);
}
}
}
由以上的代码可知,SimpleUrlHandlerMapping只是对路径进行细心化的处理
对不以"/"开头的路径,加上"/"前缀
对beanName进行去除空字符的处理,且beanName必须是springmvc上下文存在的,否则在绑定的过程中会抛异常
BeanNameUrlHandlerMapping例子
<beans ...>
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<bean id="/welcome.htm"
class="com.mkyong.common.controller.WelcomeController" />
<bean id="/streetName.htm"
class="com.mkyong.common.controller.StreetNameController" />
<bean id="/process*.htm"
class="com.mkyong.common.controller.ProcessController" />
</beans>
小结
1.AbstractUrlHandlerMapping主要是将请求路径绑定beanName,介绍了其直接实现类SimpleUrlHandlerMapping的注册步骤,比较简单,其余的实现类比如BeanNameUrlHandlerMapping会对以"/"开头的beanName注册,具体可自行去分析
2.
SimpleUrlHandlerMapping和BeanNameUrlHandlerMapping其基本都是对以/开头的路径绑定以org.springframework.web.servlet.mvc.Controller为接口实现类,前者间接关联,后者直接关联
SpringMVC源码情操陶冶-AbstractUrlHandlerMapping的更多相关文章
- SpringMVC源码情操陶冶-FreeMarker之web配置
前言:本文不讲解FreeMarkerView视图的相关配置,其配置基本由FreeMarkerViewResolver实现,具体可参考>>>SpringMVC源码情操陶冶-ViewRe ...
- SpringMVC源码情操陶冶-DispatcherServlet
本文对springmvc核心类DispatcherServlet作下简单的向导,方便博主与读者查阅 DispatcherServlet-继承关系 分析DispatcherServlet的继承关系以及主 ...
- SpringMVC源码情操陶冶-AnnotationDrivenBeanDefinitionParser注解解析器
mvc:annotation-driven节点的解析器,是springmvc的核心解析器 官方注释 Open Declaration org.springframework.web.servlet.c ...
- SpringMVC源码情操陶冶-DispatcherServlet父类简析
阅读源码有助于陶冶情操,本文对springmvc作个简单的向导 springmvc-web.xml配置 <servlet> <servlet-name>dispatch< ...
- SpringMVC源码情操陶冶-DispatcherServlet类简析(一)
阅读源码有利于陶冶情操,此文承接前文SpringMVC源码情操陶冶-DispatcherServlet父类简析 注意:springmvc初始化其他内容,其对应的配置文件已被加载至beanFactory ...
- SpringMVC源码情操陶冶-DispatcherServlet简析(二)
承接前文SpringMVC源码情操陶冶-DispatcherServlet类简析(一),主要讲述初始化的操作,本文将简单介绍springmvc如何处理请求 DispatcherServlet#doDi ...
- SpringMVC源码情操陶冶-HandlerAdapter适配器简析
springmvc中对业务的具体处理是通过HandlerAdapter适配器操作的 HandlerAdapter接口方法 列表如下 /** * Given a handler instance, re ...
- SpringMVC源码情操陶冶-AbstractHandlerMethodMapping
承接前文SpringMVC源码情操陶冶-AbstractHandlerMapping,本文将介绍如何注册HandlerMethod对象作为handler 类结构瞧一瞧 public abstract ...
- SpringMVC源码情操陶冶-RequestMappingHandlerAdapter适配器
承接前文SpringMVC源码情操陶冶-HandlerAdapter适配器简析.RequestMappingHandlerAdapter适配器组件是专门处理RequestMappingHandlerM ...
随机推荐
- Codeforces 839E Mother of Dragons【__builtin_popcount()的使用】
E. Mother of Dragons time limit per test:2 seconds memory limit per test:256 megabytes input:standar ...
- UVALive3882-And Then There Was One-约瑟夫问题-递推
And Then There Was One Time limit: 3.000 seconds Let's play a stone removing game. Initially, n ston ...
- [国嵌攻略][148][MTD系统架构]
MTD设备概述 Flash在嵌入式系统中是必不可少的,它是bootloader.Linux内核和文件系统的最佳载体.在Linux内核中引入了MTD子系统为NOR Flash和Nand FLash设备提 ...
- ZOJ 1203 Swordfish
题目: There exists a world within our world A world beneath what we call cyberspace. A world protected ...
- ItemCF_基于物品的协同过滤_MapReduceJava代码实现思路
ItemCF_基于物品的协同过滤 1. 概念 2. 原理 如何给用户推荐? 给用户推荐他没有买过的物品--103 3. java代码实现思路 数据集: 第一步:构建物品的同现矩阵 第 ...
- O2O网站
编辑 020是新型的网络营销模式,O2O即Online To Offline,线下销售与服务通过线上推广来揽客,消费者可以通过线上来筛选需求,在线预订.结算,甚至可以灵活地进行线上预订,线下交易.消费 ...
- socket编程--相关函数--sendto();read();
{1} 头文件:#include <sys/types.h> #include <sys/socket.h>定义函数:int sendto(int s, const voi ...
- JS与ajax遍历list
示例: <script> <c:forEach var="yanan" items="${yananList}"> ...
- junit源码解析总结
前面的博客我们也已经整理到了,我们使用junit38,在写测试类的时候我们的测试类必须继承TestCase.这个所有测试类的父类在junit.framework包下面. 前面我们的整理都是说直接在ID ...
- java里程碑之泛型--泛型注意的几点
1,泛型的基本语法:类名<具体类> 对象名 = new 类名<具体类>().类型参数规范如下: 1),K键,比如映射的键,key的类型 2),V值,比如Map的值,value类 ...