【SpringMVC】是如何接管Servlet容器的(如何注册DispatcherServlet的)

Servlet3.0规范

Servlet3.0规范:Servlet容器(eg.Tomcat)启动后,会自动从容器中找ServletContainerInitializer的实现类,然后通过反射创建实例并调用其onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)方法,传入两个参数,第一个为该实现类上的@HandlesTypes注解指定的类型的所有后代类的集合,第二个为ServletContext

package javax.servlet;

public interface ServletContainerInitializer {

    public void onStartup(Set<Class<?>> c, ServletContext ctx)
        throws ServletException; 
}
package javax.servlet.annotation;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface HandlesTypes {

    Class<?>[] value();
}

SpringMVC接管Servlet容器

Spring提供了SpringServletContainerInitializer实现了ServletContainerInitializer接口,并指定对WebApplicationInitializer接口的子类感兴趣
在这里插入图片描述

package org.springframework.web;

//SpringMVC接管Servlet容器(Tomcat),并指定对WebApplicationInitializer接口的子类感兴趣
@HandlesTypes(WebApplicationInitializer.class)
SpringServletContainerInitializer implements ServletContainerInitializer{
    //Servlet容器启动后,会自动调这个方法,传入webAppInitializerClasses(感兴趣接口的后代类集合)和servletContext(servlet上下文)
    public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext){
        //遍历传入的所有WebApplicationInitializer后代类,创建实例,并调用onStartup(servletContext)方法
        ......
    }
}
public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer {
	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		registerContextLoaderListener(servletContext);
	}

	protected void registerContextLoaderListener(ServletContext servletContext) {
		//创建root的WebApplicationContext(父容器)
		WebApplicationContext rootAppContext = createRootApplicationContext();
		if (rootAppContext != null) {
			//创建ContextLoaderListener,并监听rootAppContext的启动
			ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
			listener.setContextInitializers(getRootApplicationContextInitializers());
			servletContext.addListener(listener);
		}
		else {
			logger.debug("No ContextLoaderListener registered, as " +
					"createRootApplicationContext() did not return an application context");
		}
	}
	
	protected abstract WebApplicationContext createRootApplicationContext();
}
package org.springframework.web.servlet.support;

AbstractDispatcherServletInitialize extends AbstractContextLoaderInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);
        registerDispatcherServlet(servletContext);
    }

    //创建一个DispatcherServlet实例并添加到servletContext中
    protected void registerDispatcherServlet(ServletContext servletContext){
        String servletName = getServletName();
		Assert.hasLength(servletName, "getServletName() must not return null or empty");
		
		//创建Servlet的WebApplicationContext(子容器)
		WebApplicationContext servletAppContext = createServletApplicationContext();
		Assert.notNull(servletAppContext, "createServletApplicationContext() must not return null");
		
		//创建DispatcherServlet
		FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
		Assert.notNull(dispatcherServlet, "createDispatcherServlet(WebApplicationContext) must not return null");
		dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());

		//将创建的DispatcherServlet注册到创建的Servlet的WebApplicationContext中
		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);
		registration.addMapping(getServletMappings());
		registration.setAsyncSupported(isAsyncSupported());

		Filter[] filters = getServletFilters();
		if (!ObjectUtils.isEmpty(filters)) {
			for (Filter filter : filters) {
				registerServletFilter(servletContext, filter);
			}
		}

		customizeRegistration(registration);
    }
	
	protected abstract WebApplicationContext createServletApplicationContext();
	
	protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
		return new DispatcherServlet(servletAppContext);
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值