zoukankan      html  css  js  c++  java
  • 036.[转] JNDI 学习

    使用外置服务器(如tomcat)时,如果一个服务器启动多个项目,可以使用JNDI配置数据源,这样每个项目都可以获取到Tomcat 配置的 JNDI的数据源。

    在学习 jsp 的时候,作用域对象

    pageContext < request < session <  application(ServletContext) ;  最多能从当前servlet容器获取到参数值

    在Tomcat配置JNDI数据源的三种方式

    https://blog.csdn.net/dyllove98/article/details/7706218

    (1)JNDI为何而生?

    (2)什么是JNDI?

    (3)在Tomcat中怎么使用JNDI?

    (4)Spring Boot中怎么使用JNDI 

    一、JNDI为何而生?

    1.1 JDBC的天下

    我们如果要在程序中连接数据库的话,在没有JNDI的时候,就是使用JDBC(Java DataBase Connectivity,java数据库连接)了,是不是已经忘得差不多了,一起来回顾下吧,看如下连接数据库代码

            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。从上面的分析可以得出,实际上是由容器来管理我们的数据库连接信息了。

    二、什么是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

    三、在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

    四、在SpringBoot中如何使用JNDI?

    SpringBoot使用内置的Tomcat

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

    1、新增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

    2、创建一个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;
    }

    3、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); } }; } }

    4、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

  • 相关阅读:
    android的布局xml文件如何添加注释?
    安卓xml布局中 android:paddingBottom="@dimen/activity_vertical_margin"是什么意思?
    Failure [INSTALL_FAILED_OLDER_SDK]
    安装并使用PICT,生成测试用例
    安装并使用Junit
    SourceMonitor的安装
    FindBugs
    pdm的说明
    Checkstyle的安装与使用
    白话决策树
  • 原文地址:https://www.cnblogs.com/badboyh2o/p/11258186.html
Copyright © 2011-2022 走看看