-
spring讲解一:为什么tomcat可以运行SpringMvc...对比使用纯java代码 和 纯xml配置,如何启动SpringMvc项目。
2020-03-12 17:13:51tomcat和java代码是两个独立的个体,他们如何最后达到tomcat可以运行java代码的呢? 为什么tomcat运行的是Springmvc项目的代码?为什么现在的项目都离不开Springmvc?为什么不直接运行一个随意的main方法?为什么web...为什么tomcat会调用java代码?tomcat和java代码是两个独立的个体,他们如何最后达到tomcat可以运行java代码的呢? 为什么tomcat运行的是Springmvc项目的代码?为什么现在的项目都离不开Springmvc?为什么不直接运行一个随意的main方法?为什么web应用框架有Springmvc和Struts2 ? Springmvc和Struts2有什么共同点? 不知道答案的其实可以先猜一下试试。
答案:Servlet的规范,也可以说成是Servlet协议。
以前web项目都是必须用xml做配置,达到项目运行的效果,为什么现在可以不使用xml了?
答案:Servlet3.0的规范,2.5或者是以前的版本是不可以的,2.5版本以前,规定项目必须使用web.xml配置方式来运行代码。
为什么tomcat运行的是Springmvc项目的代码?没有随便运行一个main方法的代码?
答案:因为Springmvc框架遵守了Servlet规范,其中一条规范规定,在代码的根目录中(以spring框架为例,springmvc提供的jar包spring-web),必须有一个叫META-INF/services的目录且里面有一个全类路径名的文件(文件内容很简单:就是一个自定义的启动的类的全类名),而这个类中呢,必须有一个方法,名字叫:onStartup
到了这个时候,其实就明白了,原来tomcat启动,是直接去代码根目录找一个文件,然后根据文件里的内容,找到一个类,再运行这个类的一个叫onStartup方法,然后代码就开始一层一层的开始往下运行了。
其实不要springmvc也是可以的,不过就需要自己重新实现servlet的具体功能,对于开发来说,太麻烦,而且功能不一定能实现的这么全,这么好。
大家应该还记得,最开始学习java的时候,那时候的web项目可以说是非常的复杂,但是能够让你知道具体实现原理,现在框架封装太厚,如果想要了解,就算费尽九牛二虎之力,都不一定能清楚原理。特别是现在的springboot框架,用起来更加简单,但是很多原理几乎都隐藏了起来,但是万恶的面试官就喜欢问一些,对开发不太起作用的问题。
言归正传,以前的项目springmvc+spring+hibernate/mybaits项目,WEB-INF目录下有个web.xml文件
在spring3框架之前用的是Servlet3.0之前的规范,onStartup方法必须读取web.xml中的配置,进行初始化,spring3以后,就开始使用Servlet3.0规范,允许使用JavaConfig的方式(纯代码的方式),以前写在web.xml中内容,现在直接在onStartup方法中new,进行初始化,以前的名叫springmvc.xml、applicationContext-redis.xml类似这种名称的配置,现在直接用注解标记一个自定义的类,写好初始化的代码,就可以代替以前的配置文件了。
如果还记得web.xml的话,应该见过下面一段配置
<servlet> <servlet-name>springmvc_mybatis_annotation</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc/springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
里面有段配置:classpath:springmvc/springmvc.xml,就是说,运行onStartup方法后,遇到了new的DispatcherServlet后,就开始去找springmvc.xml这个文件,又再去初始化spring的其他集成配置。
现在springboot都不需要了,他把日常开发中,需要的配置,都帮你在springboot框架的java代码中写好了,程序员基本不用改了。
但是如果你想要改,不好意思,你又要去看springboot提供的官方文档(文档里有教你怎么集成redis、mysql等很多常用的组件),或者百度。
所以,如果你不想单纯的做一个码农,这个东西,你就必须要去了解。
为什么web应用框架有Springmvc和Struts2 ? 他们有什么共同点 ?
答案:因为他们两个web应用层框架都遵守了Servlet规范,他们都有相同的META-INF/services目录,都有自己实现的onStartup方法。他们都是封装了javax提供的servlet-api。也就是他们的底层都是servlet实现的。
其他解释:Servlet3.0的规范,是基于SPI的机制来实现的,
SPI ,全称为 Service Provider Interface,是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。这一机制为很多框架扩展提供了可能,比如在Dubbo、JDBC中都使用到了SPI机制。
说简单点,就是我规定你,下午3点在停车场的3号车位来接我,我下午3点会过来乘车。就两边都说好了,然后我们就可以进行交互了。
我们都知道,运行web项目,不光光是tomcat可以运行,还有weblogic、jetty、jboos等web容器(可以叫做web服务器)),因为tomcat免费,且性能还不错,所以被广泛运用。那为什么这些web服务器,就可以是web服务器了呢?那我随便写段代码为什么就成不了web服务器?
这里也就牵扯到Servlet其中的规范,也就是说,你要开发web服务器你要听我的,你要写web项目也必须听我的:
1. 你如果是运行java代码的web服务器(例:tomcat)运行之后,必须去代码的根目录下找META-INF/services文件夹并找到文件中的代码,运行代码中的onStartup方法。
2. “你”(例:springmvc框架)的代码想被呗运行,就必须有一个META-INF/services文件夹,和自己实现的onStartup的方法。
-
Tomcat是如何启动Spring,SpringMVC,Mybatis整合的web项目的?
2020-01-27 11:58:101. 当我们启动一个web项目时, 会先去启动tomcat, 也就是Bootstrap的mian()方法, tomcat开始由server组件开始一层一层向下初始化以及启动; 2. 当启动Host容器之后, 会触发HostConfig的监听操作, 开始部署/webapps...1. 当我们启动一个web项目时, 会先去启动tomcat, 也就是Bootstrap的mian()方法, tomcat开始由server组件开始一层一层向下初始化以及启动;
2. 当启动Host容器之后, 会触发HostConfig的监听操作, 开始部署/webapps目录下的web项目, 然后会通过反射创建Context实例对象, 并将当前部署的web项目绑定到该Context容器实例上;
3. 同时会将该Context实例添加到Host实例的子对象中, 在添加过程中会触发Context的初始化以及启动, 在启动过程中会触发"加载时启动"的Servlet, 也就是SpringMVC中的DispatcherServlet, 将会执行该Servlet的init()方法;
4. 在init()方法中将会触发Spring中IOC容器的初始化, 对项目中的bean实例进行注册以及管理, 在IOC容器初始化完成之后, 将会发送结束事件;
5. 此时事件会被SpringMVC监听到, 然后会从IOC容器中获取已经注册的SpringMVC相关的bean实例, 开始SpringMVC的初始化过程, 也就是将SpringMVC的各个组件注册到SpringMVC的上下文中; (IOC容器中注册的我们自定义的Bean用来处理业务逻辑的在后面项目处理请求时会使用) 当SpringMVC初始化完成, 该web项目也就启动完成了;
6. 在tomcat启动时会启动相关线程组去监听相关端口, 获取到请求后, 交由DispatcherServlet处理, 在DispatcherServlet中将根据请求信息获取到指定的处理方法, 然后通过反射执行该方法, 处理请求信息
7. 在处理方法执行时会调用数据库进行数据的持久化操作, 也就是会利用mybatis框架进行操作, 而mybatis框架的初始化相关操作在Spring初始化时触发
-
springmvc从入门到源码分析专题2_tomcat服务启动过程中如何加载ContextLoaderListener的
2020-12-24 14:32:36springmvc从入门到源码分析专题2_tomcat服务启动过程中如何加载ContextLoaderListener的 前言 在上一篇文章中我们做了相关前期准备,并且搭建好了我们的项目环境,成功运行了我们第一个springmvc项目helloword,但是...springmvc从入门到源码分析专题2_tomcat服务启动过程中如何加载ContextLoaderListener的
前言
在上一篇文章中我们做了相关前期准备,并且搭建好了我们的项目环境,成功运行了我们第一个springmvc项目helloword,但是我们并没有对我们的配置文件中的配置进行详解和分析,本篇文章及后面的文章我们将分析讲解这些配置的作用,并深入到源码讲解这些配置是如何实现的
ServletContext的作用
-
这里首先来说一下
ServletContext
的作用,因为它对后面我们分析org.springframework.web.context.ContextLoaderListener
很重要. -
ServletContext,是一个全局的储存信息的空间,服务器开始,其就存在,服务器关闭,其才释放。request,一个用户可有多个;session,一个用户一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息。
-
启动web容器后,web容器会读取web.xml中的配置信息,对ServletContext进行信息补充。(注:配置加载顺序为:context-param -> listener -> filter -> servlet)
ServletContextListener 的作用
ServletContextListener 是 ServletContext 的监听者,用于接收有关ServletContext生命周期更改的通知事件的接口。监听 ServletContext 发生变化,如服务器启动时 ServletContext 被创建,服务器关闭时 ServletContext 要被销毁。
ContextLoaderListener 的源码解析
- 首先我们来看一下web.xml中是如何配置
org.springframework.web.context.ContextLoaderListener
<!-- 使用ContextLoaderListener配置时,需要告诉它Spring配置文件的位置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!-- 配置上下文载入器,上下文载入器载入除DispatherServlet载入的配置文件之外的其他上下文配置文件 最常用的上下文载入器是一个Servlet监听器,器名称为ContextLoaderListener --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
- ContextLoaderListener 的源码
public class ContextLoaderListener extends ContextLoader implements ServletContextListener { private ContextLoader contextLoader; ... /** * Initialize the root web application context. */ public void contextInitialized(ServletContextEvent event) { this.contextLoader = createContextLoader(); if (this.contextLoader == null) { this.contextLoader = this; } this.contextLoader.initWebApplicationContext(event.getServletContext()); } protected ContextLoader createContextLoader() { return null; } ... }
-
从
ContextLoaderListener
的源码中我们看到它实现了ServletContextListener
接口,那么在容器启动的过程必然会调用ContextLoaderListener#contextInitialized(...)
方法,容器关闭时调用ContextLoaderListener#contextDestroyed(...)
方法 -
那么
ContextLoaderListener#contextInitialized(...)
方法的作用主要是做什么呢?它的作用主要是初始化WebApplicationContext
,从该方法中调用initWebApplicationContext(...)
方法的注释就可以看出,那就究竟是如何做的呢,我们继续往下看 -
ContextLoader#initWebApplicationContext(...)
的代码片段
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { throw new IllegalStateException( "Cannot initialize context because there is already a root application context present - " + "check whether you have multiple ContextLoader* definitions in your web.xml!"); } ... try { // Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown. if (this.context == null) { this.context = createWebApplicationContext(servletContext); } ... // 配置并刷新WebApplicationContext ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; configureAndRefreshWebApplicationContext(cwac, servletContext); ... servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); ... return this.context; }catch (RuntimeException ex) { ... }
ContextLoader#createWebApplicationContext(...)
的代码片段
protected WebApplicationContext createWebApplicationContext(ServletContext sc) { //获取 org.springframework.web.context.support.XmlWebApplicationContext 的class Class<?> contextClass = determineContextClass(sc); ... //通过反射创建WebApplicationContext对象 return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); }
-
在
ContextLoader#initWebApplicationContext(...)
中,首先判断在servletContext中是否存在WebApplicationContext
,如果存在则就抛出异常,然后判断上下问对象是否为空,程序第一次执行时,该对象就是空的,然后调用ContextLoader#createWebApplicationContext(...)
创建WebApplicationContext
对象,然后调用ContextLoader#configureAndRefreshWebApplicationContext(...)
方法配置并刷新WebApplicationContext上下文 -
ContextLoader#configureAndRefreshWebApplicationContext(...)
方法的代码片段
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) { ... //将ServletContext对象保存到上下文中 wac.setServletContext(sc); //获取web.xml中配置的contextConfigLocation的值 String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM); if (configLocationParam != null) { wac.setConfigLocation(configLocationParam); } .... // 刷新WebApplicationContext上下文 wac.refresh(); }
- 接下来就是将
WebApplicationContext
对象设置到servletContext
中,方便后面使用,这就是org.springframework.web.context.ContextLoaderListener
的作用
总结
通过上面分析我们不难看出
org.springframework.web.context.ContextLoaderListener
的作用就是为了加载我们在web.xml中通过contextConfigLocation
指定的spring bean配置文件,创建根WebApplicationContext上下文,好了,本篇文章就到这里了,下一篇我们将分析容器启动过程中org.springframework.web.servlet.DispatcherServlet
是如何被执行的 -
-
springmvc+mybatis 如何让tomcat启动时就加载所有的controller?
2016-12-17 08:23:51springmvc+mybatis 如何让tomcat启动时就加载所有的controller? -
springmvc从入门到源码分析专题3_tomcat服务启动过程中DispatcherServlet初始化过程
2020-12-28 17:17:45在上一篇 springmvc从入门到源码分析专题2_tomcat服务启动过程中如何加载ContextLoaderListener的 文章中我们分析了 ContextLoaderListener 是如何初始化的,讲解了springmvc是如何创建根ApplicationContext的过程,本...springmvc从入门到源码分析专题3_tomcat服务启动过程中DispatcherServlet初始化过程
在上一篇 springmvc从入门到源码分析专题2_tomcat服务启动过程中如何加载ContextLoaderListener的 文章中我们分析了 ContextLoaderListener 是如何初始化的,讲解了springmvc是如何创建根ApplicationContext的过程,本篇文章我们来分析DispatcherServlet初始化过程
web.xml的配置
<!-- SpringMVC的前端控制器,当DispatcherServlet载入后,它将从一个XML文件中 载入Spring的应用上下文,该XML文件的名字取决于这里DispathcerServlet将试图从一个 叫做Springmvc-servlet.xml的文件中载入应用上下文 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-servlet.xml</param-value> </init-param> </servlet>
DispatcherServlet的继承关系
首先我们先看下DispatcherServlet的继承关系,然后我们再来逐步分析。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
重要接口Servlet详解
/** * 该接口定义了初始化Servlet,处理请求以及从服务器中删除Servlet的方法。这些称为生命周期方法,按以下顺序调用: * 1.构建servlet,然后使用init方法初始化。 * 2.处理客户对服务方法的任何调用。 * 3.停止使用Servlet,然后使用destroy方法将其销毁,然后对垃圾进行收集并最终确定。 * * 除了生命周期方法外,此接口还提供了Servlet可用于获取任何启动信息的getServletConfig方法,以及允许Servlet返回有关自身的基本信息(如作者,版本和版本)的getServletInfo方法。版权。 */ public interface Servlet { /** * 在servlet的配置当中,<load-on-startup>1</load-on-startup>的含义是: * <p> 当值为0或者大于0时,表示容器在应用启动时就加载这个servlet; * <p> 当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。 * <p> 正数的值越小,启动该servlet的优先级越高。 * * <p> 如果我们在web.xml中设置了多个servlet的时候,可以使用load-on-startup来指定servlet的加载顺序,服务器会根据load-on-startup的大小依次对servlet进行初始化。不过即使我们将load-on-startup设置重复也不会出现异常,服务器会自己决定初始化顺序 * * <p> 配置load-on-startup后,servlet在startup后立即加载,但只是调用servlet的init()方法,用以初始化该servlet相关的资源。初始化成功后,该servlet可响应web请求;如未配置load-on-startup,容器一般在第一次响应web请求时,会先检测该servlet是否初始化,如未初始化,则调用servlet的init()先初始化,初始化成功后,再响应请求。 * *<p> 同时调用servlet的init()方法,它有一个参数ServletConfig,是容器传进来的,表示的是这个Servlet的一些配置,比如DispatcherServlet配置的<init-param> */ public void init(ServletConfig config) throws ServletException; /** * 获取Servlet的配置 */ public ServletConfig getServletConfig(); /** * 最重要的一个方法,是具体处理请求的地方 */ public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; /** * 获取Servlet的一些信息,比如作者、版本、版权等,需要子类实现 */ public String getServletInfo(); /** * 用于Servlet销毁(主要指关闭容器)时释放一些资源,只会调用一次 */ public void destroy(); }
重要接口ServletConfig详解
/** * servlet容器使用的servlet配置对象,用于在初始化期间将信息传递给servlet。 */ public interface ServletConfig { /** * 返回Servlet的名字,就是<servlet-name>中配置的名字 */ public String getServletName(); /** * 返回应用本身的一些配置 */ public ServletContext getServletContext(); /** * 返回<init-param>配置的参数 */ public String getInitParameter(String name); /** * 返回<init-param>配置的参数的名字 */ public Enumeration<String> getInitParameterNames(); }
Servlet接口的抽象实现类 GenericServlet 详解
/** * * GenericServlet实现Servlet和ServletConfig接口。 可以直接由servlet扩展GenericServlet,尽管扩展特定于协议的子类(例如HttpServlet)更为常见。 * * <p> GenericServlet使编写servlet更容易。 它提供了生命周期方法init和destroy以及ServletConfig接口中的方法的简单版本。 GenericServlet还实现了在ServletContext接口中声明的log方法。 * 要编写通用servlet,您只需要重写抽象服务方法即可。 */ public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable { private transient ServletConfig config; /** * <p> 获取初始化参数,返回一个字符串,其中包含命名的初始化参数的值;如果该参数不存在,则返回null。 * <p> 提供此方法是为了方便。 它从Servlet的ServletConfig对象获取命名参数的值。 */ public String getInitParameter(String name) {...} /** * 返回此Servlet的ServletConfig对象。 */ public ServletConfig getServletConfig() {...} /** * 返回对该ServletContext的引用,它从Servlet的ServletConfig对象获取上下文。 */ public ServletContext getServletContext() {...} /** * 可以重写的一种便捷方法,因此无需调用super.init(config)。 * * <p> 不必重写init(ServletConfig),只需重写此方法,它将由GenericServlet.init(ServletConfig config)调用。 仍然可以通过getServletConfig检索ServletConfig对象。 */ public void init() throws ServletException {...} /** * 由Servlet容器调用,以允许Servlet响应请求。 * 将此方法声明为抽象方法,因此子类(例如HttpServlet)必须覆盖它。 */ public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; }
DispatcherServlet的初始化流程
- 从上图中我们可以看到
DispatcherServlet
间接地继承于Servlet
, 而springmvc的HttpServletBean
复写了Servlet#init()
方法,这个init()
就是DispatcherServlet的初始化流程的入口,我们来看看HttpServletBean#init()
方法
public final void init() throws ServletException { ... try { //从ServletConfig中获取初始配置,比如contextConfigLocation 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())); // 模板方法,做一些初始化的工作,bw代表DispatcherServlet,但是没有子类重写 initBeanWrapper(bw); // 把初始配置设置给DispatcherServlet,比如contextConfigLocation bw.setPropertyValues(pvs, true); } catch (BeansException ex) { logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); throw ex; } // 模板方法,子类重写,做进一步初始化的工作 initServletBean(); ... }
FrameworkServlet#initServletBean()
方法
/** * 设置任何bean属性后调用的HttpServletBean的重写方法。 创建此Servlet的WebApplicationContext。 */ @Override protected final void initServletBean() throws ServletException { ... //初始化并发布此Servlet的WebApplicationContext。 this.webApplicationContext = initWebApplicationContext(); //设置任何bean属性并加载WebApplicationContext后,将调用此方法。 默认实现为空; 子类可以重写此方法以执行其所需的任何初始化。 initFrameworkServlet(); ... }
FrameworkServlet#initWebApplicationContext()
/** * 初始化并发布此Servlet的WebApplicationContext。 * <p> 代表createWebApplicationContext实际创建上下文 */ protected WebApplicationContext initWebApplicationContext() { //从ServletContext中获取父WebApplicationContext,在上一篇文章中我们在web.xml中配置了ContextLoaderListener,那么它加载的就是父WebApplicationContext WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null; // 如果通过构造方法传入了webApplicationContext,就使用它 if (this.webApplicationContext != null) { wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { if (cwac.getParent() == null) { cwac.setParent(rootContext); } configureAndRefreshWebApplicationContext(cwac); } } } if (wac == null) { // 从ServletContext中获取webApplicationContext,一般情况下是没有的 wac = findWebApplicationContext(); } if (wac == null) { // 自己创建一个webApplicationContext wac = createWebApplicationContext(rootContext); } if (!this.refreshEventReceived) { // 当ContextRefreshedEvent事件没有触发时调用此方法,模板方法,子类实现,是DispatcherServlet中重要的方法 onRefresh(wac); } if (this.publishContext) { // 把webApplicationContext保存到ServletContext中 String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); } return wac; }
正常情况下都是自己创建一个webApplicationContext,我们看下创建的过程
``` protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) { // 获取创建类型 Class<?> contextClass = getContextClass(); // 具体创建 ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); wac.setEnvironment(getEnvironment()); wac.setParent(parent); // 将设置的contextConfigLocation参数传给wac,默认传入WEB-INFO/[ServletName]-Servlet.xml wac.setConfigLocation(getContextConfigLocation()); // 配置和刷新wac configureAndRefreshWebApplicationContext(wac); return wac; } protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) { if (ObjectUtils.identityToString(wac).equals(wac.getId())) { if (this.contextId != null) { wac.setId(this.contextId); } else { wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName()); } } wac.setServletContext(getServletContext()); wac.setServletConfig(getServletConfig()); wac.setNamespace(getNamespace()); //添加ContextRefreshListener监听器, wac.addApplicationListener(new SourceFilteringListener(wac, new FrameworkServlet.ContextRefreshListener())); ConfigurableEnvironment env = wac.getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig()); } postProcessWebApplicationContext(wac); applyInitializers(wac); // 根据contextConfigLocation的值刷新webApplicationContext wac.refresh(); } /** * ContextRefreshListener接收的ContextRefreshedEvent完成刷新事件,委托给FrameworkServlet实例上的onApplicationEvent。 */ private class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> { public void onApplicationEvent(ContextRefreshedEvent event) { FrameworkServlet.this.onApplicationEvent(event); } } /** * 默认实现调用onRefresh,触发此Servlet的上下文相关状态的刷新。 */ public void onApplicationEvent(ContextRefreshedEvent event) { this.refreshEventReceived = true; onRefresh(event.getApplicationContext()); } ```
-
我们来看卡
DispatcherServlet#onRefresh()
方法都干了些什么事情/** * 此实现调用initStrategies。 */ @Override protected void onRefresh(ApplicationContext context) { initStrategies(context); } /** * 初始化springmvc执行过程中各种解析器 */ protected void initStrategies(ApplicationContext context) { //初始化文件上传解析器 initMultipartResolver(context); //初始化国际化资源解析器 initLocaleResolver(context); //初始化主题管理配置 initThemeResolver(context); //初始化HandlerMapping initHandlerMappings(context); //初始化HandlerAdapter initHandlerAdapters(context); //初始化HandlerException,可以扩展用于统一异常处理 initHandlerExceptionResolvers(context); //初始化处理请求名称作为视图名称返回 initRequestToViewNameTranslator(context); //初始化视图解析器 initViewResolvers(context); //初始化FlashMapManager,重定向时一般都是不传数据的,如果一定要传数据,只能在URL中拼接字符串来传递,但是通过拼接字符串有缺点,比如长度问题,安全问题,通过FlashManager异常发送 initFlashMapManager(context); }
最后
到这里,关于DispatcherServlet初始化过程就分析完成了,我们可以看到,本篇文章很多细节知识点都没有展开来讲,是因为这些知识点如果深入讲解得用一篇博文甚至几篇博文才能讲解清楚,随着专题的深入,我都会一一讲解,下一篇我们将会讲解从浏览器发起一个请求后springmvc是如何处理这个请求的
- 从上图中我们可以看到
-
java servlet spring_Tomcat是如何加载Spring和SpringMVC及Servlet相关知识
2021-03-08 22:34:58概述大家是否清楚,Tomcat是如何加载Spring和SpringMVC,今天我们就弄清下这个过程(记录最关键的东西)其中会涉及到大大小小的知识,包括加载时候的设计模式,Servlet知识等,看了你肯定有所收获~Tomcattomcat是一种... -
idea tomcat springmvc 无法注入bean_Spring如何与Tomcat框架进行集成
2020-11-25 18:27:56一、前言本节我们讲究如何利用Tomcat的ContextLoaderListener扩展接口来把Spring框架与Tomcat进行连接起来。二、ContextLoaderListener扩展接口ContextLoaderListener一般用来启动一个Spring容器或者框架的根容器,... -
springMVC中启动tomcat后,不显示页面
2019-04-27 15:02:46springMVC中启动tomcat后,不显示页面 第一种:不显示小猫 当你用eclipse启动tomcat之后,作如下操作。 【问题】在浏览器中输入http://localhost:8080,不显示如下界面。 【解决方法】 将tomcat作如下设置,如果你... -
学习一下SpringMVC是如何和tomcat集合的
2020-10-12 18:05:27这里,我们不得不需要一些前置知识,即TOMCAT的执行流程,同时还应该学习一下SpringMVC是如何和tomcat集合的。当然,socket和mvc没多大关系 https://blog.csdn.net/m0_51268684/article/details/109033163 大体上... -
Spring如何整合SpringMVC
2020-06-11 20:22:23因为在tomcat启动的时候,web.xml中的前端控制器只加载了springmvc.xml的配置文件,没有加载spring的配置文件,因此controller类中的spring的注解就不起作用了。 3、如何加载spring配置文件? 4、到这里也就是说现在... -
springmvc 加载 慢_求如何解决。springmvc 启动时会在控制台输出注入每个类的信息。导致 tomcat 启动太慢。...
2020-12-19 10:47:22\apache-tomcat-7.0.67\webapps\docs 三月 14, 2016 2:16:43 下午 org.apache.catalina.startup.HostConfig deployDirectory INFO: Deployment of web application directory D:\apache-tomcat-7.0.67\webapps\docs ... -
Tomcat 9 源码解析 -- 与SpringMvc如何结合在一起
2020-05-15 00:06:37Tomcat启动项目的方式下,如何加载SpringMvc 中的 DispatcherServlet SpringBootServletInitializer类 public abstract class SpringBootServletInitializer implements WebApplicationInitializer { ... -
使用idea创建springMVC项目时如何配置tomcat
2020-05-10 21:21:08接下来把项目加进去,注意这里下面的Application context可以只保留一个 / ,它默认是会给你添加一长串的东西的 ,这里影响的是tomcat服务的启动地址 比如如果是只保留/的话地址就是http://localhost:8080/,但是... -
SpringBoot之如何自动启动tomcat
2020-06-03 08:54:03首先我们要先理解Springboot和Spring mvc的区别 SpringMVC项目构建一定包含三要素 ...这个后面文章会提及,今天主要只说以下如何启动的tomcat 我们来直接看源码 1 证明是Spring项目 然后执行run方... -
通过tomcat容器启动spring容器的启动过程
2019-01-11 16:40:50通过对spring源码的解读,跟踪spring容器的启动过程,掌握SpringMVC是如何工作的;掌握Spring源码的设计和增强阅读源码的技巧。为可持续性的使用spring框架高效集成开发,解决系统一些疑难杂症提供强有力的支撑。 ... -
springMVC在tomcat中的初始化
2019-03-06 15:34:03在spring Web中,需要初始化IOC容器,用于存放...当tomcat启动的时候是如何初始化IOC容器的,我们先看一下在web.xml中经常看到的配置: <context-param> <param-name>contextConfig... -
SpringBoot 源码解析 (七)----- Spring Boot的核心能力 - SpringBoot如何实现SpringMvc的?
2019-11-23 12:50:08上一篇我们讲了SpringBoot中Tomcat的启动过程,本篇我们接着讲在SpringBoot中如何向Tomcat中添加Servlet、Filter、Listener 自定义Servlet、Filter、Listener叮当小说网 https://wap.guxs.net/ Spring容器中声明... -
#设置首页 #SpringMVC:view-controller、view-name #Tomcat:welcome-file-list、welcome-file @FDDLC
2020-12-11 15:29:40我们知道,Tomcat启动后,项目根目录下的index.html或index.jsp 主题:JavaWeb项目如何设置首页? 今天介绍两种设置首页的方式:配置Tomcat;配置SpringMVC 一、配置Tomcat ... -
Tomcat WEB 的启动过程
2021-02-04 14:51:38那么问题是tomcat 启动过程中是如何使得该项目生效的呢。大致分为两个步骤。 步骤一、解析server.xml 启动Tomcat,会去读取web.xml配置文件里的配置,当这一步骤没有出错并且完成之后,项目才能正常的被启动起来... -
【SpringBoot源码解析】第四章:SpringBoot是如何自动装配SpringMvc的
2020-04-22 09:05:12在上一章中,我们介绍了springboot是如何启动一个内置tomcat的,看完之后你可能还有疑问,那么我的springmvc是什么时候配置的呢?为什么我在项目理解价格@requestMapping就能接收对应的请求呢? springboot是如何... -
三方源码 画饼图_SpringBoot启动tomcat源码解读
2021-01-04 10:16:27一、SpringBoot自动拉起Tomcat SpringBoot框架是当前比较流行的java后端开发框架,与maven结合大大简化了开发人员项目搭建的步骤...那么SpringBoot是如何启动这些第三方依赖的呢?下面以SpringBoot拉起tomcat容器为... -
springMVC启动出错,提示NoSuchMethodError
2013-05-06 10:49:45tomcat启动时报错 java.lang.NoSuchMethodError: org.springframework.web.context.support.WebApplicationContextUtils.initServletPropertySources(Lorg/springframework/core/env/MutablePropertySources;Ljavax... -
springmvc纯注解配置启动过程原理解析
2019-05-21 20:00:33下面,我们将演示如何搭建一个纯注解配置的springmvc,并通过跟踪源码的方式解析随着应用服务器的启动我们的springmvc配置是如何生效的。使用web容器版本:apache-tomcat-8.5.27 。代码中一些不重要的内容未展示。 ... -
tomcat加载spring+springMVC流程详解,看这一篇就够了
2020-12-09 14:23:56大家是否清楚,Tomcat是如何加载Spring和SpringMVC,今天我们就弄清下这个过程(记录最关键的东西) 其中会涉及到大大小小的知识,包括加载时候的设计模式,Servlet知识等,看了你肯定有所收获~ 文章首发个人公众号... -
Tomcat如何解析URL的请求参数(追踪HttpServletRequest对于请求参数的解析过程)
2017-02-09 15:54:15想起了前两个月同事问我:我发出的请求里如果有”a=f&a=g”,那么在Servlet里... 当时我就猜测是SpringMVC做的处理,然后启动了一个测试工程,并进行了Debug追踪,最终查询到了Tomcat的源码里,发现居然是它做的解析。 -
SpringMVC 请求处理流程
2021-02-19 18:53:44SpringMVC 请求处理流程 一,如何进行初始化,初始化时做了什么,...2,启动容器时触发TomcatStarter(实现了ServletContainerInitializer)onStartup方法初始化ServletContextInitializer接口的onStartup方法,第 -
springmvc工程的配置
2018-03-13 22:26:06启动tomcat时还是报错 初学springmvc,按照教程上把springmvc依赖的jar包全部下载下来了,添加到工程里,配置好web.xml和springmvc的配置文件(网上的教程有很多教你如何配置),但是启动tomcat时仍然在报错。... -
【转载】Tomcat如何解析URL的请求参数(追踪HttpServletRequest对于请求参数的解析过程)
2017-10-07 23:11:13当时我就猜测是SpringMVC做的处理,然后启动了一个测试工程,并进行了Debug追踪,最终查询到了Tomcat的源码里,发现居然是它做的解析。 现在想写个博客记录一下,却发现自己已经找不到当时追踪的痕迹了。。。于是... -
SpringMVC基础知识小结
2020-05-26 19:06:39【掌握】创建SpringMVC项目:配置pom.xml使得没有web.xml也不会报错,且添加spring-webmvc依赖,勾选Tomcat,创建启动入口类并重写其中的3个抽象方法,创建SpringMVC的配置类; 【掌握】使用控制器处理客户端提交的... -
Eclipse中Tomcat启动时间突然从45秒内飙至80秒并且网站卡顿极其严重,怎么解决?
2020-04-04 13:02:302.以debug模式启动tomcat,Loading XML bean消耗大量时间(我是springMVC通过基于注解的方式进行开发的)  ![图片说明]...