首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

封裝 JNDI 操作 LDAP 服務的工具類(二):LdapConnectionFactory 連線工廠實作

     編輯:Java 相關知識

核心職責

LdapConnectionFactory 為單例工廠(私有建構子),提供兩類靜態方法:

  • 從連線池取得 DirContext(指定池名)
  • 直接建立新 DirContext(無池名)
  • 統一關閉 DirContext 並處理例外

完整原始碼解析

package com.common.ldapconnection;

import java.util.Properties;
import javax.naming.*;
import javax.naming.directory.*;
import org.apache.log4j.Logger;
import org.apache.commons.lang.StringUtils;

public class LdapConnectionFactory {
    private static final Logger log = Logger.getLogger(LdapConnectionFactory.class.getName());

    private LdapConnectionFactory() {} // 防止實例化

    /** 從連線池取得 DirContext */
    public static DirContext getDirContext(String poolName, Env env) {
        log.debug("INTO getDirContext(pool)");
        try {
            Properties mEnv = buildEnvProps(env);
            mEnv.put("com.sun.jndi.ldap.connect.pool", "true"); // 啟用連線池
            // poolName 實際由上層透過 JNDI 名稱綁定管理,此處略過綁定邏輯
            DirContext ctx = new InitialDirContext(mEnv);
            log.debug("DirContext from pool created successfully");
            return ctx;
        } catch (NamingException ex) {
            log.error("Create DirContext from pool failed", ex);
            return null;
        }
    }

    /** 直接建立 DirContext(無連線池) */
    public static DirContext getDirContext(Env env) {
        log.debug("INTO getDirContext(direct)");
        try {
            Properties mEnv = buildEnvProps(env);
            DirContext ctx = new InitialDirContext(mEnv);
            log.debug("Direct DirContext created successfully");
            return ctx;
        } catch (NamingException ex) {
            log.error("Create direct DirContext failed", ex);
            return null;
        }
    }

    /** 共用屬性建構邏輯:DRY 原則 */
    private static Properties buildEnvProps(Env env) {
        Properties mEnv = new Properties();
        mEnv.put(Context.AUTHORITATIVE, "true");
        mEnv.put(Context.INITIAL_CONTEXT_FACTORY, env.factory);
        mEnv.put(Context.PROVIDER_URL, env.url);
        if (!StringUtils.isEmpty(env.timeOut)) {
            mEnv.put("com.sun.jndi.ldap.connect.timeout", env.timeOut);
        }
        mEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
        if (env != null && "ssl".equals(env.securityProtocol)) {
            mEnv.put(Context.SECURITY_PROTOCOL, "ssl");
            System.setProperty("javax.net.ssl.trustStore", env.sslTrustStore);
        }
        mEnv.put(Context.SECURITY_PRINCIPAL, env.adminUID);
        mEnv.put(Context.SECURITY_CREDENTIALS, env.adminPWD);
        return mEnv;
    }

    /** 安全關閉 DirContext */
    public static void closeDirContext(DirContext dirContext) {
        if (dirContext != null) {
            try {
                dirContext.close();
            } catch (Exception ex) {
                log.error("Failed to close DirContext", ex);
            }
        }
    }
}

關鍵技術點深度解析

1. 連線池啟用機制

設定 com.sun.jndi.ldap.connect.pool=true 即啟用 JDK 內建 LDAP 連線池。池參數(大小、逾時、驗證)可透過系統屬性 com.sun.jndi.ldap.connect.pool.* 調整。生產環境強烈建議啟用,大幅降低頻繁建立連線開銷。

2. SSL 信任庫設置陷阱

System.setProperty("javax.net.ssl.trustStore", ...) 為全 JVM 生效,若同一應用需連接不同 SSL LDAP 伺服器,需自行實作 SSLSocketFactory 而非依賴系統屬性。本工具類適用單一 LDAP 目標場景。

3. 例外處理策略

  • 建立連線失敗:記錄錯誤日誌,回傳 null,由呼叫端決定重試或拋出業務異常。
  • 關閉連線失敗:僅記錄錯誤,不拋出,避免影響正常業務流程。

4. 相依套件

  • commons-lang:StringUtils.isEmpty() 簡化空值檢查
  • log4j:企業級日誌標準

使用範例

Env env = new Env("com.sun.jndi.ldap.LdapCtxFactory",
                  "ldap://ldap.example.com:389",
                  "cn=admin,dc=example,dc=com", "password");

// 直連模式
DirContext ctx = LdapConnectionFactory.getDirContext(env);
try {
    // 業務操作...
} finally {
    LdapConnectionFactory.closeDirContext(ctx);
}

// 連線池模式(需配合 JNDI 資源配置)
DirContext pooledCtx = LdapConnectionFactory.getDirContext("myLdapPool", env);

下一篇將介紹核心業務操作類 LdapOperUtils:Context 增刪改、屬性管理、搜尋與認證功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved