在一個網站啟動、結束時,我們經常有些操作是需要執行的。
熟悉Asp.net的朋友,使用Global.asax很容易就搞定,在其中有Application_Start和Application_End等方法可以供我們來輕松實現。
但是,在Java的SpringMVC框架中,需要如何實現這個功能呢?在互聯網上,有不少類似文章,介紹功能的實現,我看過很多篇文檔,基本都在一些關鍵點有所缺失,很多新手朋友照做往往達不到效果,下面我來闡述一下我正在使用的方法。
原理:使用注解@PostConstruct和@PreDestroy來實現功能。 從Java EE 5規范開始,Servlet中增加了兩個影響Servlet生命周期的注解(Annotion);@PostConstruct和@PreDestroy。這兩個注解被用來修飾一個非靜態的void()方法 。寫法有如下兩種方式: @PostConstruct public void applicationStart(){ System.out.println("application start"); }
public @PostConstruct void applicationStart(){ System.out.println("application start"); } 被@PostConstruct修飾的方法會在服務器加載Servle的時候運行,並且只會被服務器執行一次。PostConstruct在構造函數之后執行,init()方法之前執行。執行生命周期如下: |
下邊直接來看程序中怎么寫吧,下圖是我用來測試的項目結構,標紅的3個是這個功能需要涉及的文件。
其中,web.xml用來配置Spring的servlet,內容如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>InskyScheduleCenter</display-name>
<!-- Spring應用上下文, 理解層次化的ApplicationContext --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/spring/applicationContext*.xml</param-value> </context-param>
<!-- DispatcherServlet, Spring MVC的核心 --> <servlet> <servlet-name>InskyScheduleCenter</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- DispatcherServlet對應的上下文配置, 默認為/WEB-INF/$servlet-name$-servlet.xml --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/spring/ScheduleCenter-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>InskyScheduleCenter</servlet-name> <!-- mvc-dispatcher攔截所有的請求 --> <url-pattern>/</url-pattern> </servlet-mapping>
</web-app> |
這個文件沒啥說的,只是標明contextConfigLocation的位置。
再看ScheduleCenter-servlet.xml文件。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 本配置文件為InskyScheduleCenter項目提供其相關的Spring MVC配置 -->
<!-- 啟用Spring基於annotation的DI, 使用戶可以在Spring MVC中使用Spring的強大功能。 激活 @Required @Autowired,JSR 250's @PostConstruct, @PreDestroy and @Resource 等標注 --> <context:annotation-config />
<!-- 掃描自動加載的包名 --> <context:component-scan base-package="com.insky.InskyScheduleCenter.web"> </context:component-scan>
</beans> |
其中,<context:annotation-config />一定要加上,這樣才可以激活對@PostConstruct和@PreDestroy等注解。自動掃描的包名也要寫對,確保我們的功能類global.java在配置的包名下。
最后看global.java文件。
package com.insky.InskyScheduleCenter.web.util;
import javax.annotation.PostConstruct; import javax.annotation.PreDestroy;
import org.springframework.stereotype.Service;
/** * * web應用的全局事件 * @author Simon * */ @Service public class global {
/** * 在web啟動時執行 */ @PostConstruct public void applicationStart(){ System.out.println("application start"); }
/** * 在web結束時執行 */ @PreDestroy public void applicationEnd(){ System.out.println("InskyScheduleCenter application end");
} } |
我們看到,這個類位於配置的被掃描包名com.insky.InskyScheduleCenter.web之下。
其中,在applicationStart和applicationEnd方法之上,存在注解@PostConstruct和@PreDestroy,當網站啟動時,自動掃描到這兩個注解時,在相應的生命周期,就會執行被注解的方法。
注意global.java的class頂部被標紅的注解@Service,在很多文章中,其貼出的代碼上沒有這個注解,很多照做的新手朋友最終沒有加上,運行的時候就沒有效果了,最終會多花很多時間去找問題。
因為配置文件中的<context:component-scan base-package="com.insky.InskyScheduleCenter.web"></context:component-scan>只有掃描到有@Component @Controller@Service等這些注解的類,才會把這些類注冊為bean,只有被注冊為bean,才會加載到web容器的生命周期。
當然,實現這個功能還有很多其它的方式,如實現ApplicationListener接口等,我將會在未來的文章中闡述其它們。