Java 如何在Tomcat环境中保存名称-值对?
我们有一个servlet,它需要某些变量,如密码、加密盐等,而不是永久保存在文件系统上。这就是我们目前所做的(总结): 在初始化期间Java 如何在Tomcat环境中保存名称-值对?,java,tomcat,servlets,Java,Tomcat,Servlets,我们有一个servlet,它需要某些变量,如密码、加密盐等,而不是永久保存在文件系统上。这就是我们目前所做的(总结): 在初始化期间 Perl脚本将ReadMode设置为2以屏蔽标准输出echo,提示用户输入变量,过滤已知文件以将其放入,并调用tomcat/bin/startup.sh servlet init()方法从文件中读取变量并将其删除(文件) 问题: 重新编译WAR时,tomcat会尝试部署它(autodeploy=true),这是我们想要的。但是数据文件不再存在,因此会抛出FileN
问:是否有一个属性或一些HashMap/表可供servlet使用,在手动启动期间可以存储一些变量?其思想是,如果在重新部署期间数据文件不存在,init()可以检查它们。谢谢,-女士。如果您想以编程方式处理它,我想您可能需要的是一个。创建一个实现接口的类,并在contextInitialized(ServletContextEvent sce)-方法中编写所需的功能,请参见简单示例。将易失性数据放入JNDI。JNDI在重新部署之间没有得到清理。您的servlet仍然可以在
init
期间执行相同的操作,以确保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; }
}
==========
restart.pl:
==========
阅读模式2;打印“\n输入香料:”;chomp($spice=);打印“\n”;
读取模式0;
打开(FP,“>$spicefile”)或关闭“$0:无法写入文件$spicefile:$!\n”;
打印FP“$spice\n”;关闭(FP);
系统“bin/shutdown.sh”;睡眠8;
系统“bin/startup.sh”;睡眠8;系统“wget$tomcaturl”;
系统“/bin/rm-rf*spicefile*”;#删除wget输出文件
每个$scont(1..10){#再给它10秒
睡眠1;
如果(-f$s文件){
打印“$0:正在等待servlet删除文件[$Scont]\n”
}否则{
打印“$0:servlet初始化成功,没有文件\n”;
出口0
}}
打印“\n$0:删除文件$spicefile…\n”#错误条件
系统“取消链接$spicefile”;
出口1;
===========
context.xml
===========
===================
app/WEB-INF/WEB.xml
===================
packageName.DBInterface
在重新部署期间,使用spice作为可转移工具
MyServlet/upsBean
包装名称
==============
MyServlet.java:
==============
init(){
if(新文件(spiceFile.exists())#在restart.pl中同名
dbi=新的dbi接口(文件);
其他的
dbi=新的DBInterface();#重新部署
其他初始化(dbi.getSpice());
}
================
DBInterface.java:
================
公共数据库接口(){
//如果contextInitialized有效,请注释掉下面的块
FileInputStream fin=新的FileInputStream(SafeDepositorBox);
ObjectInputStream ois=新ObjectInputStream(fin);
UPSBean UPSBean=(UPSBean)ois.readObject();
ois.close();
spice=upsBean.getSpice();
dbiIndex=2;
//用香料做东西
}
公共数据库接口(字符串文件名){
文件文件=新文件(文件名);
BufferedReader br=新的BufferedReader(新文件读取器(文件));
spice=br.readLine();
br.close();
delete();
dbiIndex=1;
//如果contextInitialized工作,请删除以下块
UPSBean UPSBean=新的UPSBean();
upsBean.setSpice(香料);
FileOutputStream fout=新的FileOutputStream(安全存储框);
ObjectOutputStream oos=新的ObjectOutputStream(fout);
oos.writeObject(upsBean);
oos.flush();
oos.close();
//用香料做一些东西,如果有用的话。。。
//contextInitialized(null);
}
//以上是目前正在工作,希望以下工作
公共无效上下文已销毁(ServletContextEvent sce){
System.setProperty(“spice”,spice);
System.out.println(“[DBInterface”+dbiIndex+
“]香料保存在”+
DateFormat.getDateTimeInstance(DateFormat.SHORT,
格式(new Date());
}
public void contextInitialized(ServletContextEvent sce){
如果(sce!=null){
spice=System.getProperty(“spice”);
System.out.println(“[DBInterface”+dbiIndex+
“]在检索到香料”+
DateFormat.getDateTimeInstance(DateFormat.SHORT,
格式(new Date());
}
//用香料做东西
}
============
UPSBean.java:
============
公共类UPSBean实现了可序列化{
私人串香料=“欧芹、鼠尾草、迷迭香和百里香”;
公共UPSBean(){}
公共字符串getSpice(){return spice;}
公共void setSpice(字符串s){spice=s;}
}
我正在尝试查看上面的get/setProperty是否有效。我试图直接使用JNDI,但是当我在contextDestroyed()中使用资源MyServlet/upsBean设置pice并尝试在contextInitialized()中读取它时,我得到一个null(对不起,我已经删除了代码的这一部分)。现在context.xml和resource env ref中的声明变得多余。当前的解决方法是将序列化实例保存在数据文件中(不是很好)。在调用startup.sh(即“bin/startup.sh-DencryptionSalt=foobar”)时,如何将它们作为系统属性传入?然后,您可以调用System.getProperty(“EncryptionAlt”),在