当前位置:   article > 正文

SpringBoot 借助 Servlet 3.1 新特性实现零配置的原理_springboot3.1.2使用javax.servlet

springboot3.1.2使用javax.servlet

简介

  • 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
  • 1

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

接口

目的是让所有实现了该接口的类都被自动调用。
/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;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

实现类

实现我们自定的接口,处理具体业务逻辑。比如注册 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 折腾起来的。");
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

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);
		}
	
	}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

启动 Tomcat 看效果

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

信息: 1个 IJerryAppInitializer 实现类在 classpath 出没
。。。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

参考资料

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/480577
推荐阅读
相关标签
  

闽ICP备14008679号