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 ...
随机推荐
- Netty的并发编程实践4:线程安全类的应用
在JDK1.5的发行版本中,Java平台新增了java.util.concurrent,这个包中提供了一系列的线程安全集合.容器和线程池,利用这些新的线程安全类可以极大地降低Java多线程编程的难度, ...
- 【原】Java学习笔记030 - 异常
package cn.temptation; public class Sample01 { public static void main(String[] args) { /* * 异常:Java ...
- 一个仿3D的平面游戏页面
package com.totoo.TouhouMassLight;import android.os.Bundle;import android.view.MotionEvent;import an ...
- 【BZOJ2037】Sue的小球(动态规划)
[BZOJ2037]Sue的小球(动态规划) 题面 BZOJ 题解 莫名想到这道题目 很明显是一样的 设\(f[i][j][0/1]\)表示已经接到了\(i-j\)这一段的小球 当前在\(i\)或者在 ...
- PHP 接口 返回构造函数
我们写接口的时候,需要返回json数据,并且里面有错误码,错误信息 还有要返回的数据,这里我构造了一个函数 这里是针对TP5来写的,自己可以根据自己的框架来修改 这样就可以在返回的时候直接用info函 ...
- PHP/JAVA 杂谈 一(php 槽点)
[本文为个人意见,不喜就喷吧!] 最近,同事问到我,『那时候为什么从PHP转成Java?』,我想了很久,且撇开主观上的原因,当初业务重构使用java确实有很多可以说道的地方. 槽点1:哪有最好的语言, ...
- SqlServer之like、charindex、patindex 在有无索引的情况下分析
1.环境介绍 测试环境 SQL2005 测试数据 200W条 2.环境准备 2.1建表 CREATE TABLE [dbo].[Depratments]( [Dep_id] [int] ...
- [转]Git教程【译】
[转]Git教程[译] http://www.cnblogs.com/zhangjing230/archive/2012/05/09/2489745.html 原文出处:http://www.voge ...
- 机器学习实战笔记(Python实现)-09-树回归
---------------------------------------------------------------------------------------- 本系列文章为<机 ...
- 在Editplus中配置java的(带包)编译(javac)和运行(java)的方法
配置的前提是电脑安装了JDK并且配置好了相关的环境变量(JAVA_HOME,path和classpath). 配置好后在命令行中输入javac和java验证是否配置成功: 如果出现上面的情况则说明配置 ...