Java安全
Java 基础知识
01概述
02变量
03运算符
04程序控制语句
05数组
06面向对象编程
07代码练习
08重载
09作用域
10构造方法&构造器
11this
12包
13修饰符
14封装
15继承
16super
17覆盖&重写
18多态
19零钱通项目
20类变量&类方法
21抽象类
22接口
23内部类
24枚举
25泛型
26常用API
27lambda表达式
28正则表达式
29异常
30File&IO流
31日志技术
32多线程
33网络编程
01反射
02反序列化
03JVM
04JDBC
05RMI
06JRMP
07JNDI
08CDI
09JPA
10Servlet
11Filter
12MVC模型
13MVC框架
14类的加载机制
15Maven
16注解
17ORM
18CC链
19JNDI注入
Log4j2
-
+
首页
07JNDI
## 概述 JNDI(Java Naming and Directory Interface,Java 命名与目录接口)是 Java EE 中用于统一管理和访问分布式资源的规范,它通过 “名称 - 资源” 映射机制,让应用程序能通过名称快速定位并使用资源(如数据库连接池、远程对象、消息队列等),无需硬编码资源的具体位置,是分布式系统中资源解耦的核心技术。 在分布式系统中,资源(如数据库、远程服务)的位置可能动态变化(如服务器迁移、端口调整),直接在代码中写死资源地址会导致维护成本极高。 JNDI底层支持RMI远程对象,RMI注册的服务可以通过JNDI接口来访问和调用。 JNDI支持多种命名和目录提供程序(Naming and Directory Providers),RMI注册表服务提供程序(RMI Registry Service Provider)允许通过JNDI应用接口对RMI中注册的远程对象进行访问操作。 将RMI服务绑定到JNDI的一个好处是更加透明、统一和松散耦合,RMI客户端直接通过URL来定位一个远程对象,而且该RMI服务可以和包含人员,组织和网络资源等信息的企业目录链接在一起。  > JNDI 的核心解决思路是: - 引入 “命名服务” 或 “目录服务” 作为中间层,负责维护 “资源名称” 与 “资源实际位置 / 引用” 的映射(称为 “绑定”); - 应用程序只需通过 JNDI API 查询 “名称”,即可获取资源,完全屏蔽资源的物理位置细节。 简单说:JNDI 是分布式系统的 “资源导航系统”,通过名称就能找到资源的 “坐标”。 ## 核心组件 | 概念 / 组件 | 描述 | | ----------------------------- | ------------------------------------------------------------ | | 命名服务(Naming Service) | 基础功能,提供 “名称 - 对象” 的映射(如 RMI Registry、DNS),支持通过名称查找对象。名称结构类似文件系统的 “路径”(如java:comp/env/jdbc/mydb)。 | | 目录服务(Directory Service) | 命名服务的扩展,除了 “名称 - 对象” 映射,还允许对象关联属性(如 LDAP 服务中,用户对象可关联邮箱、部门等属性),支持基于属性的查询。 | | Context(上下文) | JNDI 操作的核心接口,代表命名 / 目录服务中的一个 “命名空间节点”(类似文件系统的目录),提供资源的绑定(bind)、查找(lookup)、解绑(unbind)等核心方法。最常用的是InitialContext(初始上下文,JNDI 操作的入口)。 | | Binding(绑定) | “名称” 与 “资源对象” 的映射关系(如将名称"rmi://localhost:1099/helloService"绑定到一个 RMI 远程对象)。 | | Reference(引用) | 当资源对象不在本地时,JNDI 返回的 “间接引用”,包含对象的类名、工厂类(用于创建对象的类)、工厂类位置(如 URL)等信息。客户端通过 Reference 可加载并实例化目标对象。 | ## 工作流程 JNDI 的使用流程可概括为 “服务端绑定资源” 和 “客户端查找资源” 两步。 ### 服务端 服务端绑定资源到命名服务中: - 启动命名服务(如:RMI Registry、LDAP 服务器); - 创建资源对象(如:数据库资源池、RMI远程对象); - 通过Context.bind(String name, Object obj)将资源与名称绑定(如"jdbc/mydb"绑定到连接池)。 ### 客户端 客户端通过名称查找资源: - 配置InitialContext参数(指定命名服务类型和地址,如rmi://localhost:1099); - 创建InitialContext实例,调用lookup(String name)传入名称,获取资源对象; - 使用资源对象(如调用远程方法、获取数据库连接)。 ## 代码示例 通过 JNDI 访问 RMI 远程对象。 ### 服务端 绑定 RMI 远程对象到 JNDI ```java import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import javax.naming.Context; import javax.naming.InitialContext; import java.util.Hashtable; // 远程接口和实现类定义(同RMI示例) interface HelloService extends java.rmi.Remote { String sayHello() throws java.rmi.RemoteException; } class HelloServiceImpl extends java.rmi.server.UnicastRemoteObject implements HelloService { protected HelloServiceImpl() throws java.rmi.RemoteException {} @Override public String sayHello() { return "Hello JNDI"; } } public class JndiServer { public static void main(String[] args) throws Exception { // 启动RMI Registry(作为命名服务,端口1099) LocateRegistry.createRegistry(1099); // 创建远程对象 HelloService service = new HelloServiceImpl(); // 配置JNDI初始上下文(指定RMI命名服务) Hashtable<String, String> env = new Hashtable<>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory"); env.put(Context.PROVIDER_URL, "rmi://localhost:1099"); // 绑定对象到名称"helloService" Context ctx = new InitialContext(env); ctx.bind("helloService", service); System.out.println("服务绑定完成:名称=helloService"); } } ``` ### 客户端 通过 JNDI 查找并调用。 ```java import javax.naming.Context; import javax.naming.InitialContext; import java.util.Hashtable; public class JndiClient { public static void main(String[] args) throws Exception { // 配置JNDI初始上下文(与服务端一致) Hashtable<String, String> env = new Hashtable<>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory"); env.put(Context.PROVIDER_URL, "rmi://localhost:1099"); // 查找名称"helloService"对应的远程对象 Context ctx = new InitialContext(env); HelloService service = (HelloService) ctx.lookup("helloService"); // 调用远程方法 System.out.println(service.sayHello()); // 输出:Hello JNDI } } ```
毛林
2025年10月28日 10:39
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码