`
sha0k
  • 浏览: 84882 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Spring MVC 源码学习札记(四)HandlerMapping和HandlerAdapter(1)

 
阅读更多

在分析HandlerMapping和HandlerAdapter以及其子类关系和代码之前,我们先来看看DispatcherServlet对它们的初始化是怎样的,在DispatcherServlet类中,有HandlerMapping和HandlerAdapter的链表。

/** List of HandlerMappings used by this servlet */
	private List<HandlerMapping> handlerMappings;

	/** List of HandlerAdapters used by this servlet */
	private List<HandlerAdapter> handlerAdapters;

  下面的布尔属性是DispatcherServlet中用来标记探测结果的,true表示探测所有的HandlerMapping,false表示只探测已在***-servlet.xml中声明的handlerMapping bean,Adapter同上。

/** Detect all HandlerMappings or just expect "handlerMapping" bean? */
	private boolean detectAllHandlerMappings = true;

	/** Detect all HandlerAdapters or just expect "handlerAdapter" bean? */
	private boolean detectAllHandlerAdapters = true;
 

下面是HandlerMapping的初始化方法:

/**
	 * Initialize the HandlerMappings used by this class.
	 * <p>If no HandlerMapping beans are defined in the BeanFactory for this namespace,
	 * we default to BeanNameUrlHandlerMapping.
	 */
	private void initHandlerMappings(ApplicationContext context) {
		this.handlerMappings = null;

		if (this.detectAllHandlerMappings) {
			// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
			Map<String, HandlerMapping> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
				// We keep HandlerMappings in sorted order.
				OrderComparator.sort(this.handlerMappings);
			}
		}
		else {
			try {
				HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
				this.handlerMappings = Collections.singletonList(hm);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default HandlerMapping later.
			}
		}

		// Ensure we have at least one HandlerMapping, by registering
		// a default HandlerMapping if no other mappings are found.
		if (this.handlerMappings == null) {
			this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
			if (logger.isDebugEnabled()) {
				logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
			}
		}
	}

 前面的一个if...else...很好理解,就是根据是否探测上下文中所有bean name不管是handlerMapping还是不是的HandlerMapping实体bean。第二个if,当在上下文中没有找到注册的HandlerMapping时进入该条件,注意方法getDefaultStrategies,它有两个参数,一个是上下文,一个是Class对象。

/**
	 * Create a List of default strategy objects for the given strategy interface.
	 * <p>The default implementation uses the "DispatcherServlet.properties" file (in the same
	 * package as the DispatcherServlet class) to determine the class names. It instantiates
	 * the strategy objects through the context's BeanFactory.
	 * @param context the current WebApplicationContext
	 * @param strategyInterface the strategy interface
	 * @return the List of corresponding strategy objects
	 */
	@SuppressWarnings("unchecked")
	protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
		String key = strategyInterface.getName();
		String value = defaultStrategies.getProperty(key);
		if (value != null) {
			String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
			List<T> strategies = new ArrayList<T>(classNames.length);
			for (String className : classNames) {
				try {
					Class clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
					Object strategy = createDefaultStrategy(context, clazz);
					strategies.add((T) strategy);
				}
				catch (ClassNotFoundException ex) {
					throw new BeanInitializationException(
							"Could not find DispatcherServlet's default strategy class [" + className +
									"] for interface [" + key + "]", ex);
				}
				catch (LinkageError err) {
					throw new BeanInitializationException(
							"Error loading DispatcherServlet's default strategy class [" + className +
									"] for interface [" + key + "]: problem with class file or dependent class", err);
				}
			}
			return strategies;
		}
		else {
			return new LinkedList<T>();
		}
	}

 String key这一行就不用解释了,就是得到类名,请看第二行

String value = defaultStrategies.getProperty(key);

这里defaultStrategies是DispatcherSerlvet的属性

private static final Properties defaultStrategies;

	static {
		// Load default strategy implementations from properties file.
		// This is currently strictly internal and not meant to be customized
		// by application developers.
		try {
			ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
			defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
		}
		catch (IOException ex) {
			throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + ex.getMessage());
		}
	}
 
/**
	 * Name of the class path resource (relative to the DispatcherServlet class) that defines DispatcherServlet's default
	 * strategy names.
	 */
	private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";

 在DispatcherServlet的静态域,即第一次实例化该类时,运行的区域,读取了DispatcherSerlvet.properties这个配置文件,Properties类就不解释了,打开源码目录的时候,我们可以看到在DispatcherSerlvet.java的同级目录下有这个配置文件K=V。

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

 可以看到HandlerMapping的默认类有BeanNameUrlHandlerMapping(bean和Url直直接映射的解析HandlerMapping),DefaultAnnotationHandlerMapping(默认注解支持的HandlerMapping)。

我们继续向下看getDefaultStrategies部分的源码,当得到value的String值之后,将String进行破分,变为String数组,并对BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping进行bean的创建,使用语句

Object strategy = createDefaultStrategy(context, clazz);

 该方法内部:

protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) {
		return context.getAutowireCapableBeanFactory().createBean(clazz);
	}

 将创建后的bean加入到链表strategies中并返回。

这样HandlerMapping的链表就初始化完成了。

HandlerAdapter也是同理。

这一篇已经太长了,所以将重点介绍放在下一节。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2
1
分享到:
评论

相关推荐

    SpringMVC源码总结(一)HandlerMapping和HandlerAdapter入门

    在本篇博客“SpringMVC源码总结(一)HandlerMapping和HandlerAdapter入门”中,我们将探讨Spring MVC框架的核心组件——HandlerMapping和HandlerAdapter。这两个组件是Spring MVC处理请求的关键,它们负责映射HTTP...

    Spring MVC源码深度剖析开源架构源码2021.pdf

    Spring MVC是Java EE开发中广泛使用的一个Web框架,它是Spring框架的一部分,主要负责Model-View-Controller(MVC)架构模式的...通过学习和实践,开发者可以更有效地利用Spring MVC框架来构建高性能的Web应用程序。

    开发Spring MVC应用程序补充—程序源码下载.rar_spring_spring mvc_spring mvc 源码_sp

    标题中的"开发Spring MVC应用程序补充—程序源码下载.rar_spring_spring mvc_spring mvc 源码_sp"表明这是一个关于Spring MVC框架的开发教程,其中包含了源代码供学习者参考。Spring MVC是Spring框架的一个核心组件...

    springmvc项目源码

    通过深入学习这个 Spring MVC 项目源码,你可以掌握 MVC 设计模式的运用,了解 Spring 框架的组件协同工作方式,以及在实际项目中的最佳实践。这将有助于提升你的 Java Web 开发技能,更好地理解和使用 Spring MVC。

    spring mvc mybatis 整合源码,带数据库脚本,带详细注释

    - 学习Spring MVC和MyBatis的整合,可以参考官方文档、教程和开源项目的源码。 - 通过调试源码,理解其实现原理,有助于提升实战技能。 总结,这个压缩包提供了一个完整的Spring MVC和MyBatis整合的示例,包含了...

    Spring MVC jar包

    而`spring-framework-2.5.6-with-docs.zip`可能包含了Spring 2.5.6的源码和文档,帮助开发者了解Spring MVC的内部实现和最佳实践。 总之,这个压缩包提供了开发基于Spring MVC和Hibernate的Java Web应用所需要的...

    Spring5MVC源码.docx

    【Spring5MVC源码分析】 Spring MVC 是一个基于Java的、用于构建Web应用程序的、高度可插拔的MVC框架,它是Spring Framework的重要组成部分。Spring MVC的核心目标是简化前端控制器的开发,使得开发者可以专注于...

    精通spring mvc 4 看透springmvc pdf 高清完全版

    本书首先介绍了Spring MVC的基础知识,包括如何搭建Spring MVC环境,以及它的核心组件如DispatcherServlet、ModelAndView、HandlerMapping和HandlerAdapter等的工作原理。这些组件在Web请求处理过程中扮演着重要角色...

    spring mvc 的入门级资料

    在 Spring MVC 中,核心类和接口是 DispatcherServlet、HandlerMapping、HandlerAdapter、Controller、ViewResolver、HandlerInterceptor、View 等。 DispatcherServlet 是 Spring MVC 的前置控制器,它负责处理...

    Spring MVC核心组件之HandlerMapping详解

    ### Spring MVC核心组件之HandlerMapping详解 #### 一、引言 在Java Web开发领域,Spring MVC框架因其灵活且强大的特性而备受青睐。...理解和掌握`HandlerMapping`的工作机制对于深入学习Spring MVC框架至关重要。

    Spring MVC 基础实例源码01

    这个"Spring MVC 基础实例源码01"的资源很可能是为了帮助初学者理解Spring MVC的核心概念和基本用法。下面我们将详细探讨Spring MVC的一些关键知识点。 1. **MVC模式**:MVC(Model-View-Controller)是一种设计...

    spring mvc框架源码

    通过深入研究源码,我们可以更好地理解Spring MVC的运行机制,如何配置和使用其特性,以及如何优化和调试Spring MVC应用。对于开发人员来说,掌握Spring MVC的源码分析有助于提升Web应用开发的效率和质量。

    spring MVC基础学习

    - 创建Spring MVC的配置文件,例如`servlet-context.xml`,配置HandlerMapping、HandlerAdapter、ViewResolver等组件。 - 在配置文件中声明Controller Bean,通常使用注解@Controller。 3. **注解驱动开发**: -...

    Spring MVC 学习记录总结1

    在这个学习记录总结中,我们将深入理解Spring MVC的核心概念、主要组件以及其工作流程。 1. Spring MVC 概述 Spring MVC 是Spring框架的一部分,它基于Spring IoC(Inversion of Control,控制反转)容器,简化了...

    spring mvc与mybatis的集成

    2. **配置 Spring**:在 `applicationContext.xml` 或者 Spring Boot 的配置文件中,配置 Spring MVC 的 DispatcherServlet、HandlerMapping 和 HandlerAdapter。同时,配置 Spring 的 DataSource,这是连接数据库的...

    spring-webmvc-5.0.9 jar包、源码和javadoc

    spring-webmvc-5.0.9.RELEASE-sources.jar则包含了源码,可以深入研究Spring Web MVC的实现细节,对于学习和调试都非常有帮助。 九、依赖管理 在实际项目中,Spring Web MVC往往与其他Spring模块如Core、AOP、Data...

    Spring.MVC学习指南.pdf

    这份“Spring.MVC学习指南.pdf”很可能是为了帮助开发者深入理解和掌握Spring MVC的核心概念、工作原理以及实践技巧。下面将详细阐述Spring MVC的相关知识点。 1. **核心组件**: - **DispatcherServlet**:Spring...

    Spring MVC Helloword代码

    3. **创建Spring MVC配置**:创建一个XML文件(如`servlet-context.xml`),配置HandlerMapping、HandlerAdapter、视图解析器等。 4. **编写Controller**:创建一个名为`GreetingController`的Java类,使用`@...

    Spring MVC简单例子

    8. **配置文件**:理解Spring MVC的配置文件,如`servlet-context.xml`,它定义了Spring MVC的组件,如视图解析器、HandlerMapping和HandlerAdapter等。 9. **Maven或者Gradle构建**:项目可能使用Maven或Gradle...

    spring-mvc-showcase

    此外,该项目还展示了如何配置 Spring MVC,例如在 web.xml 中配置 DispatcherServlet,以及在 Spring 配置文件中定义 HandlerMapping 和 HandlerAdapter 等。这有助于理解 Spring MVC 的工作流程。 "spring-mvc-...

Global site tag (gtag.js) - Google Analytics