我是靠谱客的博主 细心斑马,最近开发中收集的这篇文章主要介绍SpringBoot 借助 Servlet 3.1 新特性实现零配置的原理简介放置 ServletContainerInitializer 实现类的全路径设计想要被调用的类及其接口Servlet 将调用此类启动 Tomcat 看效果参考资料,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

SpringBoot 借助 Servlet 3.1 新特性实现零配置的原理

  • 简介
  • 放置 ServletContainerInitializer 实现类的全路径
  • 设计想要被调用的类及其接口
    • 接口
    • 实现类
  • Servlet 将调用此类
  • 启动 Tomcat 看效果
  • 参考资料

简介

  • Servlet 3.1 搞了个类似开机自动运行的规则。(但是我貌似 3.0 也跑起来了,不知道是不是我搞错了什么)
  • 1、创建此类,类名随意别作死就行。实现接口 javax.servlet.ServletContainerInitializer
  • 2、将此类全路径名,放到这个文件中:【/项目/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer】
  • 3、Servlet容器跑起来后,自动调用当前类的 onStartup
  • 4、onStartup 的参数 Set<Class<?>> 就是当前项目所有实现了 @HandlesTypes(IJerryAppInitializer.class) 接口的类。
  • 5、通过反射,玩转 JerryAppInitializer ()
    在这里插入图片描述

放置 ServletContainerInitializer 实现类的全路径

servlet通过它来找到我们创建的类(实现了 ServletContainerInitializer 接口 ),并运行 JerryServletContainerInitializer#onStartup()
/demo/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer

com.jerry.demo.JerryServletContainerInitializer

设计想要被调用的类及其接口

接口

目的是让所有实现了该接口的类都被自动调用。
/demo/src/main/java/com/jerry/service/IJerryAppInitializer.java

package com.jerry.service;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;

public interface IJerryAppInitializer {
	// 这个名字自己取得
	void onJerryStartup(ServletContext servletContext) throws ServletException;
}

实现类

实现我们自定的接口,处理具体业务逻辑。比如注册 servlet 进行配置等。以实现编程式配置
/demo/src/main/java/com/jerry/service/impl/JerryAppInitializer.java

package com.jerry.service.impl;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import com.jerry.service.IJerryAppInitializer;

public class JerryAppInitializer implements IJerryAppInitializer{

	@Override
	public void onJerryStartup(ServletContext servletContext) throws ServletException {
		System.out.println("我是 com.jerry.service.impl.JerryApplicationInitializer,我是被 /demo/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer 折腾起来的。");
	}
}

Servlet 将调用此类

Servlet 将调用此类,此类再调用我上面定义的【想要被调用的类
在此类中,我们能获得所有IJerryAppInitializer的实现类的实例(系统通过 onStartup的参数Set<Class<?>> xxx 传给我们)。并通过反射调用其方法。
/demo/src/main/java/com/jerry/demo/JerryServletContainerInitializer.java

package com.jerry.demo;

import java.lang.reflect.Modifier;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes;

import com.jerry.service.IJerryAppInitializer;

/**
 * Servlet 3.1 搞了个类似开机自动运行的规则。
 * 1、创建此类,类名随意别作死就行。实现接口 javax.servlet.ServletContainerInitializer
 * 2、将此类全路径名,放到这个文件中:【/项目/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer】
 * 3、Servlet容器跑起来后,自动调用当前类的 onStartup
 * 4、onStartup 的参数 Set<Class<?>> 就是当前项目所有实现了  @HandlesTypes(IJerryAppInitializer.class) 接口的类。
 * 5、通过反射,玩转 JerryAppInitializer ()
 * @author jerryjin
 */
@HandlesTypes(IJerryAppInitializer.class)
public class JerryServletContainerInitializer implements ServletContainerInitializer {

	@Override
	public void onStartup(Set<Class<?>> jerryAppInitializerClasses, ServletContext servletContext) throws ServletException {
		System.out.println("servlet3.1 规定的  javax.servlet.ServletContainerInitializer 跑起来了");
	
		List<IJerryAppInitializer> initializers = new LinkedList<>();

		if (jerryAppInitializerClasses != null) {
			for (Class<?> clazz : jerryAppInitializerClasses) {
				if (!clazz.isInterface() 
						&& !Modifier.isAbstract(clazz.getModifiers()) 
						&& IJerryAppInitializer.class.isAssignableFrom(clazz))
				{
					try {
						initializers.add((IJerryAppInitializer)clazz.newInstance());
					}
					catch (Throwable ex) {
						throw new ServletException("实例化 JerryAppInitializer 失败!", ex);
					}
				}
			}
		}

		if (initializers.isEmpty()) {
			servletContext.log("木有找到 com.jerry.service.IJerryAppInitializer");
			return;
		}

		servletContext.log(initializers.size() + "个 IJerryAppInitializer 实现类在 classpath 出没");
		
		for (IJerryAppInitializer initializer : initializers) {
			// 
			initializer.onJerryStartup(servletContext);
		}
	
	}

}

启动 Tomcat 看效果

。。。
servlet3.1 规定的  javax.servlet.ServletContainerInitializer 跑起来了
我是 com.jerry.service.impl.JerryApplicationInitializer,我是被 /demo/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer 折腾起来的。

信息: 1个 IJerryAppInitializer 实现类在 classpath 出没
。。。

参考资料

【鲁班学院】2019全网最全面的spring boot源码分析
org.springframework.web.WebApplicationInitializer.java
org.springframework.web.SpringServletContainerInitializer.java

最后

以上就是细心斑马为你收集整理的SpringBoot 借助 Servlet 3.1 新特性实现零配置的原理简介放置 ServletContainerInitializer 实现类的全路径设计想要被调用的类及其接口Servlet 将调用此类启动 Tomcat 看效果参考资料的全部内容,希望文章能够帮你解决SpringBoot 借助 Servlet 3.1 新特性实现零配置的原理简介放置 ServletContainerInitializer 实现类的全路径设计想要被调用的类及其接口Servlet 将调用此类启动 Tomcat 看效果参考资料所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(31)

评论列表共有 0 条评论

立即
投稿
返回
顶部