zoukankan      html  css  js  c++  java
  • Spring中WebApplicationInitializer的理解

    现在JavaConfig配置方式在逐步取代xml配置方式。而WebApplicationInitializer可以看做是Web.xml的替代,它是一个接口。通过实现WebApplicationInitializer,在其中可以添加servlet,listener等,在加载Web项目的时候会加载这个接口实现类,从而起到web.xml相同的作用。下面就看一下这个接口的详细内容。

         首先打开这个接口,如下:

    public interface WebApplicationInitializer {
    void onStartup(ServletContext var1) throws ServletException;
    }
         只有一个方法,看不出什么头绪。但是,在这个包下有另外一个类,SpringServletContainerInitializer。它的实现如下:

    package org.springframework.web;

    import java.lang.reflect.Modifier;
    import java.util.Iterator;
    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 org.springframework.core.annotation.AnnotationAwareOrderComparator;

    @HandlesTypes({WebApplicationInitializer.class})
    public class SpringServletContainerInitializer implements ServletContainerInitializer {
    public SpringServletContainerInitializer() {
    }

    public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
    List<WebApplicationInitializer> initializers = new LinkedList();
    Iterator var4;
    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)waiClass.newInstance());
    } catch (Throwable var7) {
    throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
    }
    }
    }
    }

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

    while(var4.hasNext()) {
    WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
    initializer.onStartup(servletContext);
    }

    }
    }
    }
        这个类就比较有意思了,先不管其他的,读一下这段代码,可以得到这样的意思。

                 先判断webAppInitializerClasses这个Set是否为空。如果不为空的话,找到这个set中不是接口,不是抽象类,并且是

    WebApplicationInitializer接口实现类的类,将它们保存到list中。当这个list为空的时候,抛出异常。不为空的话就按照一定的顺序排序,并将它们按照一定的顺序实例化。调用其onStartup方法执行。到这里,就可以解释WebApplicationInitializer实现类的工作过程了。但是,在web项目运行的时候,SpringServletContainerInitializer这个类又是怎样被调用的呢。

               它只有一个接口,ServletContainerInitializer,通过它就可以解释SpringServletContainerInitializer是如何被调用的。它的内容如下,

    package javax.servlet;

    import java.util.Set;

    public interface ServletContainerInitializer {
    void onStartup(Set<Class<?>> var1, ServletContext var2) throws ServletException;
    }
               首先,这个接口是javax.servlet下的。官方的解释是这样的:为了支持可以不使用web.xml。提供了ServletContainerInitializer,它可以通过SPI机制,当启动web容器的时候,会自动到添加的相应jar包下找到META-INF/services下以ServletContainerInitializer的全路径名称命名的文件,它的内容为ServletContainerInitializer实现类的全路径,将它们实例化。既然这样的话,那么SpringServletContainerInitializer作为ServletContainerInitializer的实现类,它的jar包下也应该有相应的文件。打开查看如下:

                                

             哈,现在就可以解释清楚了。首先,SpringServletContainerInitializer作为ServletContainerInitializer的实现类,通过SPI机制,在web容器加载的时候会自动的被调用。(这个类上还有一个注解@HandlesTypes,它的作用是将感兴趣的一些类注入到ServletContainerInitializerde), 而这个类的方法又会扫描找到WebApplicationInitializer的实现类,调用它的onStartup方法,从而起到启动web.xml相同的作用。

             然后,我们自己通过一个实例来实现相同的功能,通过一样的方式来访问一个servlet。

            

             1、定义接口WebParameter,它就相当于WebApplicationInitializer。内容如下:

    public interface WebParameter {

    void loadOnstarp(ServletContext servletContext);
    }
              可以在这里面添加servlet,listener等。

           2、定义Servlet。

    public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.getWriter().write("TestSetvlet");
    }
    }
           3、定义MyWebParameter作为WebParameter的实现类,将Servlet添加到上下文,并设置好映射。

    public class MyWebParameter implements WebParameter {
    public void loadOnstarp(ServletContext servletContext) {
    ServletRegistration.Dynamic testSetvelt=servletContext.addServlet("test","com.test.servlet.MyServlet");
    testSetvelt.setLoadOnStartup(1);
    testSetvelt.addMapping("/test");
    }
    }
           4、定义好WebConfig作为ServletContainerInitializer的实现类,它的作用是扫描找到WebParameter的实现类,并调用其方法。 

    @HandlesTypes({WebParameter.class})
    public class WebConfig implements ServletContainerInitializer {
    public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
    Iterator var4;
    if (set!=null){
    var4=set.iterator();
    while(var4.hasNext()){
    Class<?> clazz= (Class<?>) var4.next();
    if (!clazz.isInterface()&& !Modifier.isAbstract(clazz.getModifiers())&&WebParameter.class.isAssignableFrom(clazz)){
    try {
    ((WebParameter) clazz.newInstance()).loadOnstarp(servletContext);
    }catch (Exception e){
    e.printStackTrace();
    }
    }
    }
    }
    }
    }
             5、根据SPI机制,定义一个META-INF/services文件夹,并在其下定义相关文件名称,并将WebConfig的类全名称填入其中。

                  

                  至此,相关内容就完成了,因为我用的maven,通过install将其作为jar包上传到本地仓库。从另外一个web项目调用这个包进行访问。

             6、最终结果:

                         

                相关代码请转至我的github点击打开链接
    ————————————————
    版权声明:本文为CSDN博主「大多多」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/zq17865815296/article/details/79464403

  • 相关阅读:
    leetcode108 Convert Sorted Array to Binary Search Tree
    leetcode98 Validate Binary Search Tree
    leetcode103 Binary Tree Zigzag Level Order Traversal
    leetcode116 Populating Next Right Pointers in Each Node
    Python全栈之路Day15
    Python全栈之路Day11
    集群监控
    Python全栈之路Day10
    自动部署反向代理、web、nfs
    5.Scss的插值
  • 原文地址:https://www.cnblogs.com/daxiong225/p/12258205.html
Copyright © 2011-2022 走看看