Java JNDI编程完全指南:javax.naming核心用法与代码实例

2024-06-21 超腾开源 113 次阅读 0 次点赞
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使用方法及代码示例

评论 (1)

登录 后发表评论

晨风Alex晨风Alex2025-11-23 19:19:37

很详细的JNDI教程!示例代码很实用,让我终于搞懂了InitialContext的配置。感谢作者分享!