spring mvc的两种部署到Servlet容器的方式:web.xml 、WebApplicationInitializer 以及WebApplicationInitializer原理分析

方式一、编写web.xml

通常我们将一个spring mvc程序部署到Servlet容器(例如Tomcat)时,会使用该方式,示例如下:

<web-app>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/app-context.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>

</web-app>

其中,配置文件路径如图:

关于web.xml方式的更多细节不再探讨

 

方式二、实现WebApplicationInitializer(需要容器实现了Servlet 3.0+)

示例:

public class MyWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(javax.servlet.ServletContext servletContext) throws ServletException {
// Load Spring web application configuration
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        ac.register(SpringContent.class);
        ac.refresh();

        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration = servletContext.addServlet("mvc", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/");
    }
}

注:以上代码参考了spring官方文档:DispatcherServlet

其中,SpringContent类如下:

@ComponentScan(basePackages = "controller")
@Configuration
public class SpringContent {

    @Bean
    public org.springframework.web.servlet.view.InternalResourceViewResolver internalResourceViewResolver(){
        return new org.springframework.web.servlet.view.InternalResourceViewResolver("/WEB-INF/views/", ".jsp");
    }
}

实现WebApplicationInitializer的方式不再需要编写web.xml,实现了WebApplicationInitializer的具体类的onStartup函数会在Servlet容器启动时自动被调用,从而实现了在方法内注册spring ioc容器以及DispatcherServlet。

实现WebApplicationInitializer方式的原理如下

1.Servlet 3.0中定义了一个SPI接口javax.servlet.ServletContainerInitializer:

关于SPI是什么,可参考:java中的SPI机制

2.然后spring mvc有一个这个接口的实现类:org.springframework.web.SpringServletContainerInitializer

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {

	@Override
	public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
			throws ServletException {

		List<WebApplicationInitializer> initializers = new LinkedList<>();

		if (webAppInitializerClasses != null) {
			for (Class<?> waiClass : webAppInitializerClasses) {
				// Be defensive: Some servlet containers provide us with invalid classes,
				// no matter what @HandlesTypes says...
				if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
						WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
					try {
						initializers.add((WebApplicationInitializer)
								ReflectionUtils.accessibleConstructor(waiClass).newInstance());
					}
					catch (Throwable ex) {
						throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
					}
				}
			}
		}

		if (initializers.isEmpty()) {
			servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
			return;
		}

		servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
		AnnotationAwareOrderComparator.sort(initializers);
		for (WebApplicationInitializer initializer : initializers) {
            //此处是实际调用的地方
			initializer.onStartup(servletContext);
		}
	}

}
其中@HandlesTypes(WebApplicationInitializer.class),Servlet容器会查找所有jar包里实现了WebApplicationInitializer的类,最终会找到我们编写的MyWebApplicationInitializer并调用其onStartup方法。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值