精华内容
下载资源
问答
  • 通过对spring源码的解读,跟踪spring容器的启动过程,掌握SpringMVC是如何工作的;掌握Spring源码的设计增强阅读源码的技巧。为可持续性的使用spring框架高效集成开发,解决系统一些疑难杂症提供强有力的支撑。 ...

    参考网站:https://www.cnblogs.com/RunForLove/p/5688731.html

    通过对spring源码的解读,跟踪spring容器的启动过程,掌握SpringMVC是如何工作的;掌握Spring源码的设计和增强阅读源码的技巧。为可持续性的使用spring框架高效集成开发,解决系统一些疑难杂症提供强有力的支撑。

    一、需要掌握的理论业务点:

    1、Web容器初始化过程

    2、Spring MVC 在web.xml中的配置

    3、理解ServletContextListener

    4、掌握理解ContextLoadListener

    5、DispatcherServlet初始化(HttpServletBean • FrameworkServlet • DispatcherServlet)

    6、ContextLoadListener与DispatcherServlet的关系

    7、DispatcherServlet的设计

    8、DispatcherServlet工作原理

    二、分析各个理论节点的知识

    1、要想了解spring容器在web容器中启动的过程,首先我们需要知道web容器在tomcat中的生命周期,方可理解spring容器是如何在web容器中启动、运行、以及销毁、的生命周期

    上图展示了web容器在启动过程中主要业务走向,其官方给出的解释是:

    When a web application is deployed into a container, the following steps must be performed, in this order, before the web application begins processing client requests.
    1、Instantiate an instance of each event listener identified by a <listener> element in the deployment descriptor.
    2、For instantiated listener instances that implement ServletContextListener, call the contextInitialized() method.
    3、Instantiate an instance of each filter identified by a <filter> element in the deployment descriptor and call each filter instance's init() method.
    4、Instantiate an instance of each servlet identified by a <servlet> element that includes a <load-on-startup> element in the order defined by the load-on-startup element values, and call each servlet instance's init() method.
    

    翻译是:

    web应用程序部署到容器中时,必须按照以下顺序在web应用程序开始处理客户机请求之前执行以下步骤。

    实例化由部署描述符中的元素标识的每个事件侦听器的实例。

    对于实现ServletContextListener的实例化侦听器实例,调用contextInitialized()方法。

    实例化由部署描述符中的元素标识的每个过滤器的实例,并调用每个过滤器实例的init()方法。

    实例化由元素标识的每个servlet的实例,该元素按加载启动元素值定义的顺序包含元素,并调用每个servlet实例的init()方法。

    大致的意思是,tomcat在启动web容器的时候会启动一个叫ServletContextListener的监听器,每当在web容器中有ServletContextListener这个接口被实例化的时候,web容器会通知ServletContextListener被实例的对象去执行其contextInitialized()的方法进行相应的业务处理,而spring框架在设计的过程中ContextLoadListener这个类实现了ServletContextListener这个接口,因此每当有ContextLoadListener这个类被实例化的时候,web容器会通知他执行contextInitialized()这个方法

    2、spring MVC在web.xml在的配置
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    	<display-name>app</display-name>
    
    	<!-- 加载Spring配置文件 -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>classpath:spring-starter.xml</param-value>
    	</context-param>
    
    	<!-- Spring监听器 -->
    	<listener>
    		<description>Spring监听器</description>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>

     在web.xm配置中由<context-param>将spring的配置文件引入加载到web容器中,

    <listener>配置项是在web容器中启用监听,其所配置的class是需要启用的监听器,因此spring容器的启用是同过org.springframework.web.context.ContextLoaderListener进行spring容器的启动,而ContextLoaderListener监听实现的是ServlectContextListener接口,因此在其实例化的过程中,contextInitialized()会被调用,从而进行spring容器的启动与创建的过程中

    ContextLoaderListener中的contextInitialized()进行了spring容器的启动配置并且刷新实例化整个SpringApplicationContext中的Bean。因此,如果我们的Bean配置出错的话,在容器启动的时候,会抛异常出来的。

    @Override
    public void contextInitialized(ServletContextEvent event) {
        initWebApplicationContext(event.getServletContext());
    }
    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
        //Spring 启动的句柄,spring容器开始启动的根目录
        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!");
        } else {
            Log logger = LogFactory.getLog(ContextLoader.class);
            servletContext.log("Initializing Spring root WebApplicationContext");
            if(logger.isInfoEnabled()) {
                logger.info("Root WebApplicationContext: initialization started");
            }
    
            long startTime = System.currentTimeMillis();
    
            try {
                //处理spring容器是否已经创建(只创建没有创建spring的各个bean)
                if(this.context == null) {
                    this.context = this.createWebApplicationContext(servletContext);
                }
    
                if(this.context instanceof ConfigurableWebApplicationContext) {
                    ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)this.context;
                    if(!cwac.isActive()) {
                        if(cwac.getParent() == null) {
                            ApplicationContext parent = this.loadParentContext(servletContext);
                            cwac.setParent(parent);
                        }
    
                        //Spring容器创建完成后,加载spring容器的各个组件
                        this.configureAndRefreshWebApplicationContext(cwac, servletContext);
                    }
                }
    
                servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
                ClassLoader ccl = Thread.currentThread().getContextClassLoader();
                if(ccl == ContextLoader.class.getClassLoader()) {
                    currentContext = this.context;
                } else if(ccl != null) {
                    currentContextPerThread.put(ccl, this.context);
                }
    
                if(logger.isDebugEnabled()) {
                    logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
                }
    
                if(logger.isInfoEnabled()) {
                    long elapsedTime = System.currentTimeMillis() - startTime;
                    logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
                }
    
                return this.context;
            } catch (RuntimeException var8) {
                logger.error("Context initialization failed", var8);
                servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var8);
                throw var8;
            } catch (Error var9) {
                logger.error("Context initialization failed", var9);
                servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var9);
                throw var9;
            }
        }
    }

    以上完成Spring容器的创建 ,并在代码中配置加载Spring容器启动的配置文件,以及调用Spring容器的加载入口

    this.configureAndRefreshWebApplicationContext(cwac, servletContext);

    protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
        String configLocationParam;
        if(ObjectUtils.identityToString(wac).equals(wac.getId())) {
            configLocationParam = sc.getInitParameter("contextId");
            if(configLocationParam != null) {
                wac.setId(configLocationParam);
            } else {
                wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));
            }
        }
    
        wac.setServletContext(sc);
        //设置Spring容器启动的起始配置文件
        configLocationParam = sc.getInitParameter("contextConfigLocation");
        if(configLocationParam != null) {
            wac.setConfigLocation(configLocationParam);
        }
    
        ConfigurableEnvironment env = wac.getEnvironment();
        if(env instanceof ConfigurableWebEnvironment) {
            ((ConfigurableWebEnvironment)env).initPropertySources(sc, (ServletConfig)null);
        }
    
        this.customizeContext(sc, wac);
        //初始化spring的各个组件,以及spring容器中的各个bean
        wac.refresh();
    }
    Spring容器加载bean的过程入口:wac.refresh();
    
    protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
        String configLocationParam;
        if(ObjectUtils.identityToString(wac).equals(wac.getId())) {
            configLocationParam = sc.getInitParameter("contextId");
            if(configLocationParam != null) {
                wac.setId(configLocationParam);
            } else {
                wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));
            }
        }
    
        wac.setServletContext(sc);
        //设置Spring容器启动的起始配置文件
        configLocationParam = sc.getInitParameter("contextConfigLocation");
        if(configLocationParam != null) {
            wac.setConfigLocation(configLocationParam);
        }
    
        ConfigurableEnvironment env = wac.getEnvironment();
        if(env instanceof ConfigurableWebEnvironment) {
            ((ConfigurableWebEnvironment)env).initPropertySources(sc, (ServletConfig)null);
        }
    
        this.customizeContext(sc, wac);
        //初始化spring的各个组件,以及spring容器中的各个bean
        wac.refresh();
    }

    加spring容器中bean

    public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
        beanFactory.addBeanPostProcessor(new PostProcessorRegistrationDelegate.BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList();
        List<BeanPostProcessor> internalPostProcessors = new ArrayList();
        List<String> orderedPostProcessorNames = new ArrayList();
        List<String> nonOrderedPostProcessorNames = new ArrayList();
        String[] var8 = postProcessorNames;
        int var9 = postProcessorNames.length;
    
        String ppName;
        BeanPostProcessor pp;
        for(int var10 = 0; var10 < var9; ++var10) {
            ppName = var8[var10];
            if(beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if(pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            } else if(beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            } else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }
    
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, (List)priorityOrderedPostProcessors);
        List<BeanPostProcessor> orderedPostProcessors = new ArrayList();
        Iterator var14 = orderedPostProcessorNames.iterator();
    
        while(var14.hasNext()) {
            String ppName = (String)var14.next();
            BeanPostProcessor pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class);
            orderedPostProcessors.add(pp);
            if(pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
    
        sortPostProcessors(orderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, (List)orderedPostProcessors);
        //存放spring容器中加载的各个bean
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList();
        Iterator var17 = nonOrderedPostProcessorNames.iterator();
    
        while(var17.hasNext()) {
            ppName = (String)var17.next();
            pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if(pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
    
        registerBeanPostProcessors(beanFactory, (List)nonOrderedPostProcessors);
        sortPostProcessors(internalPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, (List)internalPostProcessors);
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }

    通过SerlvetContextListener这一特性还可以做其它的运用,如缓存数据在服务启动过程中的初始化

    https://blog.csdn.net/qq_31854907/article/details/86304955

     

     

     

     

     

     

    展开全文
  • tomcat + spring mvc 原理(一):tomcat原理综述比较详细的叙述了tomcat容器的静态结构和容器的配置,从tomcat动态运行来讲,我也在原理(一)中简单论述了: 显然,这种运作模式要求:tomcat需要有监视指定目录,一旦...


        tomcat + spring mvc 原理(一):tomcat原理综述比较详细的叙述了tomcat容器的静态结构和容器的配置,从tomcat动态运行来讲,我也在原理(一)中简单论述了:

    显然,这种运作模式要求:tomcat需要有监视指定目录,一旦有新的war包加入,就完成解包并动态加载编译后的class的能力;tomcat需要有网络端口开闭和监视的机制,维护线程池来处理随时可能到来的请求;tomcat还需要将到来的请求顺利地传递给spring mvc服务,然后再将服务返回的数据发送出去。

        其实,对tomcat的理解,不只是应该了解静态容器结构,对于动态运行方面,应该包括:    

    1. 容器的初始加载和启动
    2. war包动态监视和加载
    3. 网络请求的监控和处理

        这样基本就涵盖了tomcat所有的基本运作原理。本文主要涉及第一部分:容器的初始加载与启动。

    容器通用生命周期标准

        tomcat的容器,包括Server、Service、Connector、Engine、Host、Context、Wrapper都继承自同一个管理生命周期的接口:Lifecycle。
        首先,这个接口类定义了这些容器的初始化、启动、停止和销毁的标准生命周期方法。

    public interface Lifecycle {
        ......
        //容器初始化
        public void init() throws LifecycleException;
    
        //容器启动
        public void start() throws LifecycleException;
    
        //容器停止
        public void stop() throws LifecycleException;
    
        //容器销毁
        public void destroy() throws LifecycleException;
    
        ......
    }
    

        其次,这个接口类定义了这些容器所处生命周期的状态事件名和状态事件监听器的管理。

    public interface Lifecycle {
        ......
       /**
        *13种生命周期状态事件的名字。通过名字还是比较比较好理解的
        **/
        public static final String BEFORE_INIT_EVENT = "before_init";
    
        public static final String AFTER_INIT_EVENT = "after_init";
    
        public static final String START_EVENT = "start";
    
        public static final String BEFORE_START_EVENT = "before_start";
    
        public static final String AFTER_START_EVENT = "after_start";
    
        public static final String STOP_EVENT = "stop";
    
        public static final String BEFORE_STOP_EVENT = "before_stop";
    
        public static final String AFTER_STOP_EVENT = "after_stop";
    
        public static final String AFTER_DESTROY_EVENT = "after_destroy";
    
        public static final String BEFORE_DESTROY_EVENT = "before_destroy";
    
        public static final String PERIODIC_EVENT = "periodic";
    
        public static final String CONFIGURE_START_EVENT = "configure_start";
    
        public static final String CONFIGURE_STOP_EVENT = "configure_stop";
    
    
        /**
         *两个获取生命周期状态的方法
         **/
         //获取状态,内含事件和状态名
        public LifecycleState getState();
        //获取状态名
        public String getStateName();
    
    
        /**
         *状态事件监听器。LifecycleListener中包含一个处理事件的方
         *法LifecycleEvent()
         **/
         //添加状态事件监听器
        public void addLifecycleListener(LifecycleListener listener);
    
         //获取所有状态事件监听器
        public LifecycleListener[] findLifecycleListeners();
    
        //移除状态事件监听器
        public void removeLifecycleListener(LifecycleListener listener);
    
        ......
    }
    

    容器通用生命周期的实现

        Lifecycle接口类的通用实现是在LifecycleBase类中。
        容器都继承自LifeCycleBase类,LifecycleBase类为容器提供了基本生命周期方法的一般实现和生命周期状态监听器的管理实现。

    • 生命周期状态监听器的管理实现

        这一部分主要是监听器管理的实现,但真正发挥作用是在生命周期方法的实现中。
        LifecycleBase中使用一个自己定义的List–CopyOnWriteArrayList来存储LifecycleListener,本质上还是一个List,具体实现过于细节,这里不做研究。同时LifecycleBase基于监听器的List,对添加监听器、移除监听器、获取所有监听器的方法实现了逻辑。

    private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();
    //添加状态事件监听器的方法实现
    @Override
    public void addLifecycleListener(LifecycleListener listener) {
        lifecycleListeners.add(listener);
    }
    //获取所有状态事件监听器的方法实现
    @Override
    public LifecycleListener[] findLifecycleListeners() {
        return lifecycleListeners.toArray(new LifecycleListener[0]);
    }
    //移除状态事件监听器的方法实现
    @Override
    public void removeLifecycleListener(LifecycleListener listener) {
        lifecycleListeners.remove(listener);
    }
    

    需要特别注意的是,LifecycleBase实现了生命周期状态事件监听器处理事件的方法,其实就是遍历了监听器List,使用监听器的lifecleEvent方法处理了事件。这一方法在后面实现的init(),start()等生命周期的方法中都有间接调用,相当于只要更改了容器所处生命周期的状态,就需要对发布这一事件,调用该容器的关注该事件的监听器处理事件。

    protected void fireLifecycleEvent(String type, Object data) {
        LifecycleEvent event = new LifecycleEvent(this, type, data);
        for (LifecycleListener listener : lifecycleListeners) {
            listener.lifecycleEvent(event);
        }
    }
    
    • 生命周期方法实现

        LifecycleBase实现了Lifecycle的标准生命周期方法init()、start()、stop()、destroy()的逻辑。下面主要以init()和start()为例介绍实现的基本特点。

    //init()生命周期方法实现
    @Override
    public final synchronized void init() throws LifecycleException {
        if (!state.equals(LifecycleState.NEW)) {
        //new状态是最初加载时必须为NEW
            invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }
    
        try {
            setStateInternal(LifecycleState.INITIALIZING, null, false);
    
            initInternal();        //实际生命周期实现逻辑,由子类实现
    
            setStateInternal(LifecycleState.INITIALIZED, null, false);
        } catch (Throwable t) {
            handleSubClassException(t, "lifecycleBase.initFail", toString());
        }
    }
    

    通过init()的具体代码可以发现,LifecycleBase中主要就是设置了生命周期的状态,其中setStateInternal()除了设置了状态、校验了状态是否正确之外,还调用了上文提到的fireLifecycleEvent()响应了当前状态事件,触发了监听该事件的监听器监听到该事件的逻辑。由于不同子类(主要是不同容器)在初始化时所需要做的事不一样,所以initInternal()是真正被子类重载后做初始化的事情的方法。
        start()内部逻辑的特点和init()很相似,也是做了设置生命周期的状态,稍微复杂一些是需要:1.判断状态是否处于可以start()的阶段,不然就需要先init();2.是否失败需要stop()。

    @Override
    public final synchronized void start() throws LifecycleException {
        //校验状态,是否已经启动
        if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
                LifecycleState.STARTED.equals(state)) {
    
            if (log.isDebugEnabled()) {
                Exception e = new LifecycleException();
                log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
            } else if (log.isInfoEnabled()) {
                log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
            }
    
            return;  //已经启动,直接返回
        }
    
        if (state.equals(LifecycleState.NEW)) {
            init();  //如果未初始化,先初始化化
        } else if (state.equals(LifecycleState.FAILED)) {
            stop();  //失败直接终止
        } else if (!state.equals(LifecycleState.INITIALIZED) &&
                !state.equals(LifecycleState.STOPPED)) {
            invalidTransition(Lifecycle.BEFORE_START_EVENT);
        }
    
        try {
            setStateInternal(LifecycleState.STARTING_PREP, null, false);
    
            startInternal(); //实际生命周期实现逻辑,由子类实现
    
            if (state.equals(LifecycleState.FAILED)) {
                stop(); //失败直接终止
            } else if (!state.equals(LifecycleState.STARTING)) {
                invalidTransition(Lifecycle.AFTER_START_EVENT);
            } else {
                setStateInternal(LifecycleState.STARTED, null, false);
            }
        } catch (Throwable t) {
            handleSubClassException(t, "lifecycleBase.startFail", toString());
        }
    }
    

    可以看到,依旧有很多状态变更,和处理状态变更、发布状态变更事件的setStateInternal()的调用。

    宏观来看各种容器生命周期的实际流程

        在原理(一)我已经详细介绍了各种容器的配置、静态嵌套结构和各自的功能,铺垫了这么多,终于可以介绍各种容器是如果加载初始化的了。
    在这里插入图片描述
        首先按照基本嵌套结构,如图,最开始需要先启动Server,不管是Tomcat独立部署包还是spring mvc中的嵌入式tomcat-embed包,都需要先调用Server.init(),然后调用Server.start()。实际上,tomcat中Server的标准实现是StandardServer,根据LifecycleBase中实现的init()和start()的代码,实际上会调用子类重载的initInternal()和startInternal()方法。在StandardServer的initInternal()和startInternal()方法中,会调用StandardServer类中的Service实例的init()和start()方法…另一个方面,在StandardServer的addService()方法也会调用添加的Service实例(实际是StandardService类)的start()方法。同样的逻辑适用于Service下的Engine容器。
        Engine以下的Host、Context、Wrapper略有不同,因为它们都实现自Container接口,继承了Container接口的标准实现ContainerBase。Container中将每一种容器的包含关系定义为父子关系,即Host是Engine类的Container child,使用这个Container[]来存储所有Host子容器。同理Host和Context、Context和Wrapper都是相同的关系。在ContainerBase中实现的startInternal()有:

    Container children[] = findChildren();
    List<Future<Void>> results = new ArrayList<>();
    for (int i = 0; i < children.length; i++) {
        results.add(startStopExecutor.submit(new StartChild(children[i])));
    }
    

        需要特别注意的是,Container启动子容器的时候不一定是通过init()或者start()中调用相应子容器的生命周期函数。在容器的addChild方法中,也会调用子容器的start()方法,初始化加载和启动子容器,比如host的addChild(context)方法会调用context的start方法。
    统一使用多线程执行调用child的start方法,这样各个容器都能按顺序初始化和启动。
        关于边界的情况,比如Wrapper部分,由于和spring mvc相关,会在spring mvc原理里面叙述。

    本系列文章:
    tomcat + spring mvc原理(一):tomcat原理综述和静态架构
    tomcat + spring mvc原理(三):tomcat网络请求的监控与处理1
    tomcat + spring mvc原理(四):tomcat网络请求的监控与处理2
    tomcat + spring mvc原理(五):tomcat Filter组件实现原理
    tomcat + spring mvc原理(六):tomcat WAR包的部署与加载

    展开全文
  • 容器:管理对象的地方。spring,springMVCweb容器的区别?Tomcat(web容器)是管理servlet对象的地方,而springspringMVC是管理...其次,spring容器和springMVC容器是父子容器的关系,spring容器是父容器,sp...

    7d07e1fa6a0f53087eda0d7091f869b5.png

    容器:管理对象的地方。

    spring,springMVC和web容器的区别?
    Tomcat(web容器)是管理servlet对象的地方,而spring和springMVC是管理bean对象的地方,更进一步的讲,spring是管理service和dao的容器,springMVC是管理controller的容器。其次,spring容器和springMVC容器是父子容器的关系,spring容器是父容器,springMVC是子容器,而子容器可以访问父容器中的对象,父容器却不能访问子容器对象。通俗点就是,controller可以访问service对象,service不能访问controller对象。

    springMVC拦截器也是springMVC管理的,所以SpringMVC可以直接注入bean对象。

    web容器是管理servlet,以及过滤器(Filter),监听器(Listener)的。这些都是在web容器掌握范围内,但不在spring和springMVC范围内,因此我们无法再这些类中使用spring注解的方式获取需要的对象。如下,在这些类中获取bean对象的方式:
    方式一:

    public void contextInitialized(ServletContextEvent sce) {
      ApplicationContext context = (ApplicationContext) sce.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
      UserService userService = (UserService) context.getBean(“userService”);
    }
    方式二:

    public void contextInitialized(ServletContextEvent sce) {
      WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
      UserService userService = (UserService) webApplicationContext.getBean(“userService”);
    }
    以上参考的 博文

    过滤器作用过程:
    在这里插入图片描述

    springMVC拦截器和servlet过滤器的区别

    拦截器是基于java反射机制,过滤器是基于函数回调
    拦截器不依赖与servlet容器,过滤器依赖于servlet容器
    拦截器只对action请求起作用,过滤器对所有的请求都起作用
    拦截器可以访问action上下文,值栈里的对象,而过滤器不能
    在action的生命周期中拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
    拦截器可以调用IOC容器中的各个bean,而过滤器不能
    注:action是form表单里的属性,一般使用方式<form action=”处理页面路径”method=”post或get”>。

    展开全文
  • web容器中有servlet容器,spring项目部署后存在spring容器和springmvc容器。其中spring控制service层dao层的bean对象。springmvc容器控制controller层bean对象。servlet容器控制servlet对象。项目启动是,首先 ...

    在这里插入图片描述
    web容器中有servlet容器,spring项目部署后存在spring容器和springmvc容器。其中spring控制service层和dao层的bean对象。springmvc容器控制controller层bean对象。servlet容器控制servlet对象。项目启动是,首先 servlet初始化,初始化过程中通过web.xml中spring的配置加载spring配置,初始化spring容器和springmvc容器。待容器加载完成。servlet初始化完成,则完成启动。
    HTTP请求到达web容器后,会到达Servlet容器,容器通过分发器分发到具体的spring的Controller层。执行业务操作后返回结果。

    展开全文
  • Tomcat和Spring衔接

    千次阅读 2018-02-03 14:04:21
    1.概述:Tomcat启动的时候会触发Host的启动,进而触发我们的业务项目Context的启动,主要的配置文件就是\webapp\WEB-INF\web.xml,这里面会配置两个Spring容器,父容器是通过监听ServletContextListener上下文事件...
  • 一.背景 最近研究SpringBoot,SpringBoot内置了Tomcat容器,作为Web...web容器中有servlet容器,spring项目部署后存在spring容器和springmvc容器。 其中spring控制service层dao层的bean对象。springmvc容器控制c
  • Servlet容器Tomcat)是如何启动创建 Spring 容器的?
  • 手动创建一个 Spring 容器,然后调用容器的 getBean() 方法获取Spring容器中对应的Bean: public static void main(String[] args) { ApplicationContext apx = new ClassPathXmlApplicationContext("bean-factory...
  • Tomcat和jettey是HTTP服务器和Servlet容器,负责给类似Spring这种servlet提供一个运行的环境,其中:Http服务器与Servlet容器的功能界限是:可以把HTTP服务器想象成前台的接待,负责网络通信和解析请求,Servlet容器...
  • 回答这个问题之前,先要明确tomcat和spring mvc各自的指责是什么 tomcat:作为一个servlet容器,接受和返回http请求。 spring mvc:分发请求,执行处理器,返回数据,渲染视图。 tomcat和spring mvc的连接点在于...
  • 容器:在spring整体框架的核心概念中,容器的核心思想是管理...Tomcat(web容器)是管理servlet对象的地方,而Spring容器和SpringMVC容器是管理bean对象的地方,更进一步的讲,spring是管理servicedao的容器,sp...
  • tomcat + spring mvc 原理(一):tomcat原理综述tomcat + spring mvc的运作模式tomcat内部的基本容器构成tomcat容器对应的外部配置     tomat + spring mvc 是目前比较流行java微服务体系架构...
  • Jetty在启动时给每个Web应用创建一个全局的上下文环境,这个上下文就是ServletContext,其为后面的Spring容器提供宿主环境。 Tomcat&Jetty在启动过程中触发容器初始化事件,Spring的ContextLoaderListener会监听...
  • springmvc和spring它俩都是容器,容易就是管理对象的地方,例如Tomcat,就是管理servlet对象的,而springMVC容器和spring容器,就是管理bean对象的地方,再说的直白点 springmvc就是管理controller对象的容器,...
  • Spring容器Tomcat&Jetty在启动的过程中触发容器的初始化事件,Spring的ContextLoaderLlstener会监听到这个事件,它的contextInitialized方法会被调用,在这个方法中,Spring会初始化全局的Spring根容器,这...
  • 容器的概念在java中最熟悉的就是Tomcat了,它正是一个运行Servlet的web容器。...关于Spring容器的一个术语就是IOC容器。所谓IOC,是一种叫控制反转的编程思想。总之一句话,应用程序里不用再过问对...
  • 容器:管理对象的地方。 spring,springMVCweb容器的区别? Tomcat(web容器)是管理servlet对象的地方,而springspringMVC是管理...其次,spring容器和springMVC容器是父子容器的关系,spring容器是父容器,...
  • 感觉spring容器化思想对java来发者来说越来越重要了。所以我写一下我对spring容器的理解。 实际上spring容器就是一个放bean实例的容器(bean一定是实例化后的,类似于new())。当然了bean实例之前还需要进行类的...
  • 首先 springmvc和spring它俩都是容器,容易就是管理对象的地方,例如Tomcat,就是管理servlet对象的,而springMVC容器和spring容器,就是管理bean对象的地方,再说的直白点,springmvc就是管理controller对象的容器...
  • SpringBoot 内置了三种servlet 容器供大家选择,默认的是tomcat,说明它还是大众最多的选择。另外,也可以看出另外两种也还是有自己独有的优势。 从另一方面来说,SpringBoot 提供的默认配置也不一定最实用,对于...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,675
精华内容 670
关键字:

tomcat和spring容器

spring 订阅