百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

还搞不清Spring 与 Spring MVC 容器之间的关系?

suiw9 2025-02-19 13:52 14 浏览 0 评论

在使用Spring MVC的时候,标准的配置是如下这样的:

注意注意:小编整理了一份Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC,有需要的朋友可以私信“spring”免费领取

1.ContextLoaderListener配置:

 
 
 
 contextConfigLocation
 
 classpath:application-context.xml
 

 webAppRootKey
 meipian

 
 
 
 org.springframework.web.context.ContextLoaderListener
 
 

2.DispatcherServlet的配置:


 meipian
 
 org.springframework.web.servlet.DispatcherServlet
 
 contextConfigLocation
 classpath:springmvc.xml
 
 
 
 meipian
 /*
 

ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。

Spring MVC的使用的容器是WebApplicationContext。那么他和ContextLoaderListener所初始化的ApplicationContext有什么关系呢?

可以从DispatcherServlet的初始化过程说起:DispatcherServlet拦截了所有的请求,所以访问任何一个接口都会初始化DispatcherServlet对象。

初始化DispatcherServlet只是做了一个很简单的事:

public DispatcherServlet() {
 super();
 setDispatchOptionsRequest(true);
 }

其父类FrameworkServlet初始化什么也没有:

public FrameworkServlet() {
 }

然后Tomcat会调用DispatcherServlet的init方法,在 Servlet 的生命期中,仅执行一次 init() 方法。它是在服务器装入 Servlet 时执行的。 可以配置服务器,以在启动服务器或客户机首次访问 Servlet 时装入 Servlet。 无论有多少客户机访问 Servlet,都不会重复执行 init() 。别问我为什么会调用init方法,这是servlet的规范。DispatcherServlet的init方法是在父类FrameworkServlet的父类HttpServlet中实现的:

@Override
 public final void init() throws ServletException {
 if (logger.isDebugEnabled()) {
 logger.debug("Initializing servlet '" + getServletName() + "'");
 }
 // Set bean properties from init parameters.
 try {
 PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
 BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
 ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
 bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
 initBeanWrapper(bw);
 bw.setPropertyValues(pvs, true);
 }
 catch (BeansException ex) {
 logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
 throw ex;
 }
 // Let subclasses do whatever initialization they like.
 initServletBean();
 if (logger.isDebugEnabled()) {
 logger.debug("Servlet '" + getServletName() + "' configured successfully");
 }
 }

会调用DispatcherServlet的initServletBean()方法就是初始化WebApplicationContext的方法。这个方法在其子类FrameServlet方法中实现:

@Override
 protected final void initServletBean() throws ServletException {
 getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
 if (this.logger.isInfoEnabled()) {
 this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
 }
 long startTime = System.currentTimeMillis();
 try {
 this.webApplicationContext = initWebApplicationContext(); //初始化WebApplicationContext对象
 initFrameworkServlet();
 }
 catch (ServletException ex) {
 this.logger.error("Context initialization failed", ex);
 throw ex;
 }
 catch (RuntimeException ex) {
 this.logger.error("Context initialization failed", ex);
 throw ex;
 }
 if (this.logger.isInfoEnabled()) {
 long elapsedTime = System.currentTimeMillis() - startTime;
 this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +
 elapsedTime + " ms");
 }
 }

initWebApplicationContext方法如下所示:

protected WebApplicationContext initWebApplicationContext() {
 WebApplicationContext rootContext =
 WebApplicationContextUtils.getWebApplicationContext(getServletContext());
 WebApplicationContext wac = null;
 if (this.webApplicationContext != null) {
 // A context instance was injected at construction time -> use it
 wac = this.webApplicationContext;
 if (wac instanceof ConfigurableWebApplicationContext) {
 ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
 if (!cwac.isActive()) {
 // The context has not yet been refreshed -> provide services such as
 // setting the parent context, setting the application context id, etc
 if (cwac.getParent() == null) {
 // The context instance was injected without an explicit parent -> set
 // the root application context (if any; may be null) as the parent
 cwac.setParent(rootContext);
 }
 configureAndRefreshWebApplicationContext(cwac);
 }
 }
 }
 if (wac == null) {
 // No context instance was injected at construction time -> see if one
 // has been registered in the servlet context. If one exists, it is assumed
 // that the parent context (if any) has already been set and that the
 // user has performed any initialization such as setting the context id
 wac = findWebApplicationContext();
 }
 if (wac == null) {
 // No context instance is defined for this servlet -> create a local one
 wac = createWebApplicationContext(rootContext);
 }
 if (!this.refreshEventReceived) {
 // Either the context is not a ConfigurableApplicationContext with refresh
 // support or the context injected at construction time had already been
 // refreshed -> trigger initial onRefresh manually here.
 onRefresh(wac);
 }
 if (this.publishContext) {
 // Publish the context as a servlet context attribute.
 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;
 }

会默认走到
createWebApplicationContext方法:

protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
 Class contextClass = getContextClass();
 if (this.logger.isDebugEnabled()) {
 this.logger.debug("Servlet with name '" + getServletName() +
 "' will try to create custom WebApplicationContext context of class '" +
 contextClass.getName() + "'" + ", using parent context [" + parent + "]");
 }
 if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
 throw new ApplicationContextException(
 "Fatal initialization error in servlet with name '" + getServletName() +
 "': custom WebApplicationContext class [" + contextClass.getName() +
 "] is not of type ConfigurableWebApplicationContext");
 }
 ConfigurableWebApplicationContext wac =
 (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
 wac.setEnvironment(getEnvironment());
 wac.setParent(parent);
 wac.setConfigLocation(getContextConfigLocation());
 configureAndRefreshWebApplicationContext(wac);
 return wac;
 }

在没有 contexloaderListener的情况下,parent是空的。

在有 contexloaderListener的情况下,发现parent不是空的。

而且在Spring MVC的配置中,如果你将Service的配置与mvc的配置写在一起,有没有contexloaderListener无所谓的。

原文链接:
https://juejin.im/post/58e5b7d3b123db15eb8143ae

相关推荐

俄罗斯的 HTTPS 也要被废了?(俄罗斯网站关闭)

发布该推文的ScottHelme是一名黑客,SecurityHeaders和ReportUri的创始人、Pluralsight作者、BBC常驻黑客。他表示,CAs现在似乎正在停止为俄罗斯域名颁发...

如何强制所有流量使用 HTTPS一网上用户

如何强制所有流量使用HTTPS一网上用户使用.htaccess强制流量到https的最常见方法可能是使用.htaccess重定向请求。.htaccess是一个简单的文本文件,简称为“.h...

https和http的区别(https和http有何区别)

“HTTPS和HTTP都是数据传输的应用层协议,区别在于HTTPS比HTTP安全”。区别在哪里,我们接着往下看:...

快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别

什么是协议?网络协议是计算机之间为了实现网络通信从而达成的一种“约定”或“规则”,正是因为这个“规则”的存在,不同厂商的生产设备、及不同操作系统组成的计算机之间,才可以实现通信。简单来说,计算机与网络...

简述HTTPS工作原理(简述https原理,以及与http的区别)

https是在http协议的基础上加了一层SSL(由网景公司开发),加密由ssl实现,它的目的是为用户提供对网站服务器的身份认证(需要CA),以至于保护交换数据的隐私和完整性,原理如图示。1、客户端发...

21、HTTPS 有几次握手和挥手?HTTPS 的原理什么是(高薪 常问)

HTTPS是3次握手和4次挥手,和HTTP是一样的。HTTPS的原理...

一次安全可靠的通信——HTTPS原理

为什么HTTPS协议就比HTTP安全呢?一次安全可靠的通信应该包含什么东西呢,这篇文章我会尝试讲清楚这些细节。Alice与Bob的通信...

为什么有的网站没有使用https(为什么有的网站点不开)

有的网站没有使用HTTPS的原因可能涉及多个方面,以下是.com、.top域名的一些见解:服务器性能限制:HTTPS使用公钥加密和私钥解密技术,这要求服务器具备足够的计算能力来处理加解密操作。如果服务...

HTTPS是什么?加密原理和证书。SSL/TLS握手过程

秘钥的产生过程非对称加密...

图解HTTPS「转」(图解http 完整版 彩色版 pdf)

我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。...

HTTP 和 HTTPS 有何不同?一文带你全面了解

随着互联网时代的高速发展,Web服务器和客户端之间的安全通信需求也越来越高。HTTP和HTTPS是两种广泛使用的Web通信协议。本文将介绍HTTP和HTTPS的区别,并探讨为什么HTTPS已成为We...

HTTP与HTTPS的区别,详细介绍(http与https有什么区别)

HTTP与HTTPS介绍超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的...

一文让你轻松掌握 HTTPS(https详解)

一文让你轻松掌握HTTPS原文作者:UC国际研发泽原写在最前:欢迎你来到“UC国际技术”公众号,我们将为大家提供与客户端、服务端、算法、测试、数据、前端等相关的高质量技术文章,不限于原创与翻译。...

如何在Spring Boot应用程序上启用HTTPS?

HTTPS是HTTP的安全版本,旨在提供传输层安全性(TLS)[安全套接字层(SSL)的后继产品],这是地址栏中的挂锁图标,用于在Web服务器和浏览器之间建立加密连接。HTTPS加密每个数据包以安全方...

一文彻底搞明白Http以及Https(http0)

早期以信息发布为主的Web1.0时代,HTTP已可以满足绝大部分需要。证书费用、服务器的计算资源都比较昂贵,作为HTTP安全扩展的HTTPS,通常只应用在登录、交易等少数环境中。但随着越来越多的重要...

取消回复欢迎 发表评论: