將您的易失性數據放入JNDI中。重新部署之間沒有清理JNDI。在init
期間,您的servlet仍然可以執行相同的操作,以確保JNDI中的數據是最新的。
我不記得JNDI讀/寫是否是線程安全的,但事實並非如此,您可以始終放置一個線程安全的對象(例如ConcurrentHashMap
),並且可以毫無問題地使用它。
編輯可通過MS:
==========
restart.pl:
==========
ReadMode 2; print "\nEnter spice: "; chomp ($spice = <STDIN>); print "\n";
ReadMode 0;
open (FP, ">$spicefile") or die "$0: Cannot write file $spicefile: $!\n";
print FP "$spice\n"; close (FP);
system "bin/shutdown.sh"; sleep 8;
system "bin/startup.sh"; sleep 8; system "wget $tomcaturl";
system '/bin/rm -rf *spicefile*'; # delete wget output file
foreach $sCount (1..10) { # give it 10 more secs
sleep 1;
if (-f $spicefile) {
print "$0: Waiting on servlet to delete spicefile [$sCount]\n"
} else {
print "$0: Successful servlet initialization, no spicefile\n";
exit 0
}}
print "\n$0: deleting file $spicefile ...\n"; # Error condition
system "unlink $spicefile";
exit 1;
===========
context.xml
===========
<Resource name="MyServlet/upsBean" auth="Container" type="packageName.UPSBean"
factory="org.apache.naming.factory.BeanFactory" readOnly="false"/>
===================
app/WEB-INF/web.xml
===================
<listener>
<listener-class>packageName.DBInterface</listener-class>
</listener>
<resource-env-ref>
<description>Use spice as transferable during redeployment</description>
<resource-env-ref-name>MyServlet/upsBean</resource-env-ref-name>
<resource-env-ref-type>packageName.UPSBean</resource-env-ref-type>
</resource-env-ref>
==============
MyServlet.java:
==============
init() {
if (new File (spiceFile).exists()) # Same name in restart.pl
dbi = new DBInterface (spiceFile);
else
dbi = new DBInterface(); # Redeployment
otherInitializations (dbi.getSpice());
}
================
DBInterface.java:
================
public DBInterface() {
// Comment out following block if contextInitialized works
FileInputStream fin = new FileInputStream (safeDepositBox);
ObjectInputStream ois = new ObjectInputStream (fin);
UPSBean upsBean = (UPSBean) ois.readObject();
ois.close();
spice = upsBean.getSpice();
dbiIndex = 2;
// do stuff with spice
}
public DBInterface (String spiceFileName) {
File file = new File (spiceFileName);
BufferedReader br = new BufferedReader (new FileReader (file));
spice = br.readLine();
br.close();
file.delete();
dbiIndex = 1;
// Delete following block if contextInitialized works
UPSBean upsBean = new UPSBean();
upsBean.setSpice (spice);
FileOutputStream fout = new FileOutputStream (safeDepositBox);
ObjectOutputStream oos = new ObjectOutputStream (fout);
oos.writeObject (upsBean);
oos.flush();
oos.close();
// do stuff with spice and if it works, ...
// contextInitialized (null);
}
// Above is working currently, would like the following to work
public void contextDestroyed(ServletContextEvent sce) {
System.setProperty ("spice", spice);
System.out.println ("[DBInterface" + dbiIndex +
"] Spice saved at " +
DateFormat.getDateTimeInstance (DateFormat.SHORT,
DateFormat.LONG).format (new Date()));
}
public void contextInitialized(ServletContextEvent sce) {
if (sce != null) {
spice = System.getProperty ("spice");
System.out.println ("[DBInterface" + dbiIndex +
"] Spice retrieved at " +
DateFormat.getDateTimeInstance (DateFormat.SHORT,
DateFormat.LONG).format (new Date()));
}
// do stuff with spice
}
============
UPSBean.java:
============
public class UPSBean implements Serializable {
private String spice = "parsley, sage, rosemary and thyme";
public UPSBean() { }
public String getSpice() { return spice; }
public void setSpice (String s) { spice = s; }
}
我想看看是否GET /工作的setProperty以上。試圖直接使用JNDI,但是當我使用contextDestroyed()中的資源MyServlet/upsBean設置Spice並嘗試在contextInitialized()中讀取它時,我得到一個null(對不起,我已經刪除了該代碼部分)。現在context.xml中的聲明以及resource-env-ref已經變得多餘。目前的解決方法是將序列化的實例保存在數據文件中(不太好)。
是的,我們希望以編程方式處理這個問題。現在,ServletContext是在部署過程中創建的 - 這是否也意味着Servlet在重新部署時會被銷燬並重新創建?如果是這樣,使用setAttribute()或setInitParameter()保存的任何內容都將被刪除(不會在新的上下文中被讀取)。 – 2011-02-11 18:18:16
是的,但是ServletContextListener接口也有一個方法(contextDestroyed)來監聽上下文的銷燬,並且可以實現將值保存到數據庫或平面文件中,然後偵聽器可以在一旦上下文被重新創建,contextInitialized方法。 ServletContextEvent -object被傳遞到兩個方法中,並且您可以從中訪問實際的ServletContext對象。 – esaj 2011-02-11 18:21:37
是的,這將工作。本質上,您建議將值保存在數據庫或平面文件中,並在下一次調用init()時讀取它。但是,我們正在尋找一種解決方案,可以保留tomcat容器中的值。一種方法是編寫一個全新的Servlet來保存這些值,並使用localhost上的URL按需檢索它們,但這可能是一種矯枉過正。因此,tomcat不能被說服在內存中保存一些字符串以供不同的servlet訪問? – 2011-02-11 18:54:20