spring 源码笔记 spring-web如何实现servlet规范 - Go语言中文社区

spring 源码笔记 spring-web如何实现servlet规范


servlet 3.0 规范

角色:应用方(spring) + servlet + web容器(tomcat)

servlet 3.0 规范
  • 规范提供ServletContainerInitializer接口,应用方提供实现类。
  • 规范提供"根目录/resources/META-INF/services/javax.servlet.ServletContainerInitializer"路径,应用方把ServletContainerInitializer接口实现类全类名写在该文件内。
  • 规范提供@HandlesTypes注解,由应用方配置,web容器解析,解析得到的实现类集合将通过参数传给ServletContainerInitializer.onStartup方法。
  • web容器启动完成回调ServletContainerInitializer.onStartup方法。

spring-web 如何实现servlet规范

spring提供WebApplicationInitializer接口,让程序员方便地进行web容器初始化回调。
spring把WebApplicationInitializer接口配置到@HandlesTypes,让web容器找到所有WebApplicationInitializer接口的实现类。
spring提供SpringServletContainerInitializer类实现ServletContainerInitializer接口,把web容器找到的实现类实例化出来,并执行。
spring把SpringServletContainerInitializer全类名配置到servlet规定的文件内,由web容器调用。

WebApplicationInitializer
public interface WebApplicationInitializer {
	void onStartup(ServletContext servletContext) throws ServletException;
}
SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
	// webAppInitializerClasses:web容器找到的WebApplicationInitializer的实现类集合
	@Override
	public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
		// 执行集合
		List<WebApplicationInitializer> initializers = new LinkedList<>();
		if (webAppInitializerClasses != null) {
			for (Class<?> waiClass : webAppInitializerClasses) {
				// 验证 添加到执行集合
				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);
		}
	}
}
/resources/META-INF/services/javax.servlet.ServletContainerInitializer
org.springframework.web.SpringServletContainerInitializer

自己实现servlet 3.0 规范

CustomWebApplicationInitializer
// 参考spring的WebApplicationInitializer接口
public interface CustomWebApplicationInitializer {
    void onStartup(ServletContext servletContext) throws ServletException;
}
CustomServletContainerInitializer
// 提供ServletContainerInitializer接口实现类,加上@HandlesTypes注解,传入自己提供的CustomWebApplicationInitializer接口
@HandlesTypes(CustomWebApplicationInitializer.class)
public class CustomServletContainerInitializer implements ServletContainerInitializer {
    @Override
    public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
        List<CustomWebApplicationInitializer> initializers = new LinkedList<>();
        if (c != null) {
            for (Class<?> waiClass : c) {
                if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && CustomWebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                    try {
                        initializers.add((CustomWebApplicationInitializer) ReflectionUtils.accessibleConstructor(waiClass).newInstance());
                    } catch (Throwable ex) {
                        throw new ServletException("Failed to instantiate CustomWebApplicationInitializer class", ex);
                    }
                }
            }
        }
        if (initializers.isEmpty()) {
            ctx.log("No Spring CustomWebApplicationInitializer types detected on classpath");
            return;
        }
        ctx.log(initializers.size() + " Spring CustomWebApplicationInitializers detected on classpath");
        AnnotationAwareOrderComparator.sort(initializers);
        for (CustomWebApplicationInitializer initializer : initializers) {
            initializer.onStartup(ctx);
        }
    }
}
/resources/META-INF/services/javax.servlet.ServletContainerInitializer
com.tbryant.springmvctest.customspringmvc.core.CustomServletContainerInitializer

使用自己实现servlet 3.0 规范

MyCustomWebApplicationInitializer
public class MyCustomWebApplicationInitializer implements CustomWebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) {
        System.out.println("web容器初始化回调,可在此添加spring容器启动代码");
    }
}

其他类文件请参考spring 零xml配置 & 内置tomcat 启动spring mvc

执行结果

在这里插入图片描述

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_37956177/article/details/104015684
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢