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

在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 = ... //获取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);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值