什么是JNDI?
Java Naming and Directory Interface(JNDI)是 Java 平台的一个 API,用于访问各种命名和目录服务,如 DNS、LDAP、Active Directory 等。JNDI 提供了一个统一的接口,使得 Java 应用程序可以通过相同的方式访问不同的命名和目录服务,而不需要了解底层服务的细节。
主要功能和特点:
1.统一命名: JNDI 提供了统一的命名系统,允许开发人员为各种资源(如对象、文件、目录)定义全局唯一的名字。
2.目录服务访问: JNDI 允许 Java 应用程序访问和管理目录服务,如 LDAP(轻量级目录访问协议)、X.500 等。
3.命名空间操作: JNDI 提供了一组 API,用于在命名空间中执行 CRUD(创建、读取、更新、删除)操作。
4.扩展性: JNDI 是一个可扩展的 API,允许开发人员编写自定义的命名服务提供者,以实现对其他命名服务的访问。
JNDI 的使用场景:
1.连接到目录服务: 通过 JNDI 可以连接到目录服务(如 LDAP 服务器),执行用户身份验证、读取用户信息等操作。
2.资源管理: JNDI 可以用于管理和访问各种资源,如数据库连接池、JMS(Java 消息服务)队列等。
3.分布式应用程序: JNDI 可以用于在分布式环境中发现和访问远程对象。
4.企业 Java 应用程序: JNDI 在企业 Java 应用程序中广泛用于查找和访问 EJB(Enterprise JavaBean)、JMS 队列、JDBC 数据源等。
核心组件
1.上下文(Context): 上下文是 JNDI 中的核心概念,表示了命名和目录服务的一个节点。上下文可以包含其他上下文和命名对象,形成一个层级结构。在 JNDI 中,所有的操作都是在上下文上进行的。例如,查找对象、绑定对象、创建子上下文等。
2.名称(Name): 名称是 JNDI 中用于标识命名对象和上下文的唯一标识符。名称由一系列名称组件(Name Component)构成,每个名称组件代表了命名层次结构中的一个节点。名称的格式通常是由一个或多个字符串组成的序列,如 cn=admin,ou=users,dc=example,dc=com。
3.命名对象(Named Object): 命名对象是 JNDI 中的一个重要概念,表示了在命名空间中具有唯一名称的对象。命名对象可以是任何 Java 对象,如字符串、整数、数组、自定义对象等。通过 JNDI,可以将命名对象绑定到命名空间中的特定位置,并通过名称来访问和查找这些对象。
4.命名操作(Naming Operation): 命名操作是指 JNDI 中对命名空间进行的各种操作,如查找对象、绑定对象、重命名对象、创建子上下文等。这些操作可以在上下文对象上直接调用,以实现对命名空间的管理和访问。
5.命名服务提供者(Naming Service Provider): 命名服务提供者是 JNDI 中的一个重要概念,表示了实际提供命名和目录服务的实体。JNDI 通过命名服务提供者来访问和操作各种命名和目录服务,如 LDAP、DNS、文件系统等。JNDI 提供了 SPI(Service Provider Interface)来允许开发人员编写自定义的命名服务提供者,以支持对其他命名服务的访问。
体系架构
Java Application(Java 应用程序): Java 应用程序是使用 JNDI 的主体,它通过调用 JNDI API 提供的方法来访问和管理命名和目录服务。Java 应用程序可以通过 JNDI 实现各种功能,如连接到 LDAP 服务器、查询数据库、访问文件系统等。
JNDI API(Java Naming and Directory Interface API): JNDI API 是 Java 平台提供的用于访问命名和目录服务的标准 API。它定义了一组接口和类,用于在 Java 应用程序中执行命名操作,如查找对象、绑定对象、创建子上下文等。Java 应用程序通过调用 JNDI API 中的方法来实现对命名和目录服务的访问和管理。
Naming Manager(命名管理器): 命名管理器是 JNDI API 中的一个重要组件,负责管理和加载命名服务提供者。当 Java 应用程序调用 JNDI API 中的方法时,命名管理器负责根据指定的名称服务提供者来实现对命名和目录服务的访问。命名管理器通过 SPI(Service Provider Interface)加载适当的命名服务提供者,并在运行时动态地选择和调用相应的实现。
JNDI SPI(Service Provider Interface): JNDI SPI 是 JNDI API 提供的一组接口,用于允许开发人员编写自定义的命名服务提供者。通过实现 JNDI SPI 中定义的接口,开发人员可以为 Java 应用程序提供自定义的命名和目录服务,以实现对其他命名服务的访问和管理。JNDI SPI 允许命名服务提供者将自己的实现注册到 JNDI 环境中,从而使 Java 应用程序能够使用这些服务。
简单示例:
以下是一个简单的示例,演示了使用 JNDI 连接到 LDAP 服务器并执行查询操作的过程:
import javax.naming.*;
import javax.naming.directory.*;
import java.util.Hashtable;
public class JNDIDemo {
public static void main(String[] args) {
try {
// 创建连接到 LDAP 服务器的环境属性
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://ldap.example.com:389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=example,dc=com");
env.put(Context.SECURITY_CREDENTIALS, "password");
// 创建初始上下文对象
DirContext ctx = new InitialDirContext(env);
// 定义 LDAP 查询条件
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String filter = "(objectClass=person)";
// 执行查询操作
NamingEnumeration results = ctx.search("ou=users,dc=example,dc=com", filter, controls);
// 处理查询结果
while (results.hasMore()) {
SearchResult result = results.next();
Attributes attrs = result.getAttributes();
Attribute cn = attrs.get("cn");
Attribute mail = attrs.get("mail");
System.out.println("Common Name: " + cn.get());
System.out.println("Email: " + mail.get());
}
// 关闭上下文对象
ctx.close();
} catch (NamingException e) {
e.printStackTrace();
}
}
}
在这个示例中,我们使用 JNDI 连接到 LDAP 服务器,并执行了一个查询操作,搜索指定组织单位下的人员信息。这个示例演示了如何使用 JNDI 访问目录服务并执行查询操作。