在Tomcat上查找java:comp/env之外的JNDI名称



我正在使用一个最初为 IBM WebSphere 设计的应用程序,但我也想在 Tomcat 上托管它。应用程序无法更改,并且正在执行 new InitialContext().lookup("servername") ,这在 WebSphere 上工作。

但是在 Tomcat 上,当我在应用程序特定的上下文 xml 中指定<Environment>名称时,它们以 java:comp/env 为前缀,并且上述查找找不到这些名称。

它将在容器中运行,因此如果有必要,更新server.xml没有问题,当然还有特定于应用程序的上下文 xml。

如何让雄猫在lookup("servername")上返回字符串?

看起来 Tomcat 是硬编码的,可以以这种方式运行。

但它不必保持这种状态。加入Tomcat用户的邮件列表,询问事情之所以如此,是否有特殊原因。如果没有特定原因将环境条目限制为 java:comp/env 命名空间,那么我怀疑代码更改(可能涉及新的配置选项(绝对是可能的。

作为一个黑客,我创建了这个InitialContextFactory,它只是将字符串名称的查找委托给System.getenv()(环境变量(。这是非常不安全的,并且会破坏正确使用命名的应用程序,因此我不建议将其用于生产或特定用例之外。或者真的对任何一个

尽管如此,通过使用它,我能够让(String) new InitialContext().lookup("servername")通过命令行set servername=blah返回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/中创建(:

set CLASSPATH=C:pathtocompiledclass
set CATALINA_OPTS=-Djava.naming.factory.initial=EnvironmentInitialContextFactory

我正在重新审视这个(我是提问者(。受到这个答案的启发,我决定改为实现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/ 命名空间中的所有名称,以创建更通用的侦听器。目前,我只是绑定单个名称,因为该应用程序使用的单个名称很少。

最新更新