`
sha0k
  • 浏览: 84048 次
  • 性别: 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入门

    NULL 博文链接:https://yihuawuye1.iteye.com/blog/2104547

    Spring MVC核心组件之HandlerMapping详解

    java Spring MVC核心组件之HandlerMapping详解

    spring MVC配置详解

    在使用 Spring MVC 之前,需要引入相应的 jar 包,包括 Spring 2.5.6 和 Hibernate 3.2.0。Spring 2.5.6 需要引入的 jar 包有 spring.jar、spring-webmvc.jar、commons-logging.jar、cglib-nodep-2.1_3.jar 等。...

    org.apache.cxf.spring.remoting.Jsr181HandlerMapping.jar

    org.apache.cxf.spring.remoting.Jsr181HandlerMapping.jar

    全面掌握Spring MVC:从基础到高级的实践指南

    本文通过分析Spring MVC的核心组件和执行流程,提供了一个全面的学习指南。 Spring MVC基于Model-View-Controller(MVC)架构模式,优化了Web应用程序的设计和开发。在Spring MVC中,DispatcherServlet作为前端控制...

    HandlerMapping HandlerAdapter View ViewResolver类图 矢量图

    HandlerMapping HandlerAdapter View ViewResolver类图 矢量图文件 https://blog.csdn.net/qq_39609993/article/details/105435850

    spring3mvc入门资料

    HandlerMapping接口 HandlerAdapter接口 Controller接口 HandlerInterceptor 接口 View接口 LocalResolver接口HandlerExceptionResolver接口 ModelAndView类 。

    Spring MVC运行流程

    Spring MVC运行流程,分七个步骤,1.DispatcherServlet 2.HandlerMapping

    java spring mvc

    5)Spring MVC处理流程 a.首先客户端发出spring mvc请求,请求到达DispatcherServlet主控制器处理(前端控制器) b.主控制器调用HandlerMapping组件,根据请求不同调用Controller处理器 c.主控制器调用Controller方法...

    Spring MVC 学习笔记

    2、 DispatcherServlet把请求转交给HandlerMapping, HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器对象、多个HandlerInterceptor拦截器)对象.(后面会学习到拦截器) 3、 ...

    民宿网站管理系统java+spring.7z,架构是SSM

    Spring MVC 内置了 Requestmapping、HandlerMapping 和 ViewResolver 等组件,可以简化开发流程。MyBatis 作为持久层框架,负责处理数据库操作。 在安全性方面,该网站采用了 SSL 证书进行加密传输,并实现了用户...

    Spring MVC 员工管理系统

    和众多其它Web框架一样,它基于MVC设计理念,此外,由于它采用了松散耦合可插拔组件结构,具有比其它MVC框架更多的扩展性和灵活性。 Spring MVC框架围绕DispatcherServlet这个核心展开,DispatcherServlet的作用是...

    基于spring+java的教务管理系统.7z,SSM框架

    Spring MVC 内置了 Requestmapping、HandlerMapping 和 ViewResolver 等组件,可以简化开发流程。MyBatis 作为持久层框架,负责处理数据库操作。 在安全性方面,该教务管理系统采用了 SSL 证书进行加密传输,并实现...

    spring mvc 思维导图

    Spring的模型-视图-控制器(MVC)框架是围绕一个DispatcherServlet来设计的,这个Servlet会把请求分发给各个处理器,并支持可配置的处理器映射、视图渲染、本地化、时区与主题渲染等,甚至还能支持文件上传。...

    看透springMvc源代码分析与实践

    第1章 网站架构及其演变过程2 1.1 软件的三大类型2 1.2 基础的结构并不简单3 1.3 架构演变的起点5 1.4 海量数据的解决方案5 1.4.1 缓存和页面静态化5 1.4.2 数据库优化6 1.4.3 分离活跃数据8 1.4.4 批量...

    springMVC技术概述

    springMVC相关技术配置使用注解的HandlerMapping和HandlerAdapter使用&lt;mvc:annotation-driver&gt; 不过springBoot已经省略了这些配置 配置使用注解的Handler和Service等等使用&lt;context:component-scan&gt; 不过springBoot...

    SSM框架原理 spring-mvc执行流程

    SSM框架是spring MVC ,spring和mybatis框架的整合,是标准的MVC模式,将整个系统划分为controller层,service层,mapper层三层,通常称为三层架构 使用spring MVC负责请求的转发和视图管理 spring实现业务对象管理...

    Spring MVC工作原理 及注解说明1

    1. 客户端请求提交到DispatcherServlet 2. 由DispatcherServlet控制器查询个或多个HandlerMapping,找到处理 3

    入门案例-SpringMVC技术架构图

    Spring MVC以DispatcherServlet为核心,众多组件如HandlerMapping为辅助,为用户封装了请求映射等底层逻辑,让用户可以更专注与业务逻辑的处理。本文会对Spring MVC整体结构做简单介绍。 Spring MVC结构图 Spring ...

    spring mvc

    只有对应的HandlerMapping (为了实现类型级别的注解)和/ 或HandlerAdapter (为了实现方法级别的注解)出现在 dispatcher中时, @RequestMapping 才会被处理。 这在DispatcherServlet 和DispatcherPortlet 中都是...

Global site tag (gtag.js) - Google Analytics