独立 Java 程序中的初始上下文

2022-09-01 20:36:53

我正在使用JNDI来创建连接池。它在Web应用程序中效果很好。我相信InitialContext是由tomcat服务器提供的。

Context initContext  = new InitialContext();
Context envContext  = (Context)initContext.lookup("java:/comp/env");
dataSource = (DataSource)envContext.lookup("jdbc/testdb");

但是当我尝试从独立的Java程序调用相同的实用程序时,initContext对象为空。如何显式提供上下文对象所期望的所有必要属性。

错误:javax.nameing.NoInitialContextException:需要在环境或系统属性中指定类名,或者作为小程序参数,或者在应用程序资源文件中指定:java.name.factory.initial


答案 1

下面是一个根据已接受的答案改编的示例,但要以内联方式执行所有操作以避免创建额外的类。

public static void main(String[] args) {
    setupInitialContext();
    //do something that looks up a datasource
}

private static void setupInitialContext() {
    try {
        NamingManager.setInitialContextFactoryBuilder(new InitialContextFactoryBuilder() {

            @Override
            public InitialContextFactory createInitialContextFactory(Hashtable<?, ?> environment) throws NamingException {
                return new InitialContextFactory() {

                    @Override
                    public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
                        return new InitialContext(){

                            private Hashtable<String, DataSource> dataSources = new Hashtable<>();

                            @Override
                            public Object lookup(String name) throws NamingException {

                                if (dataSources.isEmpty()) { //init datasources
                                    MysqlConnectionPoolDataSource ds = new MysqlConnectionPoolDataSource();
                                    ds.setURL("jdbc:mysql://localhost:3306/mydb");
                                    ds.setUser("mydbuser");
                                    ds.setPassword("mydbpass");
                                    dataSources.put("jdbc/mydbname", ds);

                                    //add more datasources to the list as necessary
                                }

                                if (dataSources.containsKey(name)) {
                                    return dataSources.get(name);
                                }

                                throw new NamingException("Unable to find datasource: "+name);
                            }
                        };
                    }

                };
            }

        });
    }
    catch (NamingException ne) {
        ne.printStackTrace();
    }
}

答案 2

您还可以创建自己的自定义上下文。

LocalContext ctx = LocalContextFactory.createLocalContext();
ctx.addDataSource("jdbc/testdb", driverName, url, usr, pwd);

有关更多详细信息,请参阅在本地运行使用应用程序服务器数据源的 Bean


new更新

你可以使用类 org.springframework.mock.jndi.SimpleNamingContextBuilder of Spring。例如:

  • 设置:

    SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
    builder.bind("jdbc/Oracle", ods);
    builder.activate();
    
  • 用:

    DataSource ds = InitialContext.doLookup("jdbc/Oracle");
    

推荐