SpringMvc源码分析--配置文件解析

2023-05-16

        我们简单分析一下springmvc配置解析过程,我个人认为理解这个过程对于后续学习是有帮助的,毕竟配置文件是入口。

一、认识springmvc.xml配置文件

        下面这个是springmvc中的配置,与spring的配置类似,只不过里面增加了springmvc特有的配置项,假设以default-servelt-handler举例说明。

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/context
                            https://www.springframework.org/schema/context/spring-context.xsd
                            http://www.springframework.org/schema/mvc
                            https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="com.example.controller"/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <mvc:default-servlet-handler/>
 ...
</beans>

二、入口

2.1、如何找到入口呢?

这里有简单说一下我的学习方式,具体有两种方式:

1)我们打开spring代码目录,可以通过代码目录进行猜测,因为spring的代码结构比较清晰,所以这种方式是最快的,虽然不能一次性找对,但多点几个文件也是可以找到的

2)搜索+断点调试

        这种方法如果如果匹配串准确度比较高,应该也能很快找到对应的文件,举个反例比如:搜bean可能会搜出很多文件,这样的字段就不是适合搜索。当我们找到怀疑的文件,就可以直接通过断点调试方式,来确定是不是最终能进到方法中。

2.2、注册解析器

springmvc配置文件中能用到的所有标签都在下面定义中

/**
 * {@link NamespaceHandler} for Spring MVC configuration namespace.
 *
 * @author Keith Donald
 * @author Jeremy Grelle
 * @author Sebastien Deleuze
 * @since 3.0
 * 用于解析springmvc配置文件中的配置项
 */
public class MvcNamespaceHandler extends NamespaceHandlerSupport {

	@Override
	public void init() {
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
		registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
		registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
		registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
		registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
		registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
		registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
		registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
		registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
		registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
		registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
		registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
	}

}

三、default-servlet-handler解析器

        default-servlet-handler解析器代码比较少,结构清晰,在实际开发中肯定会用的,所以用这个进行分析。

class DefaultServletHandlerBeanDefinitionParser implements BeanDefinitionParser {
	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		Object source = parserContext.extractSource(element);

		String defaultServletName = element.getAttribute("default-servlet-name"); //获取属性的值
		//创建BeanDefinition
		RootBeanDefinition defaultServletHandlerDef = new RootBeanDefinition(DefaultServletHttpRequestHandler.class);
		defaultServletHandlerDef.setSource(source);
		defaultServletHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		if (StringUtils.hasText(defaultServletName)) {
			defaultServletHandlerDef.getPropertyValues().add("defaultServletName", defaultServletName);
		}
		//注册到BeanDefinitionRegistry
		String defaultServletHandlerName = parserContext.getReaderContext().generateBeanName(defaultServletHandlerDef);
		parserContext.getRegistry().registerBeanDefinition(defaultServletHandlerName, defaultServletHandlerDef);
		parserContext.registerComponent(new BeanComponentDefinition(defaultServletHandlerDef, defaultServletHandlerName));

        //这里很关键,将处理器映射器和Servlet进行关联
		Map<String, String> urlMap = new ManagedMap<>();
		urlMap.put("/**", defaultServletHandlerName); //处理所有请求

		//创建BeanDefinition,这个SimplerUrlHandlerMapping也是一个处理器映射器
		RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);
		handlerMappingDef.setSource(source);
		handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		handlerMappingDef.getPropertyValues().add("urlMap", urlMap);
		//注册到BeanDefinitionRegistry
		String handlerMappingBeanName = parserContext.getReaderContext().generateBeanName(handlerMappingDef);
		parserContext.getRegistry().registerBeanDefinition(handlerMappingBeanName, handlerMappingDef);
		parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, handlerMappingBeanName));

		// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
        //注册各种组件 比如说适配器,拦截器
		MvcNamespaceUtils.registerDefaultComponents(parserContext, source);

		return null;
	}
}
	public static void registerDefaultComponents(ParserContext context, @Nullable Object source) {
		registerBeanNameUrlHandlerMapping(context, source);
		registerHttpRequestHandlerAdapter(context, source);//适配器
		registerSimpleControllerHandlerAdapter(context, source);//适配器
		registerHandlerMappingIntrospector(context, source);//拦截器
		registerLocaleResolver(context, source);
		registerThemeResolver(context, source);
		registerViewNameTranslator(context, source);
		registerFlashMapManager(context, source);
	}

四、总结

        本篇并没有分析太多的源码,介绍了一种看源码的方式,希望能帮助大家

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringMvc源码分析--配置文件解析 的相关文章

随机推荐

  • GitBook快速入门

    1 安装 Node js Node 官网已经把 linux 下载版本更改为已编译好的版本了 xff0c 我们可以直接下载解压后使用 xff1a wget https nodejs org dist v10 15 3 node v10 15
  • 基于jsonp和cookie实现单点登录

    1 SSO需求 当前域名A xff1a www abc com 跨域域名B xff1a www def com 当在A域名下登录后点击链接跳转至域名B xff0c 希望实现域名B免登录 2 实现思路 2 1域名A开发一个接口C xff1a
  • 基于docker安装破解jira7.11.1

    1 拉取jira的docker镜像 docker pull cptactionhank atlassian jira software 7 11 1 2 启动jira容器 docker run name jira detach restar
  • Shell命令学习

    Shell命令 文章目录 Shell命令一 Shell是什么 xff1f 二 linux环境下的快捷键tab xff1a 输入命令或者路径等操作时自动补全上键 xff1a 快速选择上一次或多次执行的命令下键 xff1a 快速选择下一次或多次
  • 关于onNewIntent理解

    首先介绍一下Android的四种启动模式 standard 默认的 xff1a 所有的activity实例放在一个task xff08 任务栈 xff09 中 xff0c 遵循先进后出 xff0c 后进先出的规则 singleTop xff
  • ubuntu20.04系统安装谷歌浏览器

    1 百度搜索 谷歌浏览器官网 xff0c 然后在搜索界面点击如图所示图标进入谷歌浏览器下载界面 2 在谷歌浏览器下载界面 xff0c 点击 下载Chrome 3 在弹出的下载界面选择Ubuntu适用的64位下载包后点击 接受并安装 4 在下
  • 【Algorithm】单向链表模拟实现vector功能

    span class token function cmake minimum required span span class token punctuation span VERSION span class token number
  • ARCH INSTALL

    Arch Linux Install With UEFI Boot gdisk dev sdxy boot always uses less than 1G uses EF00 EFI System home uses 8302 mnt u
  • SQL Server 表注释&列注释

    添加表注释 表加注释 EXEC sys sp addextendedproperty 64 name 61 N 39 MS Description 39 64 value 61 N 39 注释内容 39 64 level0type 61 N
  • 在ubuntu14.04上安装或升级git

    git version git version 1 9 1 可以使用下面命令升级git xff08 如果不是root用户 xff0c 需在命令前加sudo xff09 xff1a add apt repository ppa git cor
  • C#串口数据处理--环形缓冲区-FIFO

    一 FIFO环形缓冲区初始化 static int MAX BUFFER LEN 61 1024 定义缓冲区大小 FIFO receiveBufferManager 61 new FIFO MAX BUFFER LEN 二 串口接收事件中添
  • IDEA 解决jar冲突问题

    在实际的 Maven 项目开发中 xff0c 由于项目引入的依赖过多 xff0c 遇到 jar 冲突算是一个很常见的问题了 如何使用 IntelliJ IDEA 解决 jar 包冲突的问题 xff01 简单粗暴 xff0c 直接上示例 xf
  • Ubuntu 18.04下安装Google Chrome

    Ubuntu 18 04下安装Google Chrome 进入Chrome官网下载地址 xff1a https www google cn intl zh CN chrome 点击 下载Chrome xff0c 进入下载页面 xff1a 如
  • css获取网页内所有标签的内容

    选择所有标签内的内容 包括script和style xff1a span class token punctuation span span class token punctuation span text 选择除script和style
  • Ubuntu 22.04 dektop 开启root并自动登录桌面

    1 设置root密码 span class token function sudo span span class token function passwd span root 2 解锁root span class token func
  • linux服务器之间的数据拷贝

    方法一 xff1a scp xff08 secure copy xff09 安全拷贝 xff08 1 xff09 scp定义 xff1a scp可以实现服务器与服务器之间的数据拷贝 xff08 from server1 to server2
  • Ubuntu桌面美化方法记录

    Ubuntu 20 04 1 LTS 桌面系统主题 xff0c 图标美化记录 Ubuntu使用的是Gnome Desktop xff0c 可以在 Gnome Look 寻找需要的主题 xff0c 图标 xff0c 插件等来丰富桌面系统 本文
  • spring mvc配置类简介及放静态资源释放

    配置文件ApplicationContext xml 基于spring的项目资源都是通过DispatcherServlet作为拦截器 xff0c DispatcherServlet是前置控制器 xff0c 配置在web xml文件中的 拦截
  • 【PVI-DSO】Leveraging Planar Regularities for Direct Sparse Visual-Inertial Odometry

    PVI DSO xff1a PVI DSO Leveraging Planar Regularities for Direct Sparse Visual Inertial Odometry 翻译 利用平面正则性进行直接稀疏视觉惯性里程计
  • SpringMvc源码分析--配置文件解析

    我们简单分析一下springmvc配置解析过程 xff0c 我个人认为理解这个过程对于后续学习是有帮助的 xff0c 毕竟配置文件是入口 一 认识springmvc xml配置文件 下面这个是springmvc中的配置 xff0c 与spr