在web.xml中,对于每一个servlet都有一个load-on-startup属性,其值为一个整数。若该值为0或正整数,则当Web容器启动时,该servlet会自动加载,并调用其中的init()方法,整数值越小,加载的优先级越高;若值为负数或未指定,则该servlet只有被选择时才会被加载。
对应web.xml配置如下,这里优先级设为10:
这样即可实现servlet的自动加载。那么如果在项目中使用了Spring MVC框架,并且在初始化时需要整合Spring,或是需要用到在Spring中配置好的bean以及Spring MVC的controller,该如何处理呢?
我们知道,Spring通过ApplicationContext(通常翻译成上下文)来对bean进行配置与管理,因此若要与Spring整合,使用Spring的bean,必须先拿到相关的上下文,然后通过上下文获取bean。大致思路如下:
在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。
从上述代码的第19行可以看出,在该工程下只有一个Spring MVC DispatcherServlet,其名称为appServlet,那么我们就可以确定Spring MVC的上下文保存在org.springframework.web.servlet.FrameworkServlet.CONTEXT.appServlet中。获取方法如下:
而对于Spring的根上下文,bean的获取方式就有很多种了。通过根上下文,也可以拿到ServletContext相关信息。
最终代码:
因此,可以考虑通过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 = ... //获取ApplicationContext
ExampleBean 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);
}
}