springMVC零配置之上下文配置

2023-05-16

记得刚参加工作的时候,搭建springMVC框架还是需要手动配置web.xml文件,现在已经被渐渐淘汰了,在项目中几乎看不到有这种配置了,取而代之的是springMVC的零配置,原理就是tomcat的SPI的技术。

通过spi机制,tomcat会扫描所有jar下的
/META-INF/services/javax.servlet.ServletContainerInitializer文件。
在这里插入图片描述

在这里插入图片描述

在SpringServletContainerInitializer中通过@HandlesTypes注解,将实现了所有WebApplicationInitializer接口的类作为参数传入onstartup方法中。
在这里插入图片描述
在这里插入图片描述

然后遍历所有实现了WebApplicationInitializer接口的类,调用他们的onstartup方法。

接下来定义一个WebApplicationInitializer接口的类:

代码片段一:

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    //父容器
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[]{SpringContainer.class};
    }

    //SpringMVC配置子容器
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{MvcContainer.class};
    }

    //获取DispatcherServlet的映射信息
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

代码片段二:

//不扫描有@Controller注解的类
@ComponentScan(value = "com.dongsq",excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})
})
public class SpringContainer {
}

代码片段三:

//扫描有@Controller注解的类
@ComponentScan(value = "com.dongsq",includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})
})
public class MvcContainer {
}

定义的类继承了AbstractAnnotationConfigDispatcherServletInitializer,而被继承类 又实现了WebApplicationInitializer接口。

所以由继承关系可知:会调用到AbstractDispatcherServletInitializer的onStartup方法。
在这里插入图片描述
看super.onStartup方法:
在这里插入图片描述
super.onStartup方法做了两件事:
一、创建spring上下文,createRootApplicationContext方法会调用复写的getRootConfigClasses方法,会将自定义的SpringConfainer类加入spring容器。
在这里插入图片描述
二、servlet容器注册监听。

AbstractDispatcherServletInitializer的onStartup方法中的super.onStartup方法调用完成,接下来会调用registerDispatcherServlet方法,创建mvc上下文,注册DispatcherServlet。

代码片段四:

protected void registerDispatcherServlet(ServletContext servletContext) {
	String servletName = getServletName();
	Assert.hasLength(servletName, "getServletName() must not return null or empty");

	//创建mvc的上下文,这里会调代码片段一中的getServletConfigClasses
	WebApplicationContext servletAppContext = createServletApplicationContext();
	Assert.notNull(servletAppContext, "createServletApplicationContext() must not return null");

	//创建DispatcherServlet对象,把springmvc上下文设置到DispatcherServlet中
	FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
	Assert.notNull(dispatcherServlet, "createDispatcherServlet(WebApplicationContext) must not return null");
	dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());

	//把DispatcherServlet放到servlet上下文中
	ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
	if (registration == null) {
		throw new IllegalStateException("Failed to register servlet with name '" + servletName + "'. " +
				"Check if there is another servlet registered under the same name.");
	}


	registration.setLoadOnStartup(1);
	//钩子方法 会调用代码片段一中的getServletMappings方法
	registration.addMapping(getServletMappings());
	registration.setAsyncSupported(isAsyncSupported());

	//定义拦截器
	Filter[] filters = getServletFilters();
	if (!ObjectUtils.isEmpty(filters)) {
		for (Filter filter : filters) {
			registerServletFilter(servletContext, filter);
		}
	}

	customizeRegistration(registration);
}

接下来在servlet容器启动时,会调到监听类中的contextInitialized方法。
在这里插入图片描述

看initWebApplicationContext方法:

代码片段五:

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
	.....

	try {
		.....
		if (this.context instanceof ConfigurableWebApplicationContext) {
			ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
			if (!cwac.isActive()) {
				if (cwac.getParent() == null) {
					ApplicationContext parent = loadParentContext(servletContext);
					cwac.setParent(parent);
				}
				//这里会调用refresh方法,启动spring上下文
				configureAndRefreshWebApplicationContext(cwac, servletContext);
			}
		}
	//将spring上下文设置到servlet容器中
	servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
		.....
	}
	....
}

接下来servlet容器在启动的时候,会调到DispatcherServlet中的init方法,最终会调到initWebApplicationContext方法。在这里插入图片描述
initWebApplicationContext方法代码:

protected WebApplicationContext initWebApplicationContext() {
	//从servlet下午文中获取spring的上下文对象
	WebApplicationContext rootContext =
			WebApplicationContextUtils.getWebApplicationContext(getServletContext());
	WebApplicationContext wac = null;

	if (this.webApplicationContext != null) {
		wac = this.webApplicationContext;
		if (wac instanceof ConfigurableWebApplicationContext) {
			ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
			if (!cwac.isActive()) {
				if (cwac.getParent() == null) {
					//设置spring上下文为springMVC的父上下文
					cwac.setParent(rootContext);
				}
				//在这启动springMVC上下文
				configureAndRefreshWebApplicationContext(cwac);
			}
		}
	}
	if (wac == null) {
		wac = findWebApplicationContext();
	}
	if (wac == null) {
		wac = createWebApplicationContext(rootContext);
	}

	if (!this.refreshEventReceived) {
		onRefresh(wac);
	}

	if (this.publishContext) {
		String attrName = getServletContextAttributeName();
		getServletContext().setAttribute(attrName, wac);
		if (this.logger.isDebugEnabled()) {
			this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
					"' as ServletContext attribute with name [" + attrName + "]");
		}
	}

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

springMVC零配置之上下文配置 的相关文章

随机推荐

  • dataturks解析

    34 34 34 根据大json写小json 34 34 34 with open 39 pay json 39 as f datas 61 f readlines for data in datas data 61 data strip
  • STM32串口之环形队列接收数据

    原文链接 xff1a STM32串口之环形队列接收数据 码代码的应该学数据结构都学过队列 环形队列是队列的一种特殊形式 xff0c 应用挺广泛的 因为有太多文章关于这方面的内容 xff0c 理论知识可以看别人的 xff0c 下面写得挺好的
  • Linux使用ssh远程登陆

    什么是SSH xff1f 简单说 xff0c SSH是一种网络协议 xff0c 用于计算机之间的加密登录 如果一个用户从本地计算机 xff0c 使用SSH协议登录另一台远程计算机 xff0c 我们就可以认为 xff0c 这种登录是安全的 x
  • 使用Vscode 编译 开发 调试 STM32单片机 VScode+openocd+STM32CubeMX+GDB

    Vscode 编译 开发 调试 STM32单片机 为什么记录这篇文章环境准备软件及工具下载软件安装 VScode功能搭建使用STM32CubeMX生成带有makefile的工程配置VScode工程 使用vscode 开发 xff0c 编译
  • 出错信息“module or group tools is not avaliable”

    出错信息 module or group tools is not avaliable 使用yum安装软件时 xff0c 有时会出现这个问题 xff0c 可能是需要安装的软件来自第三方 解决办法 yum install epel relea
  • ubuntu 自动登录/图形界面启动流程

    ubuntu 自动登录 图形界面启动流程 启动流程配置greeter和desktop自动登录配置自动登录后进入的desktop总结 这两天在Jetson nano 上想做一个跳过用户界面直接自动登录到桌面的功能 本来很简单的在System
  • Ubuntu update-alternatives 安装/管理多版本 Python3及PIP3

    Ubuntu update alternatives 安装 管理多版本 Python3及PIP3 前言安装python安装对应版本pipupdate alternatives 切换python3 环境 前言 在ubuntu系统上 xff0c
  • 实用的Visual Studio Code插件

    1 vscode color highlight 颜色代码高亮插件 xff08 sublime text也有 xff09 2 vscode Open in Browser 右键在浏览器打开 xff08 sublime text也有 xff0
  • LWIP 双IP实现

    LwIP是Light Weight 轻型 IP协议 xff0c 有无操作系统的支持都可以运行 LwIP实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用 xff0c 它只需十几KB的RAM和40K左右的ROM就可以运行 xff
  • Seata解析-seata部署启动初体验

    本文基于seata 1 3 0版本 seata是由阿里巴巴开源的分布式事务框架 xff0c 用于在分布式环境中保持事务一致性 它提供了四种事务模式 xff1a AT TCC SAGA 和 XA 事务模式 xff0c 默认是AT模式 Seat
  • 功能案例----java实现语音播报功能

    功能案例 java实现语音播报功能 根据自己最近的写的项目 xff0c 总结整理了关于java语音播报功能的方法 xff0c 可分为两种形式 一种是通过自己写出一个语音播报方法的工具类 xff0c 然后从前端获取文本数据 xff0c 最后跳
  • spring mvc拦截器 需求:在controller层的方法上,使用自定义注解的方式 不拦截指定请求

    原来是在controller类上实现此需求 缺点 xff1a 只能是整个controller类下的方法全部放开拦截 xff0c 不能放开其中某个方法 xff0c 颗粒度太高 现实现在方法上增加注解 xff0c 更加细颗粒度 1 首先是自定义
  • 生产者消费者代码实现(JAVA)

    代码 import lombok extern slf4j Slf4j import java util LinkedList final class Message 单条消息 private int id private String m
  • 手误删除服务器tomcat下的bin目录,./start.sh无效

    关于LINUX权限 bash startup sh Permission denied 在执行 startup sh 或者 shutdown sh的时候 xff0c 爆出了Permission denied xff0c 其实很简单 xff0
  • C++ 进程间通信

    一 xff0c C 43 43 常用进程间通信 管道 Pipe xff1a 管道可用于具有亲缘关系进程间的通信 xff0c 允许一个进程和另一个与它有共同祖先的进程之间进行通信 命名管道 named pipe xff1a 命名管道克服了管道
  • 【Android7.1.2源码解析系列】Android ADB概览 ---system/core/adb/OVERVIEW.txt

    ADB实施笔记 I 总体概览 xff1a 安卓调试桥 ADB 被用来 xff1a 保持一条指向于所有安卓设备以及连接向或者运行于所给的开发主机的仿真机 实现多个适用于客户端 命令行用户或者像DDMS那样的帮助程序 的控制命令 比如说 34
  • 内存泄漏 定位方法

    目录 内存概念 物理内存 虚拟内存 内存泄漏 定位方法和手段 1 MemInFo MemTotal MemFree MemAvailable Cached 2 vmalloc info 3 Kmemleak 算法原理 使用方法 参考文献与链
  • 关于环形缓冲区的用法和理解

    通信中 xff0c 经常会遇到数据交互的问题 为了保证数据的高效处理和解析 xff0c 通常会有 缓冲区的说法 接下来谈谈常用的环形缓冲区的特点和使用方法 xff1a 说到环形缓冲区 xff0c 相信大家都不会陌生 xff0c 这里就不贴图
  • 电脑安装系统时提示“找不到硬盘”如何解决

    电脑安装系统的方法有很多众 xff0c 比较常见的是用PE来安装的 xff0c 当然也可以用U盘安装 安装过程中无法识别到硬盘那是很正常的事 xff0c 相信大部分用户都遇到过 xff0c 该如何解决 xff1f 不要担心 xff0c 本教
  • springMVC零配置之上下文配置

    记得刚参加工作的时候 xff0c 搭建springMVC框架还是需要手动配置web xml文件 xff0c 现在已经被渐渐淘汰了 xff0c 在项目中几乎看不到有这种配置了 xff0c 取而代之的是springMVC的零配置 xff0c 原