我正在使用最初为IBM WebSphere设计的应用程序,但我也希望将其托管在Tomcat上。该应用程序无法更改,并且正在运行new InitialContext().lookup("servername")
,可在WebSphere上运行。
但是在Tomcat上,当我在应用程序特定的上下文xml中指定<Environment>
名称时,它们以java:comp/env
为前缀,而上述查找找不到这些名称。
它将在容器中运行,因此,如果有必要,当然还有应用程序特定的上下文xml,则更新server.xml
没问题。
如何让Tomcat在lookup("servername")
上返回字符串?
答案 0 :(得分:0)
看起来Tomcat进行了硬编码,以这种方式工作。
但是不必那样做。加入Tomcat user's mailing list并询问是否有某种特定的原因来说明事物的现状。如果没有特殊原因将环境条目限制为java:comp/env
名称空间,那么我怀疑可以进行代码更改(可能涉及新的配置选项)。
答案 1 :(得分:0)
作为一个hack,我创建了这个InitialContextFactory,它只是将对字符串名称的查找委托给System.getenv()
(环境变量)。这是非常不安全的,会破坏正确使用命名的应用程序,因此我不建议在生产环境或特定用例之外使用此功能。或真的给任何人。
尽管如此,通过使用此命令,我能够在命令行上通过(String) new InitialContext().lookup("servername")
返回blah
来返回特定值set servername=blah
。
import java.util.Hashtable;
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NameClassPair;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactory;
public class EnvironmentInitialContextFactory implements InitialContextFactory {
public Context getInitialContext(Hashtable<?,?> environment) throws NamingException {
return new Context() {
public Object lookup(String name) throws NamingException {
return System.getenv(name);
}
public Object lookup(Name name) throws NamingException { return null; }
public void bind(Name name, Object obj) throws NamingException {}
public void bind(String name, Object obj) throws NamingException {}
public void rebind(Name name, Object obj) throws NamingException {}
public void rebind(String name, Object obj) throws NamingException {}
public void unbind(Name name) throws NamingException {}
public void unbind(String name) throws NamingException {}
public void rename(Name oldName, Name newName) throws NamingException {}
public void rename(String oldName, String newName) throws NamingException {}
public NamingEnumeration<NameClassPair> list(Name name) throws NamingException { return null; }
public NamingEnumeration<NameClassPair> list(String name) throws NamingException { return null; }
public NamingEnumeration<Binding> listBindings(Name name) throws NamingException { return null; }
public NamingEnumeration<Binding> listBindings(String name) throws NamingException { return null; }
public void destroySubcontext(Name name) throws NamingException {}
public void destroySubcontext(String name) throws NamingException {}
public Context createSubcontext(Name name) throws NamingException { return null; }
public Context createSubcontext(String name) throws NamingException { return null; }
public Object lookupLink(Name name) throws NamingException { return null; }
public Object lookupLink(String name) throws NamingException { return null; }
public NameParser getNameParser(Name name) throws NamingException { return null; }
public NameParser getNameParser(String name) throws NamingException { return null; }
public Name composeName(Name name, Name prefix) throws NamingException { return null; }
public String composeName(String name, String prefix) throws NamingException { return null; }
public Object addToEnvironment(String propName, Object propVal) throws NamingException { return null; }
public Object removeFromEnvironment(String propName) throws NamingException { return null; }
public Hashtable<?, ?> getEnvironment() throws NamingException { return null; }
public void close() throws NamingException {}
public String getNameInNamespace() throws NamingException { return null; }
};
}
}
编译类,并通过将以下行添加到setenv.bat
(在%CATALINA_HOME%/bin/
中创建)将其添加到CLASSPATH和系统属性中:
set CLASSPATH=C:\path\to\compiled\class
set CATALINA_OPTS=-Djava.naming.factory.initial=EnvironmentInitialContextFactory
答案 2 :(得分:0)
我正在重新研究这个问题(我是问问者)。受this answer的启发,我决定改为实施ServletContextListener
。
总而言之,您不能使Tomcat将环境资源放在java:comp/env/
之外,但是您可以从那里读取它们并在“任何地方”重新分配它们。
初始化ServletContext时,我的侦听器将它们重新绑定:
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
Context ctx = new InitialContext();
ctx.bind("servername", ctx.lookup("java:comp/env/servername"));
}
这是一个更好的解决方案-它不会摆弄部署上下文之外的任何内容。
也有可能只是重新绑定comp/env/
名称空间中的所有名称,以创建更通用的侦听器。目前,我只是绑定单个名称,因为该应用程序使用的名称很少。