上文中,我们讲解了如何通过实现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