Java JNDI编程完全指南:javax.naming核心用法与代码实例
javax.naming是Java JNDI技术的核心包,为访问各种命名和目录服务提供统一接口。本文通过5个完整代码示例详细演示了JNDI的基本查找、LDAP目录操作、对象绑定重绑定、数据源配置以及自定义对象序列化等核心功能,涵盖文件系统、LDAP和数据库等常见应用场景,帮助开发者全面掌握Java命名和目录服务编程。
javax.naming 包是 Java 命名和目录接口 (JNDI) 的核心包,提供了访问命名和目录服务的功能。它允许 Java 应用程序通过统一的接口访问各种命名和目录服务,如 LDAP、DNS、文件系统等。
主要类和接口
Context - 命名服务的核心接口
InitialContext - 初始上下文的实现类
Name - 表示名称的接口
NamingException - 命名操作异常基类
示例代码
示例 1: 基本的 JNDI 查找
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;
public class BasicJNDILookup {
public static void main(String[] args) {
try {
// 设置 JNDI 环境属性
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
env.put(Context.PROVIDER_URL, "file:///C:/temp");
// 创建初始上下文
Context ctx = new InitialContext(env);
// 查找对象
Object obj = ctx.lookup("testfile.txt");
System.out.println("查找到的对象: " + obj);
// 关闭上下文
ctx.close();
} catch (NamingException e) {
e.printStackTrace();
}
}
}
示例 2: LDAP 目录服务操作
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.*;
import java.util.Hashtable;
import java.util.Properties;
public class LDAPExample {
public static void main(String[] args) {
// 设置 LDAP 连接属性
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=example,dc=com");
env.put(Context.SECURITY_CREDENTIALS, "password");
try {
// 创建目录上下文
DirContext ctx = new InitialDirContext(env);
// 搜索 LDAP 条目
String searchFilter = "(objectClass=person)";
String[] requiredAttributes = {"cn", "mail", "telephoneNumber"};
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningAttributes(requiredAttributes);
NamingEnumeration<SearchResult> results =
ctx.search("ou=people,dc=example,dc=com", searchFilter, controls);
// 遍历搜索结果
while (results.hasMore()) {
SearchResult result = results.next();
Attributes attrs = result.getAttributes();
System.out.println("姓名: " + attrs.get("cn").get());
if (attrs.get("mail") != null) {
System.out.println("邮箱: " + attrs.get("mail").get());
}
if (attrs.get("telephoneNumber") != null) {
System.out.println("电话: " + attrs.get("telephoneNumber").get());
}
System.out.println("---");
}
ctx.close();
} catch (NamingException e) {
e.printStackTrace();
}
}
}
示例 3: 绑定和重绑定操作
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;
public class BindExample {
public static void main(String[] args) {
try {
// 创建初始上下文
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
env.put(Context.PROVIDER_URL, "file:///C:/temp/jndi");
Context ctx = new InitialContext(env);
// 绑定对象
String message = "Hello JNDI!";
ctx.bind("greeting", message);
System.out.println("对象绑定成功");
// 查找绑定的对象
String retrieved = (String) ctx.lookup("greeting");
System.out.println("查找到的对象: " + retrieved);
// 重绑定对象
String newMessage = "Hello Updated JNDI!";
ctx.rebind("greeting", newMessage);
System.out.println("对象重绑定成功");
// 解绑对象
ctx.unbind("greeting");
System.out.println("对象解绑成功");
ctx.close();
} catch (NamingException e) {
e.printStackTrace();
}
}
}
示例 4: 使用 JNDI 数据源
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class DataSourceExample {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 获取初始上下文
Context ctx = new InitialContext();
// 查找数据源
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/MyDB");
// 获取数据库连接
conn = ds.getConnection();
// 执行查询
pstmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?");
pstmt.setInt(1, 1);
rs = pstmt.executeQuery();
// 处理结果
while (rs.next()) {
System.out.println("用户ID: " + rs.getInt("id"));
System.out.println("用户名: " + rs.getString("username"));
System.out.println("邮箱: " + rs.getString("email"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 清理资源
try {
if (rs != null) rs.close();
if (pstmt != null) pstmt.close();
if (conn != null) conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
示例 5: 自定义对象绑定和查找
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.io.Serializable;
import java.util.Hashtable;
// 自定义可序列化对象
class User implements Serializable {
private String name;
private String email;
private int age;
public User(String name, String email, int age) {
this.name = name;
this.email = email;
this.age = age;
}
// getters and setters
public String getName() { return name; }
public String getEmail() { return email; }
public int getAge() { return age; }
@Override
public String toString() {
return "User{name='" + name + "', email='" + email + "', age=" + age + "}";
}
}
public class CustomObjectExample {
public static void main(String[] args) {
try {
// 创建初始上下文
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
env.put(Context.PROVIDER_URL, "file:///C:/temp/jndi");
Context ctx = new InitialContext(env);
// 创建并绑定自定义对象
User user = new User("张三", "zhangsan@example.com", 25);
ctx.bind("user/zhangsan", user);
System.out.println("用户对象绑定成功");
// 查找自定义对象
User retrievedUser = (User) ctx.lookup("user/zhangsan");
System.out.println("查找到的用户: " + retrievedUser);
ctx.close();
} catch (NamingException e) {
e.printStackTrace();
}
}
}
注意事项
1、依赖: 需要相应的 JNDI 服务提供者实现
2、安全性: 注意 JNDI 注入安全问题
3、异常处理: 妥善处理 NamingException
4、资源管理: 及时关闭上下文和连接
5、这些示例展示了 javax.naming 包的基本用法,实际使用时需要根据具体的命名服务提供者进行相应的配置
最后更新于6月前
本文由人工编写,AI优化,转载请注明原文地址: javax.naming使用方法及代码示例