- 浏览: 21905 次
- 性别:
- 来自: 深圳
-
文章分类
最新评论
转发 http://yunqiang-zhang-hotmail-com.iteye.com/blog/1616951
JNDI全面总结 (tomact中配置连接池)
JNDI全面总结
原理:
在DataSource中事先建立多个数据库连接,保存在数据库连接池中。当程序访问数据库时,只用从连接池中取空闲状态的数据库连接即可,访问结束,销毁资源,数据库连接重新回到连接池,这与每次去直接访问数据库相比,会节省大量时间和资源。
JNDI( Java Naming and Directory Interface ),是Java平台的一个标准扩展,提供了一组接口、类和关于命名空间的概念。如同其它很多Java技术一样,JDNI是provider-based的技术,暴露了一个 API和一个服务供应接口(SPI)。这意味着任何基于名字的技术都能通过JNDI而提供服务,只要JNDI支持这项技术。JNDI目前所支持的技术包括 LDAP、CORBA Common Object Service(COS)名字服务、RMI、NDS、DNS、Windows注册表等等。很多J2EE技术,包括EJB都依靠JNDI来组织和定位实体。可以把它理解为一种将对象和名字捆绑的技术,对象工厂负责生产出对象,这些对象都和唯一的名字绑在一起,外部资源可以通过名字获得某对象的引用。
在javax.naming的包包中提供Context接口,提供了两个很好用的方法:
<1> void bind( String name , Object object )
将名称绑定到对象。所有中间上下文和目标上下文(由该名称最终原子组件以外的其他所有组件指定)都必须已经存在。
<2>Object lookup( String name )
检索指定的对象。如果 name为空,则返回此上下文的一个新实例(该实例表示与此上下文相同的命名上下文,但其环境可以独立地进行修改,而且可以并发访问)。
运行机制:
1、 首先程序代码获取初始化的 JNDI 环境并且调用 Context.lookup() 方法从 JNDI 服务提供者那里获一个 DataSource 对象
2、 中间层 JNDI 服务提供者返回一个 DataSource 对象给当前的 Java 应用程序这个 DataSource 对象代表了中间层服务上现存的缓冲数据源
3、 应用程序调用 DataSource 对象的 getConnection() 方法
4、 当 DataSource 对象的 getConnection() 方法被调用时,中间层服务器将查询数据库 连接缓冲池中有没有 PooledConnection 接口的实例对象。这个 PooledConnection 对象将被用于与数据库建立物理上的数据库连接
5、 如果在缓冲池中命中了一个 PooledCoonection 对象那么连接缓冲池将简单地更 新内部的缓冲连接队列并将该 PooledConnection 对象返回。如果在缓冲池内没 有找到现成的 PooledConnection 对象,那么 ConnectionPoolDataSource 接口将会被 用来产生一个新的 PooledConnection 对象并将它返回以便应用程序使用
6。 中间层服务器调用 PooledConnection 对象的 getConnection() 方法以便返还一个 java.sql.Connection 对象给当前的 Java 应用程序
7、 当中间层服务器调用 PooledConnection 对象的 getConnection() 方法时, JDBC 数据 库驱动程序将会创建一个 Connection 对象并且把它返回中间层服务器
8、 中间层服务器将 Connection 对象返回给应用程序 Java 应用程序,可以认为这个 Connection 对象是一个普通的 JDBC Connection 对象使用它可以和数据库建立。事 实上的连接与数据库引擎产生交互操作 。
9、 当应用程序不需要使用 Connection 对象时,可以调用 Connection 接口的 close() 方 法。请注意这种情况下 close() 方法并没有关闭事实上的数据库连接,仅仅是释 放了被应用程序占用的数据库连接,并将它还给数据库连接缓冲池,数据库连接 缓冲池会自动将这个数据库连接交给请求队列中下一个的应用程序使用。
现在,数据库的连接没有用到连接池几乎很少很少,每个项目组都可能有自己的数据库连接池组件,各容器提供商也提供了各自的数据库连接池,下面介绍一下tomcat的数据库连接管理。
tomcat6 数据源配置(server.xml方式和context.xml方式)
在server.xml下配置你必需重启服务器才能生效,而context.xml配置保存后tomcat会自动加载无需重启
在JNDI配配置数据源中需注意:项目下需要引入数据库驱动包,并且TOMCAT下也需要引入,不然会报错的
1.context.xml方式
Tomcat-6.0.26\conf\context.xml文件当添加以下的配置信息:
<Resource name="jdbc/mysql" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="60" wait_timeout="18800" timeBetweenEvictionRunsMillis="300000" minEvictableIdleTimeMillis="600000"
username="root" password="jdzxdb" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/sxtele?comautoReconnect=true&failOverReadOnly=false" removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true"/>
<Resource name="jdbc/db2" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="60" wait_timeout="18800" timeBetweenEvictionRunsMillis="300000" minEvictableIdleTimeMillis="600000"
username="lcgluser" password="lcgluser" driverClassName="com.ibm.db2.jcc.DB2Driver"
url="jdbc:db2://133.64.46.65:50000/STEDWDB" removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true"/>
其中:
name 表示指定的jndi名称
auth 表示认证方式,一般为Container
type 表示数据源床型,使用标准的javax.sql.DataSource
maxActive 表示连接池当中最大的数据库连接
maxIdle 表示最大的空闲连接数
maxWait 当池的数据库连接已经被占用的时候,最大等待时间
logAbandoned 表示被丢弃的数据库连接是否做记录,以便跟踪
username 表示数据库用户名
password 表示数据库用户的密码
driverClassName 表示JDBC DRIVER
url 表示数据库URL地址
注意,这里你配置的name值要和程序中使用的是一样的,比如按照这个例子,程序就应该是这样的
Java代码
String gENV = "java:comp/env/";
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx .lookup(gENV+"jdbc/mysql");
Connection conn = ds.getConnection();
String gENV = "java:comp/env/";
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup(gENV+"jdbc/db2");
Connection conn = ds.getConnection();
2.在server.xml文件中配置数据源
Tomcat-6.0.26\conf\context.xml中的配置:在<Host></Host>中添加如下配置
<Context path="/sljx" reloadable="true" docBase="sljx" crossContext="true"
debug="0">
<Resource
name="jdbc/oracle"
type="javax.sql.DataSource"
auth="Container"
username="sljx"
password="sljx"
driverClassName="oracle.jdbc.driver.OracleDriver"
maxIdle="3000"
maxWait="5000"
url="jdbc:oracle:thin:@localhost:1521:jadetrus"
autoReconnect="true"
maxActive="1000"/>
</Context>
具体属性解释和JAVA获取数据源跟上面一样
3.在hibernate中配置JNDI也很简单在hibernate.cfg.xml中
<property name="connection.datasource">java:/comp/env/jdbc/mysql</property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
常用获取示例
package com.cn.util.db;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class DBCache {
private InitialContext ic;
private Map<String,DataSource> cache;
private static DBCache instance = new DBCache();
private DBCache() {
try {
ic = new InitialContext();
} catch (NamingException e) {
e.printStackTrace();
}
cache = Collections.synchronizedMap(new HashMap<String,DataSource>());
}
public static DBCache getInstance() {
return instance;
}
public Connection getDBConn(String dataSourceName) throws SQLException,
NamingException {
Connection conn = null;
conn=getDataSource(dataSourceName).getConnection();
return conn;
}
public DataSource getDataSource(String dataSourceName)
throws NamingException {
if (cache.containsKey(dataSourceName)) {
return cache.get(dataSourceName);
} else {
DataSource newDataSource = (DataSource) ic.lookup(dataSourceName);
cache.put(dataSourceName, newDataSource);
return newDataSource;
}
}
public void removeDateSouceOffCache(String dataSourceName) {
try {
DataSource ds = cache.get(dataSourceName);
ds.getConnection().close();
cache.remove(dataSourceName);
} catch (Exception ex) {
}
}
public static void freeConn(Connection conn) {
freeConn(conn, null, null);
}
public static void freeConn(Connection connection, Statement statement) {
freeConn(connection, statement, null);
}
public static void freeConn(Connection conn, Statement ps, ResultSet rs) {
try {
try {
if (rs != null)
rs.close();
} finally {
try {
if (ps != null)
ps.close();
} finally {
if (conn != null)
conn.close();
}
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
如果获取连接调用getDBConn传入下面两值中任意一个即可
public static final String DATA_SOURCE = "java:comp/env/jdbc/localhostMysql";
public static final String DATA_SOURCE_DB2 = "java:comp/env/jdbc/db2";
private static final String DATA_SOURCE="java:comp/env/jdbc/oracle";
关于JNDI的更多用法
基于JNDI的应用开发
JNDI(The Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API.命名服务将名称和对象联系起来,使得我们可以用名称访问对象。目录服务是一种命名服务,在这种服务里,对象不但有名称,还有属性。
命名或目录服务使你可以集中存储共有信息,这一点在网络应用中是重要的,因为这使得这样的应用更协调、更容易管理。例如,可以将打印机设置存储在目录服务中,以便被与打印机有关的应用使用。
JNDI概述
我们大家每天都不知不觉地使用了命名服务。例如,当你在web浏览器输入URL,http://java.sun.com时,DNS(Domain Name System,域名系统)将这个符号URL名转换成通讯标识(IP地址)。命名系统中的对象可以是DNS记录中的名称、应用服务器中的EJB组件(Enterprise JavaBeans Component)、LDAP(Lightweight Directory Access Protocol)中的用户Profile.
目录服务是命名服务的自然扩展。两者之间的关键差别是目录服务中对象可以有属性(例如,用户有email地址),而命名服务中对象没有属性。因此,在目录服务中,你可以根据属性搜索对象。JNDI允许你访问文件系统中的文件,定位远程RMI注册的对象,访问象LDAP这样的目录服务,定位网络上的EJB组件。
对于象LDAP 客户端、应用launcher、类浏览器、网络管理实用程序,甚至地址薄这样的应用来说,JNDI是一个很好的选择。
JNDI架构
JNDI架构提供了一组标准的独立于命名系统的API,这些API构建在与命名系统有关的驱动之上。这一层有助于将应用与实际数据源分离,因此不管应用访问的是LDAP、RMI、DNS、还是其他的目录服务。换句话说,JNDI独立于目录服务的具体实现,只要你有目录的服务提供接口(或驱动),你就可以使用目录。如图1所示。 图1:JNDI架构
关于JNDI要注意的重要一点是,它提供了应用编程接口(application programming interface,API)和服务提供者接口(service provider interface,SPI)。这一点的真正含义是,要让你的应用与命名服务或目录服务交互,必须有这个服务的JNDI服务提供者,这正是JNDI SPI发挥作用的地方。服务提供者基本上是一组类,这些类为各种具体的命名和目录服务实现了JNDI接口?很象JDBC驱动为各种具体的数据库系统实现了JDBC接口一样。作为一个应用开发者,你不必操心JNDI SPI.你只需要确认你要使用的每一个命名或目录服务都有服务提供者。
J2SE和JNDI
Java 2 SDK 1.3及以上的版本包含了JNDI.对于JDK 1.1和1.2也有一个标准的扩展。Java 2 SDK 1.4.x的最新版本包括了几个增强和下面的命名/目录服务提供者:
l LDAP(Lightweight Directory Access Protocol)服务提供者 l CORBA COS(Common Object Request Broker Architecture Common Object Services)命名服务提供者 l RMI(Java Remote Method Invocation)注册服务提供者 l DNS(Domain Name System)服务提供者
更多的服务提供者
可以在如下网址找到可以下载的服务提供者列表:
http://java.sun.com/products/jndi/serviceproviders.html 特别有意思的或许是如下网址提供的Windows 注册表JNDI服务提供者:http://cogentlogic.com/cocoon/CogentLogicCorporation/JNDI.xml 这个服务提供者使你可以访问Windows XP/2000/NT/Me/9x的windows注册表。
也可以在如下网址下载JNDI/LDAP Booster Pack:http://java.sun.com/products/jndi/ 这个Booster Pack包含了对流行的LDAP控制的支持和扩展。它代替了与LDAP 1.2.1服务提供者捆绑在一起的booster pack.关于控制和扩展的更多信息可以在如下网站看到: http://java.sun.com/products/jndi/tutorial/ldap/ext/index.html 另一个有趣的服务提供者是Sun的支持DSML v2.0(Directory Service Markup Language,目录服务标记语言)的服务提供者。DSML的目的是在目录服务和XML之间架起一座桥梁。
JNDI API
JNDI API由5个包组成:
l Javax.naming:包含了访问命名服务的类和接口。例如,它定义了Context接口,这是命名服务执行查询的入口。 l Javax.naming.directory:对命名包的扩充,提供了访问目录服务的类和接口。例如,它为属性增加了新的类,提供了表示目录上下文的DirContext接口,定义了检查和更新目录对象的属性的方法。 l Javax.naming.event:提供了对访问命名和目录服务时的时间通知的支持。例如,定义了NamingEvent类,这个类用来表示命名/目录服务产生的事件,定义了侦听NamingEvents的NamingListener接口。 l Javax.naming.ldap:这个包提供了对LDAP 版本3扩充的操作和控制的支持,通用包javax.naming.directory没有包含这些操作和控制。 l Javax.naming.spi:这个包提供了一个方法,通过javax.naming和有关包动态增加对访问命名和目录服务的支持。这个包是为有兴趣创建服务提供者的开发者提供的。
JNDI 上下文
正如在前面提到的,命名服务将名称和对象联系起来。这种联系称之为绑定(binding)。一组这样的绑定称之为上下文(context),上下文提供了解析(即返回对象的查找操作)。其他操作包括:名称的绑定和取消绑定,列出绑定的名称。注意到一个上下文对象的名称可以绑定到有同样的命名约定的另一个上下文对象。这称之为子上下文。例如,如果UNIX中目录/home是一个上下文,那么相对于这个目录的子目录就是子上下文?例如,/home/guests中guests就是home的子上下文。在JNDI中,上下文用接口javax.naming.Context表示,这个接口是与命名服务交互的关键接口。在Context(或稍后讨论的DirContext)接口中的每一个命名方法都有两种重载形式:
Lookup(String name):接受串名 l
Lookup(javax.naming.Name):接受结构名,
例如,CompositeName(跨越了多个命名系统的名称)或CompondName(单个命名系统中的名称);它们都实现了Name接口。Compound name的一个例子是:cn=mydir,cn=Q Mahmoud,ou=People,composite name的一个例子是:cn=mydir,cn=Q Mahmoud,ou=People/myfiles/max.txt(这里,myfiles/max.txt是表示第二部分的文件名)
Javax.naming.InitialContext是实现了Context接口的类。用这个类作为命名服务的入口。为了创建InitialContext对象,构造器以java.util.Hashtable或者是其子类(例如,Properties)的形式设置一组属性。下面给出了一个例子:
Hashtable env = new Hashtable(); // select a service provider factory env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContext"); // create the initial context Context contxt = new InitialContext(env);
INITIAL_CONTEXT_FACTORY指定了JNDI服务提供者中工厂类(factory class)的名称。Factory负责为其服务创建适当的InitialContext对象。在上面的代码片断中,为文件系统服务提供者指定了工厂类。表1给出了所支持的服务提供者的工厂类。要注意的是文件系统服务提供者的工厂类需要从Sun公司单独下载,J2SE 1.4.x没有包含这些类。
表1:上下文INITIAL_CONTEXT_FACTORY的值 Name Service Provider Factory
File System com.sun.jndi.fscontext.RefFSContextFactory
LDAP com.sun.jndi.ldap.LdapCtxFactory
RMI com.sun.jndi.rmi.registry.RegistryContextFactory
CORBA com.sun.jndi.cosnaming.CNCtxFactory
DNS com.sun.jndi.dns.DnsContextFactory
为了用名称从命名服务或目录中取得或解析对象,使用Context的lookup方法:Object obj=contxt.lookup(name)。Lookup方法返回一个对象,这个对象表示的是你想要找的上下文的儿子。
----------------------------------------------------------------------------------------------------------------------------
对jndi总体的理解: jndi(java naming and directory Interface)它提供了一套使用命名和目录服务的接口。用户可以通过它来使用命名和目录服务。就像jdbc一样。jndi包括命名服务和目录服务两部分,其中目录服务包含目录对象directory object,它包含若干属性对象。提供了对属性的很多操作。
命名和目录服务: 命名和目录服务我们一直在使用,如操作系统的文件系统,它给我们提供对文件的操作,查询,添加删除等功能。DNS服务将url同ip地址绑定在了一起。命名和目录系统的最主要的功能是将name和对象绑定。在它的基础之上还提供更多的功能如lookup,search.而且存储的对象是有一定层次结构的。使用这样的服务我们可以对对象更加有效的管理和操作。
命名服务将一个名称映射到一个对象。RMI Registry和CORBA Naming Service都是命名服务。
目录服务也存放对象,但目录服务识别这些对象的相关属性。可以用项目属性来搜索目录。
在20世纪90年代早期,轻量级的目录访问协议(LightWeightDiretoryAccessProtocol,LDAP)被作为一种标准的目录协议被开发出来,JNDI能够访问LDAP。
j2se为jndi提供了5个扩展包:
javax.naming;为访问命名服务提供的api
javax.naming.directory;为访问目录服务提供了基本的接口
javax.naming.event;支持命名和目录服务中的事件通知
javax.naming.ldap; 支持ldap的包,
javax.naming.spi;提供了不同命名和目录服务可以挂接他们的实现的方法。
context: context是一套name-to-object的绑定(bindings),可以理解为层次或目录,它还可已包括下一层subContext。在使用命名和目录服务时获得initial context是对整个名字空间操作的入口。在目录服务中是DirContext.
----------------------------------------------------------------------------------------------------------------------------
JNDI(Java Naming and Directory Interface)是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通用、统一的接口,类似JDBC都是构建在抽象层上。
JNDI可访问的现有的目录及服务有:
DNS、XNam 、Novell目录服务、LDAP(Lightweight Directory Access Protocol 轻型目录访问协议)、 CORBA对象服务、文件系统、Windows XP/2000/NT/Me/9x的注册表、RMI、DSML v1&v2、NIS。
JNDI优点:
包含了大量的命名和目录服务,使用通用接口来访问不同种类的服务;可以同时连接到多个命名或目录服务上;建立起逻辑关联,允许把名称同Java对象或资源关联起来,而不必指导对象或资源的物理ID。
JNDI程序包:
javax.naming:命名操作;
javax.naming.directory:目录操作;
javax.naming.event:在命名目录服务器中请求事件通知;
javax.naming.ldap:提供LDAP支持;
javax.naming.spi:允许动态插入不同实现。
利用JNDI的命名与服务功能来满足企业级APIs对命名与服务的访问,诸如EJBs、JMS、JDBC 2.0以及IIOP上的RMI通过JNDI来使用CORBA的命名服务。
JNDI与JDBC:
JNDI提供了一种统一的方式,可以用在网络上查找和访问服务。通过指定一个资源名称,该名称对应于数据库或命名服务中的一个纪录,同时返回数据库连接建立所必须的信息。
代码示例:
try{
Context cntxt = new InitialContext();
DataSource ds = (DataSource) cntxt.lookup("jdbc/dpt");
}
catch(NamingException ne){
...
}
JNDI与JMS:
消息通信是软件组件或应用程序用来通信的一种方法。JMS就是一种允许应用程序创建、发送、接收、和读取消息的JAVA技术。
代码示例:
try{
Properties env = new Properties();
InitialContext inictxt = new InitialContext(env);
TopicConnectionFactory connFactory = (TopicConnectionFactory) inictxt.lookup("TTopicConnectionFactory");
...
}
catch(NamingException ne){
...
}
访问特定目录:举个例子,人是个对象,他有好几个属性,诸如这个人的姓名、电话号码、电子邮件地址、邮政编码等属性。通过getAttributes()方法
Attribute attr = directory.getAttributes(personName).get("email");
String email = (String)attr.get();
通过使用JNDI让客户使用对象的名称或属性来查找对象:
foxes = directory.search("o=Wiz,c=US", "sn=Fox", controls);
通过使用JNDI来查找诸如打印机、数据库这样的对象,查找打印机的例子:
Printer printer = (Printer)namespace.lookup(printerName);
printer.print(document);
浏览命名空间:
NamingEnumeration list = namespace.list("o=Widget, c=US");
while (list.hasMore()) {
NameClassPair entry = (NameClassPair)list.next();
display(entry.getName(), entry.getClassName());
}
参考资料:
http://java.sun.com/products/jndi/examples.html
http://java.sun.com/products/jndi/serviceproviders.html
常用的JNDI操作:
void bind(String sName,Object object);――绑定:把名称同对象关联的过程
void rebind(String sName,Object object);――重新绑定:用来把对象同一个已经存在的名称重新绑定
void unbind(String sName);――释放:用来把对象从目录中释放出来
void lookup(String sName,Object object);――查找:返回目录总的一个对象
void rename(String sOldName,String sNewName);――重命名:用来修改对象名称绑定的名称
NamingEnumeration listBinding(String sName);――清单:返回绑定在特定上下文中对象的清单列表
NamingEnumeration list(String sName);
代码示例:重新得到了名称、类名和绑定对象。
NamingEnumeration namEnumList = ctxt.listBinding("cntxtName");
...
while ( namEnumList.hasMore() ) {
Binding bnd = (Binding) namEnumList.next();
String sObjName = bnd.getName();
String sClassName = bnd.getClassName();
SomeObject objLocal = (SomeObject) bnd.getObject();
}
----------------------------------------------------------------------------------------------------------------------------
了解名字服务和目录服务的相关概念,有助于更好的使用JNDI。 Naming service 名字服务定义了如何将名字与对象关联,并通过名字如何找到对象的方法。典型的例子如:DNS将域名与IP关联,文件系统将文件名与文件相关联。在名字服务中,主要的概念:
- 名字(Names),在名字系统中实际对象的代号,如文件名,域名等,它会被用来查找关联的对象。不同的系统中会有不同的命名规范,如文件系统采用“\”来表示层级,而DNS则使用“.”。
- 绑定(Bindings),名字和实际对象的关联。
- 引用和地址(References and Addresses),当对象不能直接被存储在名字系统时,就必须使用引用,通过引用找到实际的对象。在系统中,保存的引用的内容被称为地址。引用还有另一个用处:在名字系统中,缺少象关系数据库中外键的概念。通过使用引用,可以作为外键的一个取代办法。
- 上下文(Context),它是一个名字-对象集合,提供了与名字系统交互的主要操作,如查找、绑定、去绑定。子上下文(subcontext)与它的关系类似文件系统中目录和子目录的关系,子上下文被包含在一个上下文中,通过父上下文中的一个名字与子上下文关联。
- 名字系统和名字空间(Naming Systems and Namespaces),名字系统是相同类型的上下文的集合,它提供名字服务;名字空间,是名字系统中的名字集合,如文件系统的文件名和目录。
Directory service 目录服务是名字服务的扩展,它除了关联名字和对象,还允许对象包含属性。目录系统通常以层次结构组织数据。在目录服务中的主要概念:
- 属性(Attributes),它属于目录对象,它是(名字,值)对,属性可以有多个值。
- 目录和目录服务(Directories and Directory Services),目录是目录对象的集合;目录服务则提供与目录相关的服务,创建、删除和修改存放在目录中的对象的属性。
- 查找和查找过滤器(Searches and Search Filters),获取目录对象的操作就是查找;过滤器是类似查找条件的对象。
基本使用
² 注册JNDI提供者
在使用JNDI之前,需要先获取JNDI的提供者,并在系统注册它。与JNDI相关的系统属性在javax.naming.Context中定义,常用的属性:
- java.naming.factory.initial,服务提供者用来创建InitialContext的类名。
- java.naming.provider.url,用来配置InitialContext的初始url
- java.naming.factory.object,用来创建name-to-object映射的类,用于NameClassPair和References。
- java.naming.factory.state,用来创建jndi state的类
对于目录服务,由于一般需要安全设置,还通常使用:
- java.naming.security.authentication,安全类型,三个值:none,simple或strong。
- java.naming.security.principal,认证信息。
- java.naming.security.credentials,证书信息。
- java.naming.security.protocol,安全协议名。
使用System.setProperty注册,如果程序不显示说明,那么java会在classpath内查找jdni.properties文件来完成注册。jdni.properties例子:
java.naming.factory.initial=com.codeline.db.MockInitialContextFactory
【连接服务】
注册之后,就可以实施服务连接了。对于名字服务由InitialContext开始,目录服务则使用InitialDirContext。它们分别实现了Context和DirContext,这两个接口分别对应名字服务和目录服务的接口,也是JNDI中最重要的两个接口。
连接名字服务:
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,"
com.sun.jndi.fscontext.FSContextFactory");
InitialContext ctx = new InitialContext();
连接目录服务:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://myserver.com/");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
//登录ldap server需要的用户名
env.put(Context.SECURITY_PRINCIPAL, "ldapuser");
//登录ldap server需要的密码
env.put(Context.SECURITY_CREDENTIALS, "mypassword");
InitialDirContext ctx = new InitialDirContext(env);
多服务提供者:如果应用包含多个服务提供者,在连接时略有不同。以名字服务为例
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.rmi.registry.RegistryContextFactory");
env.put(Context.PROVIDER_URL, "rmi://myserver.com:1099");
//使用不同的构造函数
InitialContext ctx = new InitialContext(env);
【查找对象】
不论名字服务还是目录服务,都是使用lookup来查找对象的。除了可以使用String作为参数之外,lookup还可使用Name接口作为参数。
Greeter greeter = (Greeter)ctx.lookup("SayHello");
如果想要获得上下文中所有的对象名字,就使用lis返回NameClassPair列表。NameClassPair包含对象名字和对象类名。如果想要获得实际的对象实例列表,就使用listBindings,它返回Binding列表。Binding是NameClassPair的子类,它包含对象的实例。
- list
NamingEnumeration list = ctx.list("awt");
while (list.hasMore()) {
NameClassPair nc = (NameClassPair)list.next();
System.out.println(nc);
}
- listBindings
NamingEnumeration bindings = ctx.listBindings("awt");
while (bindings.hasMore()) {
Binding bd = (Binding)bindings.next();
System.out.println(bd.getName() + ": " + bd.getObject());
}
【对象绑定】
- 使用bind添加绑定
Fruit fruit = new Fruit("orange");
ctx.bind("favorite", fruit);
- 使用rebind修改绑定
Fruit fruit = new Fruit("lemon");
ctx.rebind("favorite", fruit);
- 使用unbind去除绑定。
ctx.unbind("favorite");
【对象改名】
使用rename可以给一个在上下文中的对象改名
ctx.rename("report.txt", "old_report.txt");
- 获取属性
属性相关的接口是Attribute和Attributes,它们都在javax.naming.directory包内。通过DirContext的getAttributes方法就可以获得对象的属性集合,然后使用Attributes的get方法获得对应的属性,最后通过Attribute的get方法就可以获得属性值。
String dn = "uid=me, dc=mycompany, dc=com, ou=customer, o=ExampleApp";
Context user = (Context)ctx.lookup(dn);
//获得所有属性
Attributes attrs = user.getAttributes("");
Attribute test= attrs .get("test");
Object testValue= test.get();
上例中获得的是user的所有属性,在实际使用过程中,考虑网络带宽的影响,可以设置获取要获取的属性列表:
String reqd_attrs = new String[] { "surname", "initials","title", "rfc822mailalias"};
Attributes attrs = user.getAttributes("", reqd_attrs);
【查找和过滤】
使用search方法完成。
public DirContext[] findUser(String initials,String surname,String country,String phone) {
//构造条件
BasicAttributes search_attrs = new BasicAttributes();
search_attrs.put("initials", initials);
search_attrs.put("sn", surname);
search_attrs.put("c", country);
if(phone != null)
search_attrs.put("phonenumber", phone);
NamingEnumeration results = initial_ctx.search("ou=Customer,o=ExampleApp", search_attrs);
LinkedList found = new LinkedList();
while(results.hasMore()) {
SearchResults sr = (SearchResults)results.next();
String name = sr.getName();
Object ctx = sr.getObject();
if((ctx == null) || !(ctx instanceof DirContext))
found.add(initial_ctx.lookup(name));
else
found.add(ctx);
}
DirContext[] ret_val = new DirContext[found.size()];
found.toArray(ret_val);
return ret_val;
}
DirContext接口主要过滤方式:
1.使用过滤字符串
String reqd_attrs = new String[] { "cn", "uid","rfc822mailalias" };
NamingEnumeration results = initial_ctx.search("ou=Customer, o=ExampleApp",search_attrs,reqd_attrs);
2.使用SearchControls,获得更多的控制
SearchControls ctrls = new SearchControls();
ctrls.setCountLimit(20);
ctrls.setTimeLimit(5000);
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration results = initial_ctx.search("cat=books,ou=Products,
o=ExampleApp","title=*Java*",ctrls);
【修改属性 】
使用DirContext和InitialDirContext的modifyAttributes方法完成。所谓的修改过程,实际就是先构造要修改的属性列表,然后使用上述方法提交。对于属性包含多个值时,需要把属性的不修改的值也要包含,否则服务器会认为那些值不再需要而删除它们。
public void updateAddress(String dn,String address, String country, String phone) {
BasicAttributes mod_attrs = new BasicAttributes();
if(address != null)
mod_attrs.put("address", address);
if(country != null)
mod_attrs.put("c", country);
if(phone != null)
mod_attrs.put("phonenumber", phone);
if(mod_attrs.size() != 0)
initial_ctx.modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, mod_attrs);
}
使用ModificationItem,也可一次进行多个不同的修改操作:
ModificationItem[] mod_items = new ModificationItems[2];
Attribute email = new BasicAttribute("rfc822mailalias", new_email);
ModificationItem email_mod = new ModificationItem(DirContext.ADD_ATTRIBUTE, email);
Attribute addr = new BasicAttribute("address", address);
ModificationItem addr_mod = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, addr);
mod_items[0] = email_mod;
mod_items[1] = addr_mod;
initial_ctx.modifyAttributes(dn, mod_items);
【创建上下文】
使用createSubcontext方法完成。
BasicAttributes attrs = new BasicAttributes();
attrs.put("initials", initials);
attrs.put("sn", surname);
attrs.put("rfc822mailalias", email);
if(address != null)
attrs.put("address", address);
if(country != null)
attrs.put("c", country);
if(phone != null)
attrs.put("phonenumber", phone);
initial_ctx.createSubcontext(dn, attrs);
【删除上下文】
使用destroySubcontext方法完成。
initial_ctx.destroySubcontext(dn);
资料:
jndi学习笔记 http://hankun.blogbus.com/logs/2005/12/1774694.html
[精华] JNDI http://www.chinaunix.net/jh/26/30421.html
原理:
在DataSource中事先建立多个数据库连接,保存在数据库连接池中。当程序访问数据库时,只用从连接池中取空闲状态的数据库连接即可,访问结束,销毁资源,数据库连接重新回到连接池,这与每次去直接访问数据库相比,会节省大量时间和资源。
JNDI( Java Naming and Directory Interface ),是Java平台的一个标准扩展,提供了一组接口、类和关于命名空间的概念。如同其它很多Java技术一样,JDNI是provider-based的技术,暴露了一个 API和一个服务供应接口(SPI)。这意味着任何基于名字的技术都能通过JNDI而提供服务,只要JNDI支持这项技术。JNDI目前所支持的技术包括 LDAP、CORBA Common Object Service(COS)名字服务、RMI、NDS、DNS、Windows注册表等等。很多J2EE技术,包括EJB都依靠JNDI来组织和定位实体。可以把它理解为一种将对象和名字捆绑的技术,对象工厂负责生产出对象,这些对象都和唯一的名字绑在一起,外部资源可以通过名字获得某对象的引用。
在javax.naming的包包中提供Context接口,提供了两个很好用的方法:
<1> void bind( String name , Object object )
将名称绑定到对象。所有中间上下文和目标上下文(由该名称最终原子组件以外的其他所有组件指定)都必须已经存在。
<2>Object lookup( String name )
检索指定的对象。如果 name为空,则返回此上下文的一个新实例(该实例表示与此上下文相同的命名上下文,但其环境可以独立地进行修改,而且可以并发访问)。
运行机制:
1、 首先程序代码获取初始化的 JNDI 环境并且调用 Context.lookup() 方法从 JNDI 服务提供者那里获一个 DataSource 对象
2、 中间层 JNDI 服务提供者返回一个 DataSource 对象给当前的 Java 应用程序这个 DataSource 对象代表了中间层服务上现存的缓冲数据源
3、 应用程序调用 DataSource 对象的 getConnection() 方法
4、 当 DataSource 对象的 getConnection() 方法被调用时,中间层服务器将查询数据库 连接缓冲池中有没有 PooledConnection 接口的实例对象。这个 PooledConnection 对象将被用于与数据库建立物理上的数据库连接
5、 如果在缓冲池中命中了一个 PooledCoonection 对象那么连接缓冲池将简单地更 新内部的缓冲连接队列并将该 PooledConnection 对象返回。如果在缓冲池内没 有找到现成的 PooledConnection 对象,那么 ConnectionPoolDataSource 接口将会被 用来产生一个新的 PooledConnection 对象并将它返回以便应用程序使用
6。 中间层服务器调用 PooledConnection 对象的 getConnection() 方法以便返还一个 java.sql.Connection 对象给当前的 Java 应用程序
7、 当中间层服务器调用 PooledConnection 对象的 getConnection() 方法时, JDBC 数据 库驱动程序将会创建一个 Connection 对象并且把它返回中间层服务器
8、 中间层服务器将 Connection 对象返回给应用程序 Java 应用程序,可以认为这个 Connection 对象是一个普通的 JDBC Connection 对象使用它可以和数据库建立。事 实上的连接与数据库引擎产生交互操作 。
9、 当应用程序不需要使用 Connection 对象时,可以调用 Connection 接口的 close() 方 法。请注意这种情况下 close() 方法并没有关闭事实上的数据库连接,仅仅是释 放了被应用程序占用的数据库连接,并将它还给数据库连接缓冲池,数据库连接 缓冲池会自动将这个数据库连接交给请求队列中下一个的应用程序使用。
现在,数据库的连接没有用到连接池几乎很少很少,每个项目组都可能有自己的数据库连接池组件,各容器提供商也提供了各自的数据库连接池,下面介绍一下tomcat的数据库连接管理。
tomcat6 数据源配置(server.xml方式和context.xml方式)
在server.xml下配置你必需重启服务器才能生效,而context.xml配置保存后tomcat会自动加载无需重启
在JNDI配配置数据源中需注意:项目下需要引入数据库驱动包,并且TOMCAT下也需要引入,不然会报错的
1.context.xml方式
Tomcat-6.0.26\conf\context.xml文件当添加以下的配置信息:
<Resource name="jdbc/mysql" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="60" wait_timeout="18800" timeBetweenEvictionRunsMillis="300000" minEvictableIdleTimeMillis="600000"
username="root" password="jdzxdb" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/sxtele?comautoReconnect=true&failOverReadOnly=false" removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true"/>
<Resource name="jdbc/db2" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="60" wait_timeout="18800" timeBetweenEvictionRunsMillis="300000" minEvictableIdleTimeMillis="600000"
username="lcgluser" password="lcgluser" driverClassName="com.ibm.db2.jcc.DB2Driver"
url="jdbc:db2://133.64.46.65:50000/STEDWDB" removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true"/>
其中:
name 表示指定的jndi名称
auth 表示认证方式,一般为Container
type 表示数据源床型,使用标准的javax.sql.DataSource
maxActive 表示连接池当中最大的数据库连接
maxIdle 表示最大的空闲连接数
maxWait 当池的数据库连接已经被占用的时候,最大等待时间
logAbandoned 表示被丢弃的数据库连接是否做记录,以便跟踪
username 表示数据库用户名
password 表示数据库用户的密码
driverClassName 表示JDBC DRIVER
url 表示数据库URL地址
注意,这里你配置的name值要和程序中使用的是一样的,比如按照这个例子,程序就应该是这样的
Java代码
String gENV = "java:comp/env/";
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx .lookup(gENV+"jdbc/mysql");
Connection conn = ds.getConnection();
String gENV = "java:comp/env/";
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup(gENV+"jdbc/db2");
Connection conn = ds.getConnection();
2.在server.xml文件中配置数据源
Tomcat-6.0.26\conf\context.xml中的配置:在<Host></Host>中添加如下配置
<Context path="/sljx" reloadable="true" docBase="sljx" crossContext="true"
debug="0">
<Resource
name="jdbc/oracle"
type="javax.sql.DataSource"
auth="Container"
username="sljx"
password="sljx"
driverClassName="oracle.jdbc.driver.OracleDriver"
maxIdle="3000"
maxWait="5000"
url="jdbc:oracle:thin:@localhost:1521:jadetrus"
autoReconnect="true"
maxActive="1000"/>
</Context>
具体属性解释和JAVA获取数据源跟上面一样
3.在hibernate中配置JNDI也很简单在hibernate.cfg.xml中
<property name="connection.datasource">java:/comp/env/jdbc/mysql</property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
常用获取示例
package com.cn.util.db;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class DBCache {
private InitialContext ic;
private Map<String,DataSource> cache;
private static DBCache instance = new DBCache();
private DBCache() {
try {
ic = new InitialContext();
} catch (NamingException e) {
e.printStackTrace();
}
cache = Collections.synchronizedMap(new HashMap<String,DataSource>());
}
public static DBCache getInstance() {
return instance;
}
public Connection getDBConn(String dataSourceName) throws SQLException,
NamingException {
Connection conn = null;
conn=getDataSource(dataSourceName).getConnection();
return conn;
}
public DataSource getDataSource(String dataSourceName)
throws NamingException {
if (cache.containsKey(dataSourceName)) {
return cache.get(dataSourceName);
} else {
DataSource newDataSource = (DataSource) ic.lookup(dataSourceName);
cache.put(dataSourceName, newDataSource);
return newDataSource;
}
}
public void removeDateSouceOffCache(String dataSourceName) {
try {
DataSource ds = cache.get(dataSourceName);
ds.getConnection().close();
cache.remove(dataSourceName);
} catch (Exception ex) {
}
}
public static void freeConn(Connection conn) {
freeConn(conn, null, null);
}
public static void freeConn(Connection connection, Statement statement) {
freeConn(connection, statement, null);
}
public static void freeConn(Connection conn, Statement ps, ResultSet rs) {
try {
try {
if (rs != null)
rs.close();
} finally {
try {
if (ps != null)
ps.close();
} finally {
if (conn != null)
conn.close();
}
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
如果获取连接调用getDBConn传入下面两值中任意一个即可
public static final String DATA_SOURCE = "java:comp/env/jdbc/localhostMysql";
public static final String DATA_SOURCE_DB2 = "java:comp/env/jdbc/db2";
private static final String DATA_SOURCE="java:comp/env/jdbc/oracle";
关于JNDI的更多用法
基于JNDI的应用开发
JNDI(The Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API.命名服务将名称和对象联系起来,使得我们可以用名称访问对象。目录服务是一种命名服务,在这种服务里,对象不但有名称,还有属性。
命名或目录服务使你可以集中存储共有信息,这一点在网络应用中是重要的,因为这使得这样的应用更协调、更容易管理。例如,可以将打印机设置存储在目录服务中,以便被与打印机有关的应用使用。
JNDI概述
我们大家每天都不知不觉地使用了命名服务。例如,当你在web浏览器输入URL,http://java.sun.com时,DNS(Domain Name System,域名系统)将这个符号URL名转换成通讯标识(IP地址)。命名系统中的对象可以是DNS记录中的名称、应用服务器中的EJB组件(Enterprise JavaBeans Component)、LDAP(Lightweight Directory Access Protocol)中的用户Profile.
目录服务是命名服务的自然扩展。两者之间的关键差别是目录服务中对象可以有属性(例如,用户有email地址),而命名服务中对象没有属性。因此,在目录服务中,你可以根据属性搜索对象。JNDI允许你访问文件系统中的文件,定位远程RMI注册的对象,访问象LDAP这样的目录服务,定位网络上的EJB组件。
对于象LDAP 客户端、应用launcher、类浏览器、网络管理实用程序,甚至地址薄这样的应用来说,JNDI是一个很好的选择。
JNDI架构
JNDI架构提供了一组标准的独立于命名系统的API,这些API构建在与命名系统有关的驱动之上。这一层有助于将应用与实际数据源分离,因此不管应用访问的是LDAP、RMI、DNS、还是其他的目录服务。换句话说,JNDI独立于目录服务的具体实现,只要你有目录的服务提供接口(或驱动),你就可以使用目录。如图1所示。 图1:JNDI架构
关于JNDI要注意的重要一点是,它提供了应用编程接口(application programming interface,API)和服务提供者接口(service provider interface,SPI)。这一点的真正含义是,要让你的应用与命名服务或目录服务交互,必须有这个服务的JNDI服务提供者,这正是JNDI SPI发挥作用的地方。服务提供者基本上是一组类,这些类为各种具体的命名和目录服务实现了JNDI接口?很象JDBC驱动为各种具体的数据库系统实现了JDBC接口一样。作为一个应用开发者,你不必操心JNDI SPI.你只需要确认你要使用的每一个命名或目录服务都有服务提供者。
J2SE和JNDI
Java 2 SDK 1.3及以上的版本包含了JNDI.对于JDK 1.1和1.2也有一个标准的扩展。Java 2 SDK 1.4.x的最新版本包括了几个增强和下面的命名/目录服务提供者:
l LDAP(Lightweight Directory Access Protocol)服务提供者 l CORBA COS(Common Object Request Broker Architecture Common Object Services)命名服务提供者 l RMI(Java Remote Method Invocation)注册服务提供者 l DNS(Domain Name System)服务提供者
更多的服务提供者
可以在如下网址找到可以下载的服务提供者列表:
http://java.sun.com/products/jndi/serviceproviders.html 特别有意思的或许是如下网址提供的Windows 注册表JNDI服务提供者:http://cogentlogic.com/cocoon/CogentLogicCorporation/JNDI.xml 这个服务提供者使你可以访问Windows XP/2000/NT/Me/9x的windows注册表。
也可以在如下网址下载JNDI/LDAP Booster Pack:http://java.sun.com/products/jndi/ 这个Booster Pack包含了对流行的LDAP控制的支持和扩展。它代替了与LDAP 1.2.1服务提供者捆绑在一起的booster pack.关于控制和扩展的更多信息可以在如下网站看到: http://java.sun.com/products/jndi/tutorial/ldap/ext/index.html 另一个有趣的服务提供者是Sun的支持DSML v2.0(Directory Service Markup Language,目录服务标记语言)的服务提供者。DSML的目的是在目录服务和XML之间架起一座桥梁。
JNDI API
JNDI API由5个包组成:
l Javax.naming:包含了访问命名服务的类和接口。例如,它定义了Context接口,这是命名服务执行查询的入口。 l Javax.naming.directory:对命名包的扩充,提供了访问目录服务的类和接口。例如,它为属性增加了新的类,提供了表示目录上下文的DirContext接口,定义了检查和更新目录对象的属性的方法。 l Javax.naming.event:提供了对访问命名和目录服务时的时间通知的支持。例如,定义了NamingEvent类,这个类用来表示命名/目录服务产生的事件,定义了侦听NamingEvents的NamingListener接口。 l Javax.naming.ldap:这个包提供了对LDAP 版本3扩充的操作和控制的支持,通用包javax.naming.directory没有包含这些操作和控制。 l Javax.naming.spi:这个包提供了一个方法,通过javax.naming和有关包动态增加对访问命名和目录服务的支持。这个包是为有兴趣创建服务提供者的开发者提供的。
JNDI 上下文
正如在前面提到的,命名服务将名称和对象联系起来。这种联系称之为绑定(binding)。一组这样的绑定称之为上下文(context),上下文提供了解析(即返回对象的查找操作)。其他操作包括:名称的绑定和取消绑定,列出绑定的名称。注意到一个上下文对象的名称可以绑定到有同样的命名约定的另一个上下文对象。这称之为子上下文。例如,如果UNIX中目录/home是一个上下文,那么相对于这个目录的子目录就是子上下文?例如,/home/guests中guests就是home的子上下文。在JNDI中,上下文用接口javax.naming.Context表示,这个接口是与命名服务交互的关键接口。在Context(或稍后讨论的DirContext)接口中的每一个命名方法都有两种重载形式:
Lookup(String name):接受串名 l
Lookup(javax.naming.Name):接受结构名,
例如,CompositeName(跨越了多个命名系统的名称)或CompondName(单个命名系统中的名称);它们都实现了Name接口。Compound name的一个例子是:cn=mydir,cn=Q Mahmoud,ou=People,composite name的一个例子是:cn=mydir,cn=Q Mahmoud,ou=People/myfiles/max.txt(这里,myfiles/max.txt是表示第二部分的文件名)
Javax.naming.InitialContext是实现了Context接口的类。用这个类作为命名服务的入口。为了创建InitialContext对象,构造器以java.util.Hashtable或者是其子类(例如,Properties)的形式设置一组属性。下面给出了一个例子:
Hashtable env = new Hashtable(); // select a service provider factory env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContext"); // create the initial context Context contxt = new InitialContext(env);
INITIAL_CONTEXT_FACTORY指定了JNDI服务提供者中工厂类(factory class)的名称。Factory负责为其服务创建适当的InitialContext对象。在上面的代码片断中,为文件系统服务提供者指定了工厂类。表1给出了所支持的服务提供者的工厂类。要注意的是文件系统服务提供者的工厂类需要从Sun公司单独下载,J2SE 1.4.x没有包含这些类。
表1:上下文INITIAL_CONTEXT_FACTORY的值 Name Service Provider Factory
File System com.sun.jndi.fscontext.RefFSContextFactory
LDAP com.sun.jndi.ldap.LdapCtxFactory
RMI com.sun.jndi.rmi.registry.RegistryContextFactory
CORBA com.sun.jndi.cosnaming.CNCtxFactory
DNS com.sun.jndi.dns.DnsContextFactory
为了用名称从命名服务或目录中取得或解析对象,使用Context的lookup方法:Object obj=contxt.lookup(name)。Lookup方法返回一个对象,这个对象表示的是你想要找的上下文的儿子。
----------------------------------------------------------------------------------------------------------------------------
对jndi总体的理解: jndi(java naming and directory Interface)它提供了一套使用命名和目录服务的接口。用户可以通过它来使用命名和目录服务。就像jdbc一样。jndi包括命名服务和目录服务两部分,其中目录服务包含目录对象directory object,它包含若干属性对象。提供了对属性的很多操作。
命名和目录服务: 命名和目录服务我们一直在使用,如操作系统的文件系统,它给我们提供对文件的操作,查询,添加删除等功能。DNS服务将url同ip地址绑定在了一起。命名和目录系统的最主要的功能是将name和对象绑定。在它的基础之上还提供更多的功能如lookup,search.而且存储的对象是有一定层次结构的。使用这样的服务我们可以对对象更加有效的管理和操作。
命名服务将一个名称映射到一个对象。RMI Registry和CORBA Naming Service都是命名服务。
目录服务也存放对象,但目录服务识别这些对象的相关属性。可以用项目属性来搜索目录。
在20世纪90年代早期,轻量级的目录访问协议(LightWeightDiretoryAccessProtocol,LDAP)被作为一种标准的目录协议被开发出来,JNDI能够访问LDAP。
j2se为jndi提供了5个扩展包:
javax.naming;为访问命名服务提供的api
javax.naming.directory;为访问目录服务提供了基本的接口
javax.naming.event;支持命名和目录服务中的事件通知
javax.naming.ldap; 支持ldap的包,
javax.naming.spi;提供了不同命名和目录服务可以挂接他们的实现的方法。
context: context是一套name-to-object的绑定(bindings),可以理解为层次或目录,它还可已包括下一层subContext。在使用命名和目录服务时获得initial context是对整个名字空间操作的入口。在目录服务中是DirContext.
----------------------------------------------------------------------------------------------------------------------------
JNDI(Java Naming and Directory Interface)是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通用、统一的接口,类似JDBC都是构建在抽象层上。
JNDI可访问的现有的目录及服务有:
DNS、XNam 、Novell目录服务、LDAP(Lightweight Directory Access Protocol 轻型目录访问协议)、 CORBA对象服务、文件系统、Windows XP/2000/NT/Me/9x的注册表、RMI、DSML v1&v2、NIS。
JNDI优点:
包含了大量的命名和目录服务,使用通用接口来访问不同种类的服务;可以同时连接到多个命名或目录服务上;建立起逻辑关联,允许把名称同Java对象或资源关联起来,而不必指导对象或资源的物理ID。
JNDI程序包:
javax.naming:命名操作;
javax.naming.directory:目录操作;
javax.naming.event:在命名目录服务器中请求事件通知;
javax.naming.ldap:提供LDAP支持;
javax.naming.spi:允许动态插入不同实现。
利用JNDI的命名与服务功能来满足企业级APIs对命名与服务的访问,诸如EJBs、JMS、JDBC 2.0以及IIOP上的RMI通过JNDI来使用CORBA的命名服务。
JNDI与JDBC:
JNDI提供了一种统一的方式,可以用在网络上查找和访问服务。通过指定一个资源名称,该名称对应于数据库或命名服务中的一个纪录,同时返回数据库连接建立所必须的信息。
代码示例:
try{
Context cntxt = new InitialContext();
DataSource ds = (DataSource) cntxt.lookup("jdbc/dpt");
}
catch(NamingException ne){
...
}
JNDI与JMS:
消息通信是软件组件或应用程序用来通信的一种方法。JMS就是一种允许应用程序创建、发送、接收、和读取消息的JAVA技术。
代码示例:
try{
Properties env = new Properties();
InitialContext inictxt = new InitialContext(env);
TopicConnectionFactory connFactory = (TopicConnectionFactory) inictxt.lookup("TTopicConnectionFactory");
...
}
catch(NamingException ne){
...
}
访问特定目录:举个例子,人是个对象,他有好几个属性,诸如这个人的姓名、电话号码、电子邮件地址、邮政编码等属性。通过getAttributes()方法
Attribute attr = directory.getAttributes(personName).get("email");
String email = (String)attr.get();
通过使用JNDI让客户使用对象的名称或属性来查找对象:
foxes = directory.search("o=Wiz,c=US", "sn=Fox", controls);
通过使用JNDI来查找诸如打印机、数据库这样的对象,查找打印机的例子:
Printer printer = (Printer)namespace.lookup(printerName);
printer.print(document);
浏览命名空间:
NamingEnumeration list = namespace.list("o=Widget, c=US");
while (list.hasMore()) {
NameClassPair entry = (NameClassPair)list.next();
display(entry.getName(), entry.getClassName());
}
参考资料:
http://java.sun.com/products/jndi/examples.html
http://java.sun.com/products/jndi/serviceproviders.html
常用的JNDI操作:
void bind(String sName,Object object);――绑定:把名称同对象关联的过程
void rebind(String sName,Object object);――重新绑定:用来把对象同一个已经存在的名称重新绑定
void unbind(String sName);――释放:用来把对象从目录中释放出来
void lookup(String sName,Object object);――查找:返回目录总的一个对象
void rename(String sOldName,String sNewName);――重命名:用来修改对象名称绑定的名称
NamingEnumeration listBinding(String sName);――清单:返回绑定在特定上下文中对象的清单列表
NamingEnumeration list(String sName);
代码示例:重新得到了名称、类名和绑定对象。
NamingEnumeration namEnumList = ctxt.listBinding("cntxtName");
...
while ( namEnumList.hasMore() ) {
Binding bnd = (Binding) namEnumList.next();
String sObjName = bnd.getName();
String sClassName = bnd.getClassName();
SomeObject objLocal = (SomeObject) bnd.getObject();
}
----------------------------------------------------------------------------------------------------------------------------
了解名字服务和目录服务的相关概念,有助于更好的使用JNDI。 Naming service 名字服务定义了如何将名字与对象关联,并通过名字如何找到对象的方法。典型的例子如:DNS将域名与IP关联,文件系统将文件名与文件相关联。在名字服务中,主要的概念:
- 名字(Names),在名字系统中实际对象的代号,如文件名,域名等,它会被用来查找关联的对象。不同的系统中会有不同的命名规范,如文件系统采用“\”来表示层级,而DNS则使用“.”。
- 绑定(Bindings),名字和实际对象的关联。
- 引用和地址(References and Addresses),当对象不能直接被存储在名字系统时,就必须使用引用,通过引用找到实际的对象。在系统中,保存的引用的内容被称为地址。引用还有另一个用处:在名字系统中,缺少象关系数据库中外键的概念。通过使用引用,可以作为外键的一个取代办法。
- 上下文(Context),它是一个名字-对象集合,提供了与名字系统交互的主要操作,如查找、绑定、去绑定。子上下文(subcontext)与它的关系类似文件系统中目录和子目录的关系,子上下文被包含在一个上下文中,通过父上下文中的一个名字与子上下文关联。
- 名字系统和名字空间(Naming Systems and Namespaces),名字系统是相同类型的上下文的集合,它提供名字服务;名字空间,是名字系统中的名字集合,如文件系统的文件名和目录。
Directory service 目录服务是名字服务的扩展,它除了关联名字和对象,还允许对象包含属性。目录系统通常以层次结构组织数据。在目录服务中的主要概念:
- 属性(Attributes),它属于目录对象,它是(名字,值)对,属性可以有多个值。
- 目录和目录服务(Directories and Directory Services),目录是目录对象的集合;目录服务则提供与目录相关的服务,创建、删除和修改存放在目录中的对象的属性。
- 查找和查找过滤器(Searches and Search Filters),获取目录对象的操作就是查找;过滤器是类似查找条件的对象。
基本使用
² 注册JNDI提供者
在使用JNDI之前,需要先获取JNDI的提供者,并在系统注册它。与JNDI相关的系统属性在javax.naming.Context中定义,常用的属性:
- java.naming.factory.initial,服务提供者用来创建InitialContext的类名。
- java.naming.provider.url,用来配置InitialContext的初始url
- java.naming.factory.object,用来创建name-to-object映射的类,用于NameClassPair和References。
- java.naming.factory.state,用来创建jndi state的类
对于目录服务,由于一般需要安全设置,还通常使用:
- java.naming.security.authentication,安全类型,三个值:none,simple或strong。
- java.naming.security.principal,认证信息。
- java.naming.security.credentials,证书信息。
- java.naming.security.protocol,安全协议名。
使用System.setProperty注册,如果程序不显示说明,那么java会在classpath内查找jdni.properties文件来完成注册。jdni.properties例子:
java.naming.factory.initial=com.codeline.db.MockInitialContextFactory
【连接服务】
注册之后,就可以实施服务连接了。对于名字服务由InitialContext开始,目录服务则使用InitialDirContext。它们分别实现了Context和DirContext,这两个接口分别对应名字服务和目录服务的接口,也是JNDI中最重要的两个接口。
连接名字服务:
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,"
com.sun.jndi.fscontext.FSContextFactory");
InitialContext ctx = new InitialContext();
连接目录服务:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://myserver.com/");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
//登录ldap server需要的用户名
env.put(Context.SECURITY_PRINCIPAL, "ldapuser");
//登录ldap server需要的密码
env.put(Context.SECURITY_CREDENTIALS, "mypassword");
InitialDirContext ctx = new InitialDirContext(env);
多服务提供者:如果应用包含多个服务提供者,在连接时略有不同。以名字服务为例
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.rmi.registry.RegistryContextFactory");
env.put(Context.PROVIDER_URL, "rmi://myserver.com:1099");
//使用不同的构造函数
InitialContext ctx = new InitialContext(env);
【查找对象】
不论名字服务还是目录服务,都是使用lookup来查找对象的。除了可以使用String作为参数之外,lookup还可使用Name接口作为参数。
Greeter greeter = (Greeter)ctx.lookup("SayHello");
如果想要获得上下文中所有的对象名字,就使用lis返回NameClassPair列表。NameClassPair包含对象名字和对象类名。如果想要获得实际的对象实例列表,就使用listBindings,它返回Binding列表。Binding是NameClassPair的子类,它包含对象的实例。
- list
NamingEnumeration list = ctx.list("awt");
while (list.hasMore()) {
NameClassPair nc = (NameClassPair)list.next();
System.out.println(nc);
}
- listBindings
NamingEnumeration bindings = ctx.listBindings("awt");
while (bindings.hasMore()) {
Binding bd = (Binding)bindings.next();
System.out.println(bd.getName() + ": " + bd.getObject());
}
【对象绑定】
- 使用bind添加绑定
Fruit fruit = new Fruit("orange");
ctx.bind("favorite", fruit);
- 使用rebind修改绑定
Fruit fruit = new Fruit("lemon");
ctx.rebind("favorite", fruit);
- 使用unbind去除绑定。
ctx.unbind("favorite");
【对象改名】
使用rename可以给一个在上下文中的对象改名
ctx.rename("report.txt", "old_report.txt");
- 获取属性
属性相关的接口是Attribute和Attributes,它们都在javax.naming.directory包内。通过DirContext的getAttributes方法就可以获得对象的属性集合,然后使用Attributes的get方法获得对应的属性,最后通过Attribute的get方法就可以获得属性值。
String dn = "uid=me, dc=mycompany, dc=com, ou=customer, o=ExampleApp";
Context user = (Context)ctx.lookup(dn);
//获得所有属性
Attributes attrs = user.getAttributes("");
Attribute test= attrs .get("test");
Object testValue= test.get();
上例中获得的是user的所有属性,在实际使用过程中,考虑网络带宽的影响,可以设置获取要获取的属性列表:
String reqd_attrs = new String[] { "surname", "initials","title", "rfc822mailalias"};
Attributes attrs = user.getAttributes("", reqd_attrs);
【查找和过滤】
使用search方法完成。
public DirContext[] findUser(String initials,String surname,String country,String phone) {
//构造条件
BasicAttributes search_attrs = new BasicAttributes();
search_attrs.put("initials", initials);
search_attrs.put("sn", surname);
search_attrs.put("c", country);
if(phone != null)
search_attrs.put("phonenumber", phone);
NamingEnumeration results = initial_ctx.search("ou=Customer,o=ExampleApp", search_attrs);
LinkedList found = new LinkedList();
while(results.hasMore()) {
SearchResults sr = (SearchResults)results.next();
String name = sr.getName();
Object ctx = sr.getObject();
if((ctx == null) || !(ctx instanceof DirContext))
found.add(initial_ctx.lookup(name));
else
found.add(ctx);
}
DirContext[] ret_val = new DirContext[found.size()];
found.toArray(ret_val);
return ret_val;
}
DirContext接口主要过滤方式:
1.使用过滤字符串
String reqd_attrs = new String[] { "cn", "uid","rfc822mailalias" };
NamingEnumeration results = initial_ctx.search("ou=Customer, o=ExampleApp",search_attrs,reqd_attrs);
2.使用SearchControls,获得更多的控制
SearchControls ctrls = new SearchControls();
ctrls.setCountLimit(20);
ctrls.setTimeLimit(5000);
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration results = initial_ctx.search("cat=books,ou=Products,
o=ExampleApp","title=*Java*",ctrls);
【修改属性 】
使用DirContext和InitialDirContext的modifyAttributes方法完成。所谓的修改过程,实际就是先构造要修改的属性列表,然后使用上述方法提交。对于属性包含多个值时,需要把属性的不修改的值也要包含,否则服务器会认为那些值不再需要而删除它们。
public void updateAddress(String dn,String address, String country, String phone) {
BasicAttributes mod_attrs = new BasicAttributes();
if(address != null)
mod_attrs.put("address", address);
if(country != null)
mod_attrs.put("c", country);
if(phone != null)
mod_attrs.put("phonenumber", phone);
if(mod_attrs.size() != 0)
initial_ctx.modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, mod_attrs);
}
使用ModificationItem,也可一次进行多个不同的修改操作:
ModificationItem[] mod_items = new ModificationItems[2];
Attribute email = new BasicAttribute("rfc822mailalias", new_email);
ModificationItem email_mod = new ModificationItem(DirContext.ADD_ATTRIBUTE, email);
Attribute addr = new BasicAttribute("address", address);
ModificationItem addr_mod = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, addr);
mod_items[0] = email_mod;
mod_items[1] = addr_mod;
initial_ctx.modifyAttributes(dn, mod_items);
【创建上下文】
使用createSubcontext方法完成。
BasicAttributes attrs = new BasicAttributes();
attrs.put("initials", initials);
attrs.put("sn", surname);
attrs.put("rfc822mailalias", email);
if(address != null)
attrs.put("address", address);
if(country != null)
attrs.put("c", country);
if(phone != null)
attrs.put("phonenumber", phone);
initial_ctx.createSubcontext(dn, attrs);
【删除上下文】
使用destroySubcontext方法完成。
initial_ctx.destroySubcontext(dn);
资料:
jndi学习笔记 http://hankun.blogbus.com/logs/2005/12/1774694.html
[精华] JNDI http://www.chinaunix.net/jh/26/30421.html
发表评论
-
wabacus学习体会二
2012-09-26 12:09 988采用控制列编辑方式生成可编辑自动列表报表时,需要把 ... -
wabacus 学习体会一
2012-08-20 16:21 1168采用<report type ="form&q ... -
SQL完成交叉表功能
2012-08-08 09:38 2071SQL完成交叉表功能 转自http://www.2cto. ... -
Eclipse的Tomcat插件安装
2012-08-06 15:55 873Eclipse的Tomcat插件安装[ ... -
如何禁止windows xp和2003使用F8进入安全模式
2012-08-06 15:27 1492如何禁止window ... -
OFBiz的主要配置文件说明——ofbiz-component.xml
2012-07-18 17:45 1089OFBiz的主要配置文件说明——ofbiz-component ... -
OFBiz之Component与Application
2012-07-18 17:38 830OFBiz之Component与Application ... -
OFBiz的主要配置文件说明——component-load.xml
2012-07-18 17:25 980OFBiz的主要配置文件说明——component-lo ... -
Ofbiz基本结构
2012-07-18 17:11 980OFBiz是一个非常著名的电子商务平台,是一个 ... -
MVC已过时,MOVE时代来临?
2012-07-17 22:19 746转自:http://sd.csdn.net/a/201 ... -
只需一条语句即可记住所有的ORACLE的系统表
2012-08-06 15:31 698转自:http://wulinhaoxia5.ite ... -
VMWare虚拟机优化十招
2012-07-16 16:35 1364转自 http://virtual.51cto.com/art ... -
OFBIZ10.04开发环境搭建
2012-07-16 00:23 1071转自 http://www.haogongju.net/art ... -
软件产品的演示技巧
2010-03-31 15:49 652软件产品的演示技巧 -- ... -
sql语句优化
2012-07-15 23:58 704sql语句优化 总结1 选择索引 ... -
优化数据库的方法及SQL语句优化的原则
2012-07-15 23:47 712转自 硅谷动力 http://www.enet.com.cn/ ... -
SQL语句优化的原则(主要MySQL)
2012-07-15 23:44 1048转自 http://home.oncity.cc/home-s ...
相关推荐
在Java Web应用中,连接池是一种管理数据库连接的机制,它可以高效地复用数据库连接,减少创建和销毁连接带来的开销。在Tomcat 5.5这个版本中,配置...通过以上介绍,你应该对Tomcat 5.5的连接池配置有了全面的认识。
在分析数据库连接池工作原理的基础上,给出了Tomcat服务器数据库连接池的配置实例,以及在JSP页面中使用此连接池进行数据库访问的Java代码。在大型Web站点的开发中,使用数据库连接池技术是必要的,也是可取的。
- 在JBOSS的default/deploy目录下添加mssql-ds.xml文件,用于配置Microsoft SQL Server 2000的连接池。这涉及到定义JNDI名称、连接URL、驱动类、用户名、密码、最小和最大池大小等参数。 - **添加jboss-web.xml...
内容概要:文章主要讲解了力扣763题——划分字母区间的解法。题目要求对字符串进行划分,使得每个字母只出现在一个子串中,并且这些子串是连续的。文中详细解释了算法的核心思想:从字符串的第一个字符开始,找到该字符最后一次出现的位置作为初始区间边界;然后遍历该区间内的所有字符,不断更新区间的右边界为当前字符最后出现位置的最大值,直到遍历结束,即得到一个完整的区间。最后通过示例代码演示了这一思路的具体实现方法,包括输入字符串、计算各字符最远出现位置、确定区间长度并输出结果等步骤。; 适合人群:对算法和数据结构有一定了解,特别是正在准备编程竞赛或面试的程序员。; 使用场景及目标:①理解划分字母区间的贪心算法思想;②掌握如何通过查找字符最后出现位置来构建不重叠的最优区间;③学习C++语言中字符串操作函数如rfind()的应用; 阅读建议:在阅读时应重点关注算法的设计思路及其背后的逻辑,同时注意代码细节,如循环条件、边界处理等,可以尝试自己动手实现一遍加深理解。
base(1).apk.1
# 基于C语言的STM32开发板功能支持库 ## 项目简介 本项目是针对STM32微控制器的开发板支持库,涵盖多种功能模块,像GPIO控制、LCD驱动、串行通信等。为开发者提供丰富库函数与示例代码,简化STM32微控制器开发流程。 ## 项目的主要特性和功能 1. GPIO控制可进行GPIO初始化、配置、读写及引脚锁定,方便控制引脚状态。 2. LCD驱动支持多种LCD型号,能完成初始化、设置颜色、显示字符、绘制图形等操作。 3. 串行通信提供串行通信端口初始化、配置与通信功能,支持USART等协议。 4. IO扩展器支持STMPE811等IO扩展器驱动,具备IO读写、Joystick配置等功能。 5. 时钟管理可进行系统时钟配置与管理,包括时钟源选择、分频因子设置。 6. 任务调度实现实时多任务操作系统(uCOS II)核心功能,如任务创建、删除等。 7. 同步机制提供事件标志、消息邮箱、互斥锁、队列和信号量等同步机制,用于任务间通信与同步。
# 基于Linux内核的MaliG610 GPU模拟及性能分析系统 ## 项目简介 本项目名为kbasevalhall,主要用于模拟一个MaliG610(用于RK3588)GPU。它提供了创建和初始化时间线对象的功能,可用于跟踪和记录GPU设备的状态与操作序列,为GPU的性能分析和调试提供有效工具。 ## 项目的主要特性和功能 1. 模拟MaliG610 GPU通过项目代码可以模拟出MaliG610 GPU,为相关开发和测试提供环境。 2. 时间线对象管理创建并初始化多种时间线对象,如逻辑处理单元(LPU)、地址空间(AS)和GPU对象等,用于跟踪GPU设备状态。 3. 上下文跟踪遍历设备中的所有上下文,为每个上下文创建新的时间线对象,跟踪地址空间分配和内核处理器队列状态信息。 4. 数据传输刷新所有流,确保摘要包传输到用户空间,方便应用程序访问GPU性能数据。
# 基于Arduino的恐龙游戏 ## 项目简介 此项目是一个基于Arduino的恐龙游戏版本开发。包含了与游戏角色、场景元素相关的图形定义文件。通过二进制形式定义了游戏角色(如恐龙、角色腿等)以及场景元素(如云)的形状。这些图形定义被存储在AVR微控制器的PROGMEM中,用于游戏或应用程序的开发。 ## 项目的主要特性和功能 1. 图形定义项目包含多个图形定义文件,用于描述游戏角色和场景元素的形状。 2. 二进制图形表示所有的图形数据都以二进制形式存储,适用于在AVR微控制器上运行的游戏或应用程序。 3. 游戏角色和场景元素包括恐龙角色的主要形状、腿的形状,以及不同大小的云等场景元素。 ## 安装使用步骤 由于此项目为源码文件,用户已经拥有项目的全部代码,接下来可以按照以下步骤进行安装和使用 1. 导入源码将源码文件导入Arduino开发环境。 2. 修改和优化根据需要进行修改和优化代码,以适应特定的硬件或功能需求。
# 基于AVR单片机的自动搅拌杯系统 ## 项目简介 本项目针对传统手动搅拌杯需频繁按压按钮搅拌饮品的不便,利用AVR单片机(ATtiny13和ATmega328p)打造了自动搅拌杯系统。该系统通过简单电路控制电机和LED灯,实现自动搅拌功能,同时具备低功耗特性,延长电池使用寿命。 ## 项目的主要特性和功能 1. 多模式自动搅拌可通过按钮切换不同的搅拌模式,如电机持续开启、每隔30秒开启5秒、每隔1分钟开启5秒、每隔1分30秒开启5秒等。 2. LED状态指示LED灯以不同频率闪烁,直观显示当前的工作模式。 3. 低功耗运行在Power Down模式下,ATtiny13仅消耗0.5uA电流,确保长时间闲置时电池电量的有效保存。 4. 时间可调节能够通过修改代码中的相关参数,灵活调整电机搅拌时间和LED闪烁时间。 ## 安装使用步骤 ### 安装
# 基于Node.js和IoT的心率监测系统 ## 项目简介 基于Node.js和IoT的心率监测系统是一个低成本的物联网(IoT)应用,旨在全天候监测用户的心率和血氧饱和度。该系统通过心率和血氧传感器定期提醒用户进行测量,并将数据传输到Web应用程序中供用户查看。用户可以配置测量时间和频率,Web应用程序采用响应式设计,支持桌面、平板和移动设备。 ## 项目的主要特性和功能 IoT集成使用低成本的IoT设备与心率和血氧传感器协同工作。 周期性提醒全天候提醒用户在可配置的时间间隔内进行测量。 响应式设计Web应用程序设计为在不同设备上提供一致的用户体验。 数据传输和监控测量数据传输到Web应用程序,供用户监控。 ## 安装使用步骤 ### 1. 复制项目仓库 bash ### 2. 进入项目目录 bash cd 413FinalProject ### 3. 安装依赖 bash
该项目是一个基于LaTeX的个人简历设计源码,集成了Python和Shell脚本功能,共包含54个文件,包括14个OTF字体文件、8个样式文件、8个TeX源文件、6个PDF文档、5个GZ压缩文件、2个JPG图片文件、1个BST模板文件、1个LICENSE授权文件、1个Makefile构建文件、1个Markdown文件。该项目适用于个人简历制作,提供专业的排版和个性化设计。
内容概要:本文详细介绍了利用FLAC 3D进行近断层隧道围岩稳定性的流固耦合分析方法。首先构建了三维网格并设置了摩尔-库仑本构模型和相关材料参数,接着对断层带进行了特殊处理,降低了其力学性能。文中重点讲解了流固耦合的具体设置步骤,包括开启流体模式、设置水的物理属性以及孔隙水压初始化等。此外,还展示了如何通过历史记录和绘图功能监控计算过程中的重要参数变化,并提供了防止数值不稳定的经验建议。最后,作者分享了一个实际案例,强调了流固耦合分析对于提高隧道安全性和优化设计方案的重要性。 适合人群:从事地下工程、岩土工程领域的研究人员和技术人员,尤其是那些需要掌握复杂地质条件下隧道稳定性评估技能的专业人士。 使用场景及目标:适用于研究和解决靠近断层带的隧道工程项目中存在的围岩失稳风险问题,旨在帮助工程师更好地理解和预测隧道在渗流水作用下的行为,从而制定合理的支护措施。 其他说明:文章不仅涵盖了理论知识,还包括大量实用的操作技巧和注意事项,有助于读者将所学应用于实际工作中。同时,文中提供的完整代码片段便于读者动手实践,加深理解。
数字化转型是指企业或个人利用数字技术,如大数据、云计算、人工智能等,对其业务流程、运营模式、决策方式等进行全面、深入的变革,以提高效率、降低成本、提升质量、增强竞争力。在这个过程中,工具变量扮演着至关重要的角色。 本数据包含:原始数据、参考文献、代码do文件、最终结果。 指标 企业代码 企业代码 年份 股票简称 企业数字化转型程度。基于吴非方法构建 工具变量:同行业其他企业数字化转型程度的均值 工具变量:同行业数字化转型程度的均值 工具变量:同行业同年份其他企业数字化转型程度的均值 工具变量:同行业同年份数字化转型程度的均值 工具变量:同地区同行业同年份数字化转型程度的均值 工具变量:同地区同行业同年份其他企业数字化转型程度的均值 行业名称 制造业取两位代码,其他行业用大类
BellSoft Liberica JDK 是一个经过严格测试和验证的 OpenJDK,它完全符合 Java SE 规范,在Linux, Windows, macOS, 和 Solaris 操作系统上运行无误
# 基于Azure和Kubernetes的乐高小人检测系统 ## 项目简介 本项目是一个基于Azure和Kubernetes的乐高小人检测系统。项目结合了Azure机器学习服务进行模型训练和部署,利用Kubernetes进行集群管理和容器编排。通过ESP32CAM或树莓派作为图像采集设备,将采集到的图像发送到模型进行检测,并通过一个简单的网页展示检测结果。 ## 项目的主要特性和功能 1. 基础设施搭建支持Kubernetes集群和Azure环境的搭建,包括资源组、日志分析工作区、Arc连接的Kubernetes等资源的创建。 2. 模型训练使用Azure机器学习服务进行模型训练,支持自动机器学习(AutoML)功能,可同时尝试多种模型和超参数组合,提高模型性能。 3. 图像采集支持使用ESP32CAM或树莓派进行图像采集,并将采集到的图像存储到Kubernetes主节点。 4. 对象检测使用训练好的模型对采集到的图像进行乐高小人检测,并在网页上展示检测结果。
该资源为h5py-3.1.0-cp36-cp36m-macosx_10_9_x86_64.whl,欢迎下载使用哦!
内容概要:本文详细介绍了GitHub从入门到精通的各个方面,涵盖新手指南、核心操作、进阶技巧、实用工具与资源推荐以及常见问题解决方案。新手指南部分讲述了如何注册账号、创建仓库、安装配置客户端及SSH密钥配置;核心操作部分重点讲解了本地仓库初始化、版本提交与推送、文件状态与历史查看;进阶技巧部分探讨了分支管理策略、协作开发流程及冲突解决方法;实用工具与资源推荐部分介绍了GitHub Actions、GitHub Pages、GitHub Copilot等官方工具链,以及多个优秀学习资源库;常见问题解决方案部分则提供了关于权限问题处理和代码回滚方法的具体步骤。 适合人群:适用于初次接触GitHub的新手开发者,以及希望深入了解GitHub高级功能、提高团队协作效率的中高级开发者。 使用场景及目标:①帮助新手快速上手GitHub,掌握创建和管理仓库的基本技能;②教会用户如何进行版本控制、提交代码、查看历史记录等核心操作;③指导开发者进行高效的分支管理和团队协作,解决冲突并优化工作流程;④推荐实用工具和学习资源,提升开发效率和个人技能;⑤解决权限和代码回滚等常见问题,确保项目顺利进行。 阅读建议:本文内容详实,覆盖范围广,建议读者根据自身需求选择性阅读。对于初学者,可以从新手指南开始逐步学习;对于有一定经验的开发者,可以直接跳转到感兴趣的部分,如进阶技巧或实用工具章节。在学习过程中,结合实际操作进行练习,以加深理解和记忆。
内容概要:本文深入探讨了心电信号(ECG)去噪的技术实现,特别是在生物医学信号处理领域的应用。文中介绍了两种主要的去噪方法:低通滤波和小波分解。首先,通过低通滤波器去除高频噪声如肌电干扰和工频干扰,保留低频的心电信号特征。其次,利用小波分解将信号分解到不同频率子带,通过阈值处理去除噪声并重构信号。此外,还展示了如何在Matlab中实现这些方法,并提供了详细的代码示例。为了增强用户体验,作者还开发了一个带有操作界面的工具,支持时域和频域波形的显示,并附有操作视频。 适合人群:从事生物医学工程、信号处理的研究人员和技术人员,尤其是那些对心电信号处理感兴趣的初学者和中级开发者。 使用场景及目标:适用于需要对心电信号进行预处理的研究和应用场景,如医疗设备开发、健康监测系统等。目标是提高心电信号的质量,减少噪声干扰,从而提升后续分析的准确性。 其他说明:文中不仅提供了理论解释,还有具体的代码实现和操作指南,帮助读者更好地理解和应用这些技术。
内容概要:本文详细介绍了圆柱卷绕式锂电池的结构特点及其在Comsol Multiphysics中的建模与仿真方法。文章首先阐述了圆柱卷绕式电池的基本构成,包括正极、负极、隔膜、集流体和极耳的作用。接着,通过具体的Comsol建模步骤,如导入几何模型、定义材料属性、设置边界条件、模拟电流分布等,展示了如何利用Comsol进行电池性能的仿真分析。特别强调了极耳设计对电池性能的重要影响,并通过实例演示了如何优化极耳布局以提高电池效率。此外,文章还探讨了多物理场耦合仿真在电池热管理和电流分布优化中的应用。 适合人群:从事电池研究、仿真分析的技术人员以及对锂电池建模感兴趣的科研工作者。 使用场景及目标:适用于希望深入了解圆柱卷绕式锂电池内部结构和工作原理的研究人员和技术人员。通过仿真分析,能够优化电池设计,提高电池性能,特别是在极耳布局和热管理方面。 其他说明:文中提供了多个Comsol建模的具体代码示例,有助于读者快速上手并进行实际操作。同时,文章还讨论了一些常见的建模难题及解决方案,如薄层网格划分和多物理场耦合等问题。