Java™ Servlet 规范:javax.servlet.ServletContainerInitializer

概述

        ServletContainerInitializer是Servlet3.0规范中引入,目的是通过编程的手段创建web应用,而不是传统的web.xml方式。spring中实现了该接口。

        ServletContainerInitializer通过JAR包中的

META-INF/services/javax.servlet.ServletContainerInitializer

文件中的一个条目注册,JAR包中必须包含了ServletContainerInitializer接口的实现。

        ServletContainerInitializer通过javax.servlet.annotaion.HandelsTypes注解注册需要感知的类。

        当web应用程序中的类在启动时,ServletContainerInitializer的onStartup方法将收到那些满足javax.servlet.annotaion.handlesTypes类的通知。

示例

     spring使用了ServletContainerInitializer进行应用初始化。

org.springframework.web.SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
	@Override
	public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
			throws ServletException {

		List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();
        // 省略......
		servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
		AnnotationAwareOrderComparator.sort(initializers);
		for (WebApplicationInitializer initializer : initializers) {
			initializer.onStartup(servletContext);
		}
	}
}

        SpringServletContainerInitializer监听的是WebApplicationInitializer类,servlet容器启动时将会调用WebApplicationInitializer的onStartup方法完成应用程序的初始化。

Tomcat容器初始化

        tomcat在启动过程中也非常简单 ,它会扫描所有实现了ServletContainerInitializer的接口,通过获取HandlesTypes的注解,将ServletContainerInitializer与对应的类(由HandlesTypes注解指定)绑定在typeInitializerMap中。

    protected void processServletContainerInitializers() {

        List<ServletContainerInitializer> detectedScis;
        try {
            WebappServiceLoader<ServletContainerInitializer> loader = new WebappServiceLoader<>(context);
            detectedScis = loader.load(ServletContainerInitializer.class);
        } catch (IOException e) {
            log.error(sm.getString(
                    "contextConfig.servletContainerInitializerFail",
                    context.getName()),
                e);
            ok = false;
            return;
        }

        for (ServletContainerInitializer sci : detectedScis) {
            initializerClassMap.put(sci, new HashSet<>());

            HandlesTypes ht;
            try {
                ht = sci.getClass().getAnnotation(HandlesTypes.class);
            } catch (Exception e) {
                if (log.isDebugEnabled()) {
                    log.info(sm.getString("contextConfig.sci.debug",
                            sci.getClass().getName()),
                            e);
                } else {
                    log.info(sm.getString("contextConfig.sci.info",
                            sci.getClass().getName()));
                }
                continue;
            }
            if (ht == null) {
                continue;
            }
            Class<?>[] types = ht.value();
            if (types == null) {
                continue;
            }

            for (Class<?> type : types) {
                if (type.isAnnotation()) {
                    handlesTypesAnnotations = true;
                } else {
                    handlesTypesNonAnnotations = true;
                }
                Set<ServletContainerInitializer> scis =
                        typeInitializerMap.get(type);
                if (scis == null) {
                    scis = new HashSet<>();
                    typeInitializerMap.put(type, scis);
                }
                scis.add(sci);
            }
        }
    }

        在Tomcat的ServletContext类中,通过startInternal方法完成ServletContainerInitializer的调用(调用ServletContainerInitializer的onStartup方法)。

entry.getKey().onStartup(entry.getValue(),getServletContext())

            // Call ServletContainerInitializers
            for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry :
                initializers.entrySet()) {
                try {
                    entry.getKey().onStartup(entry.getValue(),
                            getServletContext());
                } catch (ServletException e) {
                    log.error(sm.getString("standardContext.sciFail"), e);
                    ok = false;
                    break;
                }
            }

  • 12
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值