您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

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

时间:2021-04-13 10:49:15  来源:掘金  作者:追逐仰望星空

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

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

 

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

1.ContextLoaderListener配置:

 <!-- Spring读取Spring的配置文件 -->
 <context-param>
 <!-- 名称 -->
 <param-name>contextConfigLocation</param-name>
 <!-- 文件的位置 -->
 <param-value>classpath:Application-context.xml</param-value>
 </context-param>
<context-param>
 <param-name>webAppRootKey</param-name>
 <param-value>meipian</param-value>
</context-param>
 <!-- Spring 的监听器配置 -->
 <listener>
 <!-- 在Spring-web包下 context -->
 <listener-class>org.springframework.web.context.ContextLoaderListener
 </listener-class>
 </listener>

2.DispatcherServlet的配置:

<servlet>
 <servlet-name>meipian</servlet-name>
 <!-- 配置SpringMVC核心控制器 -->
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 <init-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>classpath:springmvc.xml</param-value>
 </init-param>
 </servlet>
 <servlet-mapping>
 <servlet-name>meipian</servlet-name>
 <url-pattern>/*</url-pattern>
 </servlet-mapping>

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



Tags:Spring MVC   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
想要了解Spring MVC框架的原理,探究框架是如何设计的,不错的学习方式是阅读源码,然后自己手写一个框架。本文带领大家简化的手写一个Spring MVC框架。Spring框架对于Java后端程...【详细内容】
2021-09-22  Tags: Spring MVC  点击:(52)  评论:(0)  加入收藏
现在主流的Web MVC框架除了Struts这个主力 外,其次就是Spring MVC了,因此这也是作为一名程序员需要掌握的主流框架,框架选择多了,应对多变的需求和业务时,可实行的方案自然就多了...【详细内容】
2021-05-27  Tags: Spring MVC  点击:(195)  评论:(0)  加入收藏
在使用Spring MVC的时候,标准的配置是如下这样的: 注意注意:小编整理了一份Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC,有需要的朋友可以私信“spring”免费...【详细内容】
2021-04-13  Tags: Spring MVC  点击:(239)  评论:(0)  加入收藏
DispatcherServlet作为Spring MVC的核心控制器,初始化组件,处理客户端发送的请求,并返回 ModelAndView,进行视图渲染。主要是实现了父类 FrameworkServlet的抽象方法 doService()。...【详细内容】
2020-10-10  Tags: Spring MVC  点击:(71)  评论:(0)  加入收藏
前言Spring MVC是很多团队使用的Web框架。在基于Spring MVC的项目里,注解的使用几乎遍布在项目中的各个模块,有Java提供的注解,如:@Override、@Deprecated等;也有Spring提供的注...【详细内容】
2020-05-24  Tags: Spring MVC  点击:(49)  评论:(0)  加入收藏
通常,在Spring MVC中,我们编写一个控制器类来处理来自客户端的请求。然后,控制器调用业务类来处理与业务相关的任务,然后将客户端重定向到逻辑视图名称,该名称由Spring的调度程序...【详细内容】
2020-03-11  Tags: Spring MVC  点击:(47)  评论:(0)  加入收藏
在本例中,我们将使用Spring MVC框架构建一个入门级web应用程序。Spring MVC 是Spring框架最重要的的模块之一。它以强大的Spring IoC容器为基础,并充分利用容器的特性来简化...【详细内容】
2019-08-07  Tags: Spring MVC  点击:(222)  评论:(0)  加入收藏
▌简易百科推荐
近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了...【详细内容】
2021-12-23  Python阿杰    Tags:FastAPI   点击:(6)  评论:(0)  加入收藏
文章目录1、Quartz1.1 引入依赖<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version></dependency>...【详细内容】
2021-12-22  java老人头    Tags:框架   点击:(11)  评论:(0)  加入收藏
今天来梳理下 Spring 的整体脉络啦,为后面的文章做个铺垫~后面几篇文章应该会讲讲这些内容啦 Spring AOP 插件 (了好久都忘了 ) 分享下 4ye 在项目中利用 AOP + MybatisPlus 对...【详细内容】
2021-12-07  Java4ye    Tags:Spring   点击:(14)  评论:(0)  加入收藏
&emsp;前面通过入门案例介绍,我们发现在SpringSecurity中如果我们没有使用自定义的登录界面,那么SpringSecurity会给我们提供一个系统登录界面。但真实项目中我们一般都会使用...【详细内容】
2021-12-06  波哥带你学Java    Tags:SpringSecurity   点击:(18)  评论:(0)  加入收藏
React 简介 React 基本使用<div id="test"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js...【详细内容】
2021-11-30  清闲的帆船先生    Tags:框架   点击:(19)  评论:(0)  加入收藏
流水线(Pipeline)是把一个重复的过程分解为若干个子过程,使每个子过程与其他子过程并行进行的技术。本文主要介绍了诞生于云原生时代的流水线框架 Argo。 什么是流水线?在计算机...【详细内容】
2021-11-30  叼着猫的鱼    Tags:框架   点击:(21)  评论:(0)  加入收藏
TKinterThinter 是标准的python包,你可以在linx,macos,windows上使用它,你不需要安装它,因为它是python自带的扩展包。 它采用TCL的控制接口,你可以非常方便地写出图形界面,如...【详细内容】
2021-11-30    梦回故里归来  Tags:框架   点击:(26)  评论:(0)  加入收藏
前言项目中的配置文件会有密码的存在,例如数据库的密码、邮箱的密码、FTP的密码等。配置的密码以明文的方式暴露,并不是一种安全的方式,特别是大型项目的生产环境中,因为配置文...【详细内容】
2021-11-17  充满元气的java爱好者  博客园  Tags:SpringBoot   点击:(25)  评论:(0)  加入收藏
一、搭建环境1、创建数据库表和表结构create table account(id INT identity(1,1) primary key,name varchar(20),[money] DECIMAL2、创建maven的工程SSM,在pom.xml文件引入...【详细内容】
2021-11-11  AT小白在线中  搜狐号  Tags:开发框架   点击:(29)  评论:(0)  加入收藏
SpringBoot开发的物联网通信平台系统项目功能模块 功能 说明 MQTT 1.SSL支持 2.集群化部署时暂不支持retain&will类型消 UDP ...【详细内容】
2021-11-05  小程序建站    Tags:SpringBoot   点击:(55)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条