实现自己的ServletContainerInitializer
在Web容器启动的时候为提供给第三方组件做一些初始化的工作。
例如注册servlet或者filters等
servlet规范中通过ServletContainerInitializer实现次功能,每个框架再使用ServeletContainerInitlizer就必须在jar 包的META-INF/services 目录穿件一个名为javax.servlet.ServletContainerInitializer的文件 文件内容制定具体的ServletContainerInitlizer实现类
META-INF/services/javax.servlet.ServletContainerInitializer
我们的servlet类:
public class HelloService extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.write("Hello World");
writer.flush();
}
}
创建我们的这样的一个Initializer,并把servlet程序添加到Servlet 上下文对象当中:
@HandlesTypes(value = MyHandleType.class)
public class MyServletContainerInitializer implements ServletContainerInitializer
{
/**
* 作用
* @param set
* @param servletContext
* @throws ServletException
*/
@Override
public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
set.stream().forEach(c -> System.out.println(c.getName()));
ServletRegistration registration = servletContext.addServlet("helloService", HelloService.class);
registration.addMapping("/hello");
}
}
注解HandlesTypes 的value属性标示的类的子类,或者实现累标示类接口的类,是onStartup方法中形参Set集合中的元素。
这个onStartup方法 可以获取到Servlet上下文对象,我们可以为此上下文注册Servlet对象,或者Listener对象,或者是拦截器对象。
上面的代码注册了一个Servlet ,并切设置路由为 /hello
在
resources/META-INF/services/javax.servlet.ServletContainerInitializer文件中加入你的实现了ServletContainerInitializer接口的类。
crown.config.MyServletContainerInitializer
把应用部署到Tomcat 启动 在浏览器输入localhost:8080/hello
使用WebApplicationInitializer 实现无Web.xml的SpringMVC 程序
新建项目MyMvc3,导入servlet jar ,跟Spring-webmvc的jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
打开
路径:
spring-web-5.1.8.RELEASE.jar!/META-INF/services/javax.servlet.ServletContainerInitializer
内容:
org.springframework.web.SpringServletContainerInitializer
接着上面的话 :我们在META-INF/services/javax.servlet.ServletContainerInitializer 中定义的class :SpringServletContainerInitializer
@HandlesTypes({WebApplicationInitializer.class})
public class SpringServletContainerInitializer implements ServletContainerInitializer {
public SpringServletContainerInitializer() {
}
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
List<WebApplicationInitializer> initializers = new LinkedList();
Iterator var4;
//有类实现了WebApplicationInitializer 就把实现了的都加到Set集合当中
if (webAppInitializerClasses != null) {
var4 = webAppInitializerClasses.iterator();
while(var4.hasNext()) {
Class<?> waiClass = (Class)var4.next();
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer)ReflectionUtils.accessibleConstructor(waiClass, new Class[0]).newInstance());
} catch (Throwable var7) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
}
}
}
}
//集合为空就是表示没有类继承WebApplicationInitializer
if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
} else {
servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
var4 = initializers.iterator();
//调用每个实现累Webinitializer的onStartup方法,并传入当前的上下文对象
while(var4.hasNext()) {
WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
initializer.onStartup(servletContext);
}
}
}
}
首先它的HandlesTypes是WebApplicationInitializer
public interface WebApplicationInitializer {
void onStartup(ServletContext var1) throws ServletException;
}
它是一个接口 如果我们实现了它 就可以去添加Servlet到容器的上下文对象。
首先创建用来测试的Controller
com.crown.controller.HelloController
@RestController("/")
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "Hello World";
}
}
创建配置类
@Configuration
//开启注解
@EnableWebMvc
@ComponentScan(basePackages = "com.crown.controller")
public class MyMvcConfig {
}
下面创建我们最为主要的
public class MyWebInitializer implements WebApplicationInitializer {
@Override
public void onStartup(javax.servlet.ServletContext servletContext) throws ServletException {
//创建Web上下文
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
//注册我们的配置类 让他去加载我们需要扫包的类
context.register(MyMvcConfig.class);
//把DispatcherServlet程序放到servlet 上下文当中
ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcherServlet",new DispatcherServlet(context));
//拦截所有的请求
registration.addMapping("/");
//最高优先级启动
registration.setLoadOnStartup(1);
}
}