• spring学习(十三)--自己实现SpringServletContainerInitializer


    上文中,我们讲解了如何通过实现WebApplicationInitializer接口来进行spring配置,讲解了SpringServletContainerInitializer实现的机制。

    本文我们模仿SpringServletContainerInitializer自己编写一个例子。

    * 本例子是编写一个类MyServletContainerInitializer,实现了ServletContainerInitializer接口的onStartup()方法。
    * 在MyServletContainerInitializer的onStartup()方法中找到所有的MyWebAppInitializer接口的实现类
    * 然后调用MyWebAppInitializer接口实现类的loadOnStart()方法
    * 这样,其他类只要实现了MyWebAppInitializer接口实现类的loadOnStart()方法,都会随着web容器启动被依次调用

    * 这样做的话,后续我们可以把自己的工程打包成jar,让其它工程引用,只要新的类实现MyWebAppInitializer接口的loadOnStart()方法,都会在web容器启动的时候被调用。

    下图为程序结构,一共需要编写5个文件:

    1、定义一个servlet,供测试

    package servlet;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 测试servlet,在MyWebAppInitializerImpl的loadOnStart方法中被加载到servletContext上下文
     * @author qiaozhong
     *
     */
    public class LittleBallServlet extends HttpServlet{
    
        private static final long serialVersionUID = 3684613967452881093L;
    
        @Override
        public void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException
            {
                resp.getWriter().write("Hello,I am a little ball!");
            } 
    }

    2、定义接口MyWebAppInitializer,声明方法loadOnStart()

    package interfaces;
    
    import javax.servlet.ServletContext;
    
    /**
     * 定义自己的初始化接口
     * @author qiaozhong
     *
     */
    public interface MyWebAppInitializer {
    
        /**
         * 接口中方法,在MyServletContainerInitializer中会被调用
         * @param servletContext
         */
        public void loadOnStart(ServletContext servletContext);
    }

    3、编写MyWebAppInitializer接口的实现类,实现loadOnStart()方法 

    package serviceImpl;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletRegistration;
    import servlet.LittleBallServlet;
    import interfaces.MyWebAppInitializer;
    
    /**
     * MyWebAppInitializer的实现类 
     * @author qiaozhong
     *
     */
    public class MyWebAppInitializerImpl implements MyWebAppInitializer{
    
        /**
         * 实现了MyWebAppInitializer接口中的方法loadOnStart
         * (non-Javadoc)
         * @see interfaces.MyWebAppInitializer#loadOnStart(javax.servlet.ServletContext)
         */
        public void loadOnStart(ServletContext servletContext){
            System.out.println("启动执行MyWebAppInitializerImpl loadOnStart()");
            ServletRegistration.Dynamic servletReg = servletContext.addServlet("LittleBallServlet", LittleBallServlet.class);
            servletReg.setLoadOnStartup(1);
            servletReg.addMapping("/LittleBall");
        }
    }

    4、编写MyServletContainerInitializer类实现javax.servlet.ServletContainerInitializer接口的onStartup方法,在该方法中,通过@HandlesTypes(MyWebAppInitializer.class)引入MyWebAppInitializer接口,扫描MyWebAppInitializer接口的所有实现类,调用其中的loadOnStart()方法。

    package initializerConfig;
    
    import interfaces.MyWebAppInitializer;
    import java.lang.reflect.Modifier;
    import java.util.Set;
    import javax.servlet.ServletContainerInitializer;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.HandlesTypes;
    
    //引入接口类MyWebAppInitializer
    @HandlesTypes(MyWebAppInitializer.class)
    
    /**
     * 定义自己的初始化类,实现javax的ServletContainerInitializer接口,实现onStartup()方法
     * web容器初始化时候,会通过SPI机制,自动扫描ServletContainerInitializer接口所有的实现类
     * 调用ServletContainerInitializer实现类的onStartup()方法
     * @author qiaozhong
     * 
     * 本例子是编写一个类MyServletContainerInitializer,实现了ServletContainerInitializer接口的onStartup()方法。
     * 在MyServletContainerInitializer的onStartup()方法中找到所有的MyWebAppInitializer接口的实现类
     * 然后调用MyWebAppInitializer接口实现类的loadOnStart()方法
     * 这样,其他类只要实现了MyWebAppInitializer接口实现类的loadOnStart()方法,都会随着web容器启动被依次调用
     */
    public class MyServletContainerInitializer implements ServletContainerInitializer{
    
        @Override
        public void onStartup(Set<Class<?>> set, ServletContext servletcontext)
                throws ServletException {
            if (set != null) {
                for (Class<?> waiClass : set) {
                    // Be defensive: Some servlet containers provide us with invalid classes,
                    // no matter what @HandlesTypes says...
                    if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
                            MyWebAppInitializer.class.isAssignableFrom(waiClass)) {
                        try {
                            //创建MyWebAppInitializer实现类的对象,并调用loadOnStart方法
                            ((MyWebAppInitializer) waiClass.newInstance()).loadOnStart(servletcontext);
                        } catch (Throwable ex) {
                            throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
                        }
                    }
                }
            }
        }
    }

    5、在src/main/resources下创建文件夹META-INF/services,创建文件名为:javax.servlet.ServletContainerInitializer

    该文件内容为:initializerConfig.MyServletContainerInitializer

    测试

    1、通过tomcat启动工程,会打印MyWebAppInitializer类中loadOnStart方法的日志:

    2、访问:http://localhost:8088/mySpringDemo/LittleBall

     

    个人理解,如有错误,欢迎指正!
  • 相关阅读:
    2018年5月29号(堆排序最小顶)
    2018年5月31号(树状数组)
    2018年5月27号(spfa判断负环)
    2018年6月1号(线段树(1))
    2018年5月28号(差分约束)
    Inno Setup入门(十二)——Pascal脚本(1)
    Inno Setup入门(十六)——Inno Setup类参考(2)
    Inno Setup入门(二十一)——Inno Setup类参考(7)
    Inno Setup入门(十)——操作注册表
    Inno Setup入门(十八)——Inno Setup类参考(4)
  • 原文地址:https://www.cnblogs.com/gllegolas/p/11759942.html
Copyright © 2020-2023  润新知