036.[轉] JNDI 學習

需求: 在spring boot中如何使用 jndihtml

 

(1)JNDI爲什麼而生?java

(2)什麼是JNDI?mysql

(3)在Tomcat中怎麼使用JNDI?程序員

(4)Spring Boot中怎麼使用JNDI web

 https://stackoverflow.com/questions/26504913/spring-boot-with-jndi-data-sourcespring

 

實際應用中,能夠把DataSource註冊到JNDI,也能夠單獨使用DataSource。sql

https://www.cnblogs.com/aisam/articles/4388356.html數據庫

// 初始化數據源實例
DataSource ods = new DataSource(); ods.setDriverType("thin"); ods.setServerName("Chicago"); ods.setNetworkProtocol("tcp"); ods.setDatabaseName("chidb"); ods.setPortNumber(1521); ods.setUser("guest"); ods.setPassword("guest"); // 從數據源中獲取數據庫鏈接
Connection conn = ods.getConnection(); // 經過數據庫鏈接進行數據操做

 

 

1、JNDI爲什麼而生?

1.1 JDBC的天下編程

咱們若是要在程序中鏈接數據庫的話,在沒有JNDI的時候,就是使用JDBC(Java DataBase Connectivity,java數據庫鏈接)了,是否是已經忘得差很少了,一塊兒來回顧下吧,看以下鏈接數據庫代碼tomcat

        Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver", true, Thread.currentThread().getContextClassLoader()); conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb?user=root&password=root"); String sql = "select *from test"; PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery(); while (rs.next()) { System.out.println("id:" + rs.getInt("id") + ",name:" + rs.getString("name") + ""); } conn.close(); } catch (Exception e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { } } }

 

       這是在沒有JNDI的鏈接方式。

 

1.2 存在問題?

       上面的這種方式存在的問題是什麼呢?

(1)數據庫服務器名稱mydb 、用戶名和口令均可能須要改變,由此引起JDBC URL須要修改;

(2)數據庫可能改用別的產品,如改用DB2或者Oracle,引起JDBC驅動程序包和類名須要修改;

(3)隨着實際使用終端的增長,原配置的鏈接池參數可能須要調整;

注意:實際上在使用了Spring等牛逼的框架以後,實際上上面這些問題已經再也不是問題了。

 

1.3 解決方法

程序員應該不須要關心「具體的數據庫後臺是什麼?JDBC驅動程序是什麼?JDBC URL格式是什麼?訪問數據庫的用戶名和口令是什麼?」等等這些問題,程序員編寫的程序應該沒有對 JDBC 驅動程序的引用,沒有服務器名稱,沒有用戶名稱或口令 —— 甚至沒有數據庫池或鏈接管理。而是把這些問題交給J2EE容器來配置和管理,程序員只須要對這些配置和管理進行引用便可。

由此,就有了JNDI。從上面的分析能夠得出,其實是由容器來管理咱們的數據庫鏈接信息了。

 

2、什麼是JNDI?

咱們看下百度百科的描述(https://baike.baidu.com/item/JNDI/3792442):

JNDI(Java Naming and Directory Interface,Java命名和目錄接口)是SUN公司提供的一種標準的Java命名系統接口,JNDI提供統一的客戶端API,經過不一樣的訪問提供者接口JNDI服務供應接口(SPI)的實現,由管理者將JNDI API映射爲特定的命名服務和目錄系統,使得Java應用程序能夠和這些命名服務和目錄服務之間進行交互。

       看完了以後,是否是感受很抽象呢,這裏咱們須要理解這麼幾點:

(1)JNDI是J2EE的規範之一。

(2)JNDI主要有兩部分組成:應用程序編程接口和服務供應商接口。應用程序編程接口提供了Java應用程序訪問各類命名和目錄服務的功能,服務供應商接口提供了任意一種服務的供應商使用的功能。

(3)J2EE 規範要求所有 J2EE 容器都要提供 JNDI 規範的實現。

(4)JNDI 提出的目的是爲了解藕,避免了程序與數據庫之間的緊耦合,使應用更加易於配置、易於部署。

畫外音:JNDI的出現,讓數據庫鏈接代碼交給容器管理,好比Tomcat、JBOSS等容器,這樣對於開發者就不用關心數據庫配置是什麼,使用的什麼數據庫驅動鏈接數據庫等。

 

https://mp.weixin.qq.com/s?__biz=MzA4ODIyMzEwMg==&mid=2447533543&idx=1&sn=7a3aeab6a2fb29c026a420af2a70460d&chksm=843bb9f6b34c30e0ed2da36b25af7a96b08c696b22ed7767e1271ed71707cc129c007253d4a7&scene=21#wechat_redirect

 

3、在Tomcat中如何使用JNDI?

 Tomcat配置JNDI有全局配置和局部配置。大體的有如下三種配置方式:

(1)全局配置:基於context.xml的配置。

(2)局部配置:基於server.xml的配置。

(3)局部配置:基於META-INF 的配置。

 

第一種:全局配置:基於context.xml的配置

1)在tomcat的conf/context.xml配置文件中加入

<?xml version="1.0" encoding="UTF-8"?>
<Context >  
 <Resource name="jdbc/mydb" auth="Container" type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/mydb" username="root" password="root" maxActive="20" maxIdle="10" maxWait="10000"/>
</Context>

 

特別注意:若是是使用了eclipse進行開發測試的話,可能會碰到以下的異常信息:

Cannot create JDBC driver of class '' for connect URL 'null'

      這是因爲context.xml是在開發工具中的servers下的/context.xml,因此須要將配置信息配置servers/Tomcat/context.xml。

 

2)在項目的web.xml中加入資源引用(非必須的):

    <resource-ref>   
        <description>DB Connection</description>   
        <res-ref-name>jdbc/mydb</res-ref-name>   
        <res-type>javax.sql.DataSource</res-type>   
        <res-auth>Container</res-auth>   
    </resource-ref>   

其中res-ref-name值要和context.xml的name值一致。

特別說明:這個配置是無關緊要的,不配置這個的話,也是能夠正常運行的。

 

3)在jsp中調用加載jndi方式:

 Connection conn =null; try{ //初始化查找命名空間 Context ctx = new InitialContext(); //InitialContext ctx = new InitialContext();亦可 //找到DataSource,對名稱進行定位java:comp/env是必須加的,後面跟你的DataSource名 DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/mydb"); //取出鏈接 conn = ds.getConnection(); String sql = "select *from test"; PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery(); while(rs.next()){ System.out.println("id:"+rs.getInt("id")+",name:"+rs.getString("name")+""); } out.println(conn); out.println(conn.isClosed()); out.println("</br>"); System.out.println("connection pool connected !!"); } catch (NamingException e) { System.out.println(e.getMessage()); } catch (SQLException e) { e.printStackTrace(); }finally{ //注意不是關閉,是放回鏈接池. conn.close(); }

特別注意:不能夠直接用main方法測試,必須經過啓動容器從jsp中調用

 

第二種:局部配置:基於server.xml的配置(不推薦使用)

在tomcat的server.xml的<host>標籤內,添加:

   <Context docBase="demo-jndi" path="/demo-jndi">
           <Resource name="jdbc/mydb" auth="Container" type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/mydb" username="root" password="root" maxActive="20" maxIdle="10" maxWait="10000"/>
   </Context>

 

其餘配置同第一種方式。

 

第三種:局部配置:基於META-INFO的配置

在項目的META-INF 下面新建context.xml加入:

<?xml version="1.0" encoding="UTF-8"?>
<Context >  
 <Resource name="jdbc/mydb" auth="Container" type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/mydb" username="root" password="root" maxActive="20" maxIdle="10" maxWait="10000"/>
</Context>

其餘配置同第一種方式。

 

總結:

若是要配置局部的話,推薦使用第三種方式,這樣不依賴tomcat了。可是仍是推薦使用第一種方式好,雖然依賴Tomcat,可是是全局的,並且能夠配置多個。對於之後切換使用方便。另外在項目的web.xml中添加的資源引用無關緊要。

 

https://mp.weixin.qq.com/s?__biz=MzA4ODIyMzEwMg==&mid=2447533547&idx=1&sn=dbc4385eca1ba546fe3bf19f674e4ec3&chksm=843bb9fab34c30ecc62643616e859539bfbcd4d2eb9ba99ae5eee04096bd13d8bbfabcd4bce6&scene=21#wechat_redirect

 

 

4、在SpringBoot中如何使用JNDI?

SpringBoot使用內置的Tomcat

 

https://juejin.im/post/5ca6214f51882543e85f0fd6

一、新增application-dev.properties文件:

# dev環境配置 DataSource.jndiName=jdbc/timcore/DefaultDS DataSource.auth=Container DataSource.driverClassName=org.postgresql.Driver DataSource.url=jdbc:postgresql://30.31.0.14:7523/timc DataSource.username=timcopr DataSource.pwd=123456 DataSource.maxActive=100 DataSource.maxIdle=30 DataSource.maxWait=10000

 

二、建立一個PropConfig類,接收配置

@Getter @Setter @Component @ConfigurationProperties(prefix = "DataSource") public class DataSourcePropConfig { private String jndiName; private String auth; private String driverClassName; private String url; private String username; private String pwd; private String maxActive; private String maxIdle; private String maxWait; }

 

三、JavaConfig 方式修改配置,加入數據源

@Configuration public class MyWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter { @Resource private DataSourcePropConfig dataSourcePropConfig; // dev 環境數據源。
    @ConditionalOnProperty(name = "spring.profiles.active", havingValue = "dev") @Bean public TomcatEmbeddedServletContainerFactory servletContainerFactory() { return new TomcatEmbeddedServletContainerFactory() { @Override protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) { tomcat.enableNaming(); // 打開JNDI數據源
                return super.getTomcatEmbeddedServletContainer(tomcat); } @Override protected void postProcessContext(Context context) { ContextResource resource = new ContextResource(); resource.setType(DataSource.class.getName());
          // jndi name resource.setName(dataSourcePropConfig.getJndiName()); resource.setAuth(dataSourcePropConfig.getAuth()); resource.setProperty(
"driverClassName", dataSourcePropConfig.getDriverClassName()); resource.setProperty("url", dataSourcePropConfig.getUrl()); resource.setProperty("username", dataSourcePropConfig.getUsername()); resource.setProperty("password", dataSourcePropConfig.getPwd()); // 鏈接池配置,和測試、生產配置一致。 resource.setProperty("maxActive", dataSourcePropConfig.getMaxActive()); // 最大鏈接數 resource.setProperty("maxIdle", dataSourcePropConfig.getMaxIdle()); // 空閒鏈接數 resource.setProperty("maxWait", dataSourcePropConfig.getMaxWait()); // 最大等待時間 context.getNamingResources().addResource(resource); } }; } }

 

四、SpringBoot使用JNDI數據源

application.properties文件中配置

spring.datasource.jndi-name=java:comp/env/jdbc/timcore/DefaultDS

 

? 如何配置 SqlSessionFactory 與 DataSource 關聯

https://blog.csdn.net/bjl3738/article/details/86295024

https://blog.csdn.net/muyiyangyang/article/details/80807256

相關文章
相關標籤/搜索