Spring MVC让Web容器启动时自动执行代码

来源:互联网 发布:我是传奇结局知乎 编辑:程序博客网 时间:2024/05/22 03:15
在web.xml中,对于每一个servlet都有一个load-on-startup属性,其值为一个整数。若该值为0或正整数,则当Web容器启动时,该servlet会自动加载,并调用其中的init()方法,整数值越小,加载的优先级越高;若值为负数或未指定,则该servlet只有被选择时才会被加载。

因此,可以考虑通过Servlet进行实现。并配置web.xml文件,令应用容器在启动时就自动加载一个servlet并执行其中的init()方法。servlet程序如下:

package com.xxx.action;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;public class AutoRunServlet extends HttpServlet {/** *  */private static final long serialVersionUID = 1L;public void init() throws ServletException {        System.out.println("Servlet has been initialized!");}}

对应web.xml配置如下,这里优先级设为10:

<servlet>        <servlet-name>autoRunServlet</servlet-name>        <servlet-class>com.xxx.action.AutoRunServlet</servlet-class>        <load-on-startup>10</load-on-startup>    </servlet>

这样即可实现servlet的自动加载。那么如果在项目中使用了Spring MVC框架,并且在初始化时需要整合Spring,或是需要用到在Spring中配置好的bean以及Spring MVC的controller,该如何处理呢?
我们知道,Spring通过ApplicationContext(通常翻译成上下文)来对bean进行配置与管理,因此若要与Spring整合,使用Spring的bean,必须先拿到相关的上下文,然后通过上下文获取bean。大致思路如下:

ApplicationContext ac = ... //获取ApplicationContextExampleBean bean = (ExampleBean)ac.getBean(ExampleBean.class);//假设要获取的bean类型为ExampleBean

在Spring MVC中,这个ApplicationContext叫做WebApplicationContext,它直接继承于ApplicationContext。Spring MVC的WebApplicationContext分为两种,一种是Spring创建的一个全局WebApplicationContext上下文,称为根上下文,注意这个上下文是Spring的,不是Spring MVC的,因此不包含Spring MVC的信息(如Spring MVC的controller等)。若在web.xml中配置了context-param,则其对应的xml对应的配置为根上下文。该上下文保存在ServletContext中(也叫application,Servlet的一个键值对空间,类似于session,但是与session的区别是ServletContext由所有客户端共用,而session只属于一个客户端)的一个键中,该键的名字为WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性的值,可以通过很多方法取出,下面会详述。另一种是Spring MVC的DispatcherServlet(Spring MVC的Servlet,可以拥有多个)加载后自己的上下文,除了拥有根上下文的所有内容,还有Spring MVC的信息。这样的上下文同样保存在ServletContext中,key为"org.springframework.web.servlet.FrameworkServlet.CONTEXT."+servlet名称。
知道了上下文存在哪里,我们的思路也就明朗了。只要拿到这个ServletContext,就可以通过key得到对应的上下文,继而得到bean。


考虑如下web.xml配置:

<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><!-- The definition of the Root Spring Container shared by all Servlets and Filters --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath*:service-context.xml</param-value></context-param><!-- Creates the Spring Container shared by all Servlets and Filters --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- Processes application requests --><servlet><servlet-name>appServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>appServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping></web-app>

从上述代码的第19行可以看出,在该工程下只有一个Spring MVC DispatcherServlet,其名称为appServlet,那么我们就可以确定Spring MVC的上下文保存在org.springframework.web.servlet.FrameworkServlet.CONTEXT.appServlet中。获取方法如下:


ServletContext sc = getServletContext();WebApplicationContext wac = (WebApplicationContext)sc.getAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.appServlet");ExampleSpringMVCBean bean = ac.getBean(ExampleSpringMVCBean.class);

而对于Spring的根上下文,bean的获取方式就有很多种了。通过根上下文,也可以拿到ServletContext相关信息。

ServletContext sc = getServletContext();  WebApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);ExampleBean bean = (ExampleBean)ac.getBean(ExampleBean.class);

ServletContext sc = getServletContext();  WebApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(sc);ExampleBean bean = (ExampleBean)ac.getBean(ExampleBean.class);//假设要获取的bean类型为ExampleBean

WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();ExampleBean bean = (ExampleBean)ac.getBean(ExampleBean.class);

ServletContext sc = getServletContext();WebApplicationContext wac = (WebApplicationContext)sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);ExampleBean bean = (ExampleBean)ac.getBean(ExampleBean.class);



最终代码:
public class AutoRunServlet extends HttpServlet {/** *  */private static final long serialVersionUID = 1L;public void init() throws ServletException {        ServletContext sc = getServletContext(); WebApplicationContext wac = (WebApplicationContext)sc.getAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.appServlet");ExampleSpringMVCBean bean = ac.getBean(ExampleSpringMVCBean.class);WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();ExampleBean bean = (ExampleBean)ac.getBean(ExampleBean.class);}}


1 0