【动态JNDI】SpringBoot动态创建JNDI源

背景

一般JNDI源都配置在tomcat之类的web容器里,供各个应用使用,但如何在应用内部动态创建JNDI数据源呢?若能在应用中依赖命名服务,则根据业务处理不同数据源

核心

  • 利用InitialContext上下文的rebind方法绑定命名服务
  • javax.naming.Reference代理使用apache-dhcp2的数据源工厂生成DataSource

Spring Boot项目参考

pom

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.2.1.RELEASE</version>
	<relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>

	<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
	<dependency>
		<groupId>org.apache.commons</groupId>
		<artifactId>commons-dbcp2</artifactId>
		<version>2.7.0</version>
	</dependency>

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>

	<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>6.0.6</version>
	</dependency>

	<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>fastjson</artifactId>
		<version>1.2.72</version>
	</dependency>
</dependencies>

使用示例

public final class JNDILocalTest {
    private static Context ic;
	
    public static void setDataSource() throws NamingException {
        if (ic==null) {
            //Create initial context
            System.setProperty(Context.INITIAL_CONTEXT_FACTORY,"org.apache.naming.java.javaURLContextFactory");
            System.setProperty(Context.URL_PKG_PREFIXES,"org.apache.naming");

            ic = new InitialContext();

            Reference ref = new Reference("javax.sql.DataSource","org.apache.commons.dbcp2.BasicDataSourceFactory", null);
                ref.add(new StringRefAddr("driverClassName", "com.mysql.cj.jdbc.Driver"));
                ref.add(new StringRefAddr("url", "jdbc:mysql://localhost:3306/demo"));
                ref.add(new StringRefAddr("username", "root"));
                ref.add(new StringRefAddr("password", "root"));
                ref.add(new StringRefAddr("maxTotal", "100"));
                ref.add(new StringRefAddr("maxIdle", "10"));
                ref.add(new StringRefAddr("maxWaitMillis", "10000"));

                ic.rebind("demo", ref);
    }

    public static void main(String[] args) throws NamingException {
        setDataSource();
        Connection conn = null;
        Statement stmt = null;
        DataSource dataSource = null;
        ResultSet rs = null;

        try {
            String sql = "SELECT * FROM demo";

            dataSource = (DataSource) new InitialContext().lookup("sc_gateway");
            conn = dataSource.getConnection();
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            final ResultSetMetaData metaData = rs.getMetaData();
           
    }
}

版权声明:本文为u013323965原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。