接續上篇(存儲篇),本文深入講解搜索、反序列化、編組對象解編、更新及統一封裝類 LDAP4JavaObjects 的實現。
關鍵步驟:
uid=Alice + objectClass=personou=users(而非根 ou=system)DirContext.search(context, attrs) 返回 NamingEnumerationSearchResult,獲取 RDN (getName()) 與屬性集 (getAttributes())注意:JNDI 搜索參數中 uid 被視為屬性處理,實際為 RDN 組件。
將搜索屬性從 uid 改為 cn。關鍵點:cn 屬性定義了 SUBSTR 匹配規則 caseIgnoreMatch,支援不區分大小寫的子串匹配。搜 "alice" 會匹配 "Alice Smith"、"Bob Alice" 等。
需在用戶條目子樹中查找 MessagingPreferences 對象:
uid=alice,ou=users)uid=alice,ou=users,ou=systemSearchControls:setReturningObjFlag(true) + SUBTREE_SCOPE(|(javaClassName=MessagingPreferences)(javaClassName=ShippingPreferences))search(ctx, filter, ctls)SearchResult.getObject() → 類型檢查轉換與應用 6 流程相同,區別在:
(javaClassName=java.rmi.MarshalledObject)MarshalledObject.get() 獲得真實 Java 對象 → 再次類型檢查轉換// 1. 搜索獲取對象 (同應用 7)
MarshalledObject mObj = (MarshalledObject) sr1.getObject();
MessagingPreferences pref = (MessagingPreferences) mObj.get();
// 2. 修改業務數據
pref.setStyles("https://www.mystyles.com/preferences");
// 3. 關鍵:保留原屬性集合
Attributes attrs1 = sr1.getAttributes();
// 4. 重新綁定 (rebind 覆蓋現有條目)
String bindContext = entryRDN + "," + searchContext; // 完整 DN
ctx.rebind(bindContext, pref, attrs1);
rebind vs bind:rebind 會覆蓋同名條目,bind 衝突則拋異常。
整合存儲、搜索、更新、刪除核心邏輯,提供智能 writeToServer():
protected 方法,支援子類擴展業務邏輯searchFromServer() 統一搜索入口,自動填充對象狀態public class LDAP4JavaObjects {
// 配置屬性
protected String userID, commonName, javaObjectCN, initialContext;
protected Properties properties;
protected DirContext dirContext;
protected Object javaObject;
protected Attributes attributes;
// 核心操作
public void writeToServer(); // 智能存儲/更新
public void searchFromServer(String user, String object);
protected void store(...); // bind 新條目
protected void update(...); // rebind 更新
protected NamingEnumeration search(...); // 統一搜索邏輯
// ... setter/getter 輔助方法
}
LDAP4JavaObjects client = new LDAP4JavaObjects();
client.setPassword("secret");
client.setUserID("Alice");
client.setJavaObject(new MessagingPreferences());
client.setJavaObjectCN("preferences");
client.writeToServer(); // 自動判斷新增/更新