乐趣区

Java-J2EE中的依赖查找

个人看法: 设计依赖查找的设计模式, 是为了解耦.

  • 单一类型依赖查找

    • JNDI javax.naming.Context#lookup
    • JavaBeans java.beans.beancontext.BeanContext
  • 集合类型依赖查找

    • java.beans.beancontext.BeanContext#getCurrentServiceSelectors
  • 层析性依赖查找

Springboot 中使用 JNDI

JNDI 即 Java Naming and Directory Interface(JAVA 命名和目录接口),那么 java 命名目的就是为了记录一些不方便记录的内容,就像人的名字或 DNS 中的域名与 IP 的关系。

两种模式
  1. Springboot Embedded Tomcat(嵌入 Tomcat) 使用 JNDI
  2. Springboot WAR 使用 JNDI

1. Springboot Embedded Tomcat(嵌入 Tomcat) 使用 JNDI

  • 启用默认禁用的 JNDI 命名。
  • 构建一个 ContextResource 对象,然后添加到 Context 对象中

java:/comp/env/ 固定写法

JndiConfig.java

package com.rumenz;

import org.apache.catalina.Context;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.util.descriptor.web.ContextResource;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.jndi.JndiObjectFactoryBean;
import org.springframework.stereotype.Component;
import javax.naming.NamingException;
import javax.sql.DataSource;
@Component
public class JndiConfig {

    @Bean
    public ServletWebServerFactory servletContainer() {TomcatServletWebServerFactory tomcatServletWebServerFactory = new TomcatServletWebServerFactory() {
            @Override
            protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {tomcat.enableNaming(); // 启用默认禁用的 JNDI 命名
                return super.getTomcatWebServer(tomcat);

            }
            // 数据库配置信息可以配置在文件中, 数据库发生变动, 只需修改配置文件, 而不用修改代码.
            @Override
            protected void postProcessContext(Context context) {ContextResource resource = new ContextResource();
                resource.setName("jdbcMydb");
                resource.setType(DataSource.class.getName());
                resource.setProperty("driverClassName", "com.mysql.jdbc.Driver");
                resource.setProperty("url", "jdbc:mysql://127.0.0.1:3306/test");
                resource.setProperty("username", "root");
                resource.setProperty("password","root1234");
                context.getNamingResources().addResource(resource);
            }
        };
        return tomcatServletWebServerFactory;
    }
    @Bean
    public DataSource jndiDataSource() throws IllegalArgumentException,
            NamingException {JndiObjectFactoryBean bean = new JndiObjectFactoryBean();           // create JNDI data source
        bean.setJndiName("java:/comp/env/jdbcMydb");  // jndiDataSource is name of JNDI data source
        bean.setProxyInterface(DataSource.class);
        bean.setLookupOnStartup(true);
        bean.afterPropertiesSet();
        return (DataSource) bean.getObject();}

}

MysqlTest.java

package com.rumenz;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

@Component
public class MysqlTest implements ApplicationRunner {
    public static DataSource dataSource = null;

   static {
       Context context = null;
       try {context = new InitialContext();
       } catch (NamingException e) {e.printStackTrace();
       }
       // 根据资源名称搜索
       try {dataSource = (DataSource)context.lookup("java:/comp/env/jdbcMydb");
       } catch (NamingException e) {e.printStackTrace();
       }
       System.out.println("static-----");
   }

    public void run(ApplicationArguments args) throws Exception {System.out.println("run---------");
        Statement stmt = null;
        try {Connection conn = dataSource.getConnection();
            // 查询
            stmt = conn.createStatement();
            String sql = "SELECT id,name FROM qq limit 1";
            ResultSet rs = stmt.executeQuery(sql);
            while(rs.next()){int id  = rs.getInt("id");
                String name = rs.getString("name");
                System.out.print("id:" + id);
                System.out.println(", name:" + name);
            }
            rs.close();
            stmt.close();
            conn.close();} catch (Exception e) {e.printStackTrace();
        }
    }
}

源码:https://github.com/mifunc/spr…

2.Springboot WAR 使用 JNDI

打包成 war 包放到 tomcat, 需要修改 tomcat/conf/context.xml 和 tomcat/conf/server.xml

tomcat/conf/context.xml

<ResourceLink name="jdbcMydb"
                global="jdbcMydb"
                auth="Container"
                type="javax.sql.DataSource" />

tomcat/conf/server.xml

<Resource name="jdbcMydb"
          global="jdbcMydb"
          auth="Container" 
          type="javax.sql.DataSource" 
          driverClassName="com.mysql.jdbc.Driver" 
          url="jdbc:mysql://localhost:3306/test"
          username="root"
          password="root1234"
          maxActive="100" 
          maxIdle="20" 
          minIdle="5" 
          maxWait="10000"/>

业务代码

JNDIController.java

package com.rumenz.controller;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class JNDIController {
    @Autowired
    private DataSource dataSource;
    
    @GetMapping("/test")
    public String test() {
        try {Connection conn = dataSource.getConnection();
            Statement stmt = conn.createStatement();
            String sql = "SELECT id,name FROM qq limit 1";
            ResultSet rs = stmt.executeQuery(sql);
            while(rs.next()){int id  = rs.getInt("id");
                String name = rs.getString("name");
                System.out.print("id:" + id);
                System.out.println(", name:" + name);
            }
            rs.close();
            stmt.close();
            conn.close();} catch (SQLException e) {e.printStackTrace();
        }
        return null;
    }

}

源码:https://github.com/mifunc/Spr…

java.beans.beancontext.BeanContext(单一类型依赖查找 / 集合类型依赖查找)

  • 单一类型依赖查找

    • java.beans.beancontext.BeanContextServicesSupport#getService
  • 集合类型依赖查找

    • java.beans.beancontext.BeanContextServicesSupport#getCurrentServiceSelectors

层析性依赖查找

多个 BeanContext 相互为父子关系. 一个 service 的依赖有可能在多个 BeanContext

退出移动版