第三章 通过DirContextAdapter进行简单的属性访问及操作
3.1介绍
一个鲜为人知的可能被低估的Java Ldap Api DirContextAdapter 可以去创建一个context,它被很少用的原因是实现它需要创建一个Dircontext实例,Spring Ldap弥补了它的不足:一个默认的DirContext实现称作DirContextAdapter,与之相对应的DirObjectFactory的实现称作DefaultDirObjectFactory,同时使用DefaultDirObjectFactory,DirContextAdapter将变得非常实用。
3.2 使用ContextMapper搜索和查找
通常DefaultDirObjectFactory是注册在ContextSource中,这意味着每当在Ldap树中发现Context,它的属性和唯一Dn将用于构建一个DirContextAdapter,这将使我们用
ContextMapper去转换查询到的值而不是AttributeMapper。
例 3.1 使用ContextMapper查询
packagecom.example.dao;
publicclassPersonDaoImplimplementsPersonDao{
...
privatestaticclassPersonContextMapperimplementsContextMapper{
publicObjectmapFromContext(Objectctx){
DirContextAdaptercontext=(DirContextAdapter)ctx;
Personp=newPerson();
p.setFullName(context.getStringAttribute("cn"));
p.setLastName(context.getStringAttribute("sn"));
p.setDescription(context.getStringAttribute("description"));
returnp;
}
}
publicPersonfindByPrimaryKey(
Stringname,Stringcompany,Stringcountry){
Namedn=buildDn(name,company,country);
returnldapTemplate.lookup(dn, newPersonContextMapper());
}
}
上面的代码展示了我们可以直接通过名字查找属性,而不需要Attributes 和 BasicAttribute ,这在我们面对多个属性值的时候非常有用。取得多属性通常我们要使用
NamingEnumeration循环,从attrbutes得到值。但是DirContextAdapter可以帮助我们做到这一点,使用getStringAttributes()或者getObjectAttributes()方法
例3.2 :使用getStringAttributes()取得属性的多个值
privatestaticclassPersonContextMapperimplementsContextMapper{
publicObjectmapFromContext(Objectctx){
DirContextAdaptercontext=(DirContextAdapter)ctx;
Personp=newPerson();
p.setFullName(context.getStringAttribute("cn"));
p.setLastName(context.getStringAttribute("sn"));
p.setDescription(context.getStringAttribute("description"));
//TheroleNamespropertyofPersonisanStringarray
p.setRoleNames(context.getStringAttributes("roleNames"));
returnp;
}
}
3.2.1.The AbstractContextMapper
SpringLDAP提供了一个ContextMapper的抽象类AbstractContextMapper,它将提供构建好的DirContexOperations参数,上面的PersonContextMapper可以重写如下:
例3.3 使用AbstractContextMapper
privatestaticclassPersonContextMapper extendsAbstractContextMapper {
publicObject doMapFromContext(DirContextOperationsctx){
Personp=newPerson();
p.setFullName(context.getStringAttribute("cn"));
p.setLastName(context.getStringAttribute("sn"));
p.setDescription(context.getStringAttribute("description"));
returnp;
}
}0
3.3使用DirContextAdapter绑定和修改
相对于提取数据,DirContextAdapter在绑定和修改数据时隐藏属性细节方面的效率更高
3.3.1 绑定
这是一个改进的创建方法,请对照2.4.1的实现方式
packagecom.example.dao;
publicclassPersonDaoImplimplementsPersonDao{
...
publicvoidcreate(Personp){
Namedn=buildDn(p);
DirContextAdaptercontext=newDirContextAdapter(dn);
context.setAttributeValues("objectclass",newString[]{"top","pers
context.setAttributeValue("cn",p.getFullname());
context.setAttributeValue("sn",p.getLastname());
context.setAttributeValue("description",p.getDescription());
ldapTemplate.bind(context);
}
}
注意,这里DirContextAdapter作为第二个参数绑定(?),没有第三个参数,没有使用任何attributes
另外注意的是setAttributeValues()方法参数ObjectClass有两个值,如同取属性值一样麻烦,构建多值属性是繁琐和冗长的,你可以使用setAttributeValues()一次性完成它。
3.3.2 修改
反绑定代码和例3.4 几乎相同,“Bindingusing DirContextAdapter” 除了需要重新绑定。正如我们看到的2.5.2 。更合理的方法是用ModificationItem包含你想要做的操作,这将由你来决定在LdapTree中要操作的数据,而且DirContextAdapter可以帮助你,DirContextAdapter可以更好保持修改的属性,下面示例展示了这一功能
例3.5 使用DirContextAdapter修改
packagecom.example.dao;
publicclassPersonDaoImplimplementsPersonDao{
...
publicvoidupdate(Personp){
Namedn=buildDn(p);
DirContextOperationscontext=ldapTemplate.lookupContext(dn);
context.setAttributeValues("objectclass",newString[]{"top","person"});
context.setAttributeValue("cn",p.getFullname());
context.setAttributeValue("sn",p.getLastname());
context.setAttributeValue("description",p.getDescription());
ldapTemplate.modifyAttributes(context);
}
}
当ldapTemplate.lookup()操作没有返回值时将返回一个DirContextAdapter实例,虽然返回了一个对象,但更好的方法是自动强制返回一个DirContextOperations
(DirContextAdapter的实现方法)
细心的读者可能看来我们的create 和update方法中存在着重复,如果在同一类中,可以提取为一个单独的方法
例3.6 用DirContextAdapter绑定和修改
packagecom.example.dao;
publicclassPersonDaoImplimplementsPersonDao{
privateLdapTemplateldapTemplate;
...
publicvoidcreate(Personp){
Namedn=buildDn(p);
DirContextAdaptercontext=newDirContextAdapter(dn);
mapToContext(p,context);
ldapTemplate.bind(context);
}
publicvoidupdate(Personp){
Namedn=buildDn(p);
DirContextOperationscontext=ldapTemplate.lookupContext(dn);
mapToContext(person,context);
ldapTemplate.modifyAttributes(context);
}
protectedvoidmapToContext(Personp,DirContextOperationscontext){
context.setAttributeValues("objectclass",newString[]{"top","person"});
context.setAttributeValue("cn",p.getFullName());
context.setAttributeValue("sn",p.getLastName());
context.setAttributeValue("description",p.getDescription());
}
}
3.4 一个完整的PersonDao类
例3.7
packagecom.example.dao;
importjava.util.List;
importjavax.naming.Name;
importjavax.naming.NamingException;
importjavax.naming.directory.Attributes;
importorg.springframework.ldap.core.AttributesMapper;
importorg.springframework.ldap.core.ContextMapper;
importorg.springframework.ldap.core.LdapTemplate;
importorg.springframework.ldap.core.DirContextAdapter;
importorg.springframework.ldap.core.support.DistinguishedName;
importorg.springframework.ldap.filter.AndFilter;
importorg.springframework.ldap.filter.EqualsFilter;
importorg.springframework.ldap.filter.WhitespaceWildcardsFilter;
publicclassPersonDaoImplimplementsPersonDao{
privateLdapTemplateldapTemplate;
publicvoidsetLdapTemplate(LdapTemplateldapTemplate){
this.ldapTemplate=ldapTemplate;
}
publicvoidcreate(Personperson){
DirContextAdaptercontext=newDirContextAdapter(buildDn(person));
mapToContext(person,context);
ldapTemplate.bind(context);
}
publicvoidupdate(Personperson){
Namedn=buildDn(person);
DirContextOperationscontext=ldapTemplate.lookupContext(dn);
mapToContext(person,context);
ldapTemplate.modifyAttributes(context);
}
publicvoiddelete(Personperson){
ldapTemplate.unbind(buildDn(person));
}
publicPersonfindByPrimaryKey(Stringname,Stringcompany,Stringcountry){
Namedn=buildDn(name,company,country);
return(Person)ldapTemplate.lookup(dn,getContextMapper());
}
publicListfindByName(Stringname){
AndFilterfilter=newAndFilter();
filter.and(newEqualsFilter("objectclass","person")).and(newWhitespaceWildcardsFilter("cn",name));
returnldapTemplate.search(DistinguishedName.EMPTY_PATH,filter.encode(),getContextMapper());
}
publicListfindAll(){
EqualsFilterfilter=newEqualsFilter("objectclass","person");
returnldapTemplate.search(DistinguishedName.EMPTY_PATH,filter.encode(),getContextMapper());
}
protectedContextMappergetContextMapper(){
returnnewPersonContextMapper();
}
protectedNamebuildDn(Personperson){
returnbuildDn(person.getFullname(),person.getCompany(),person.getCountry());
}
protectedNamebuildDn(Stringfullname,Stringcompany,Stringcountry){
DistinguishedNamedn=newDistinguishedName();
dn.add("c",country);
dn.add("ou",company);
dn.add("cn",fullname);
returndn;
}
protectedvoidmapToContext(Personperson,DirContextOperationscontext){
context.setAttributeValues("objectclass",newString[]{"top","person"});
context.setAttributeValue("cn",person.getFullName());
context.setAttributeValue("sn",person.getLastName());
context.setAttributeValue("description",person.getDescription());
}
privatestaticclassPersonContextMapperextendsAbstractContextMapper{
publicObjectdoMapFromContext(DirContextOperationscontext){
Personperson=newPerson();
person.setFullName(context.getStringAttribute("cn"));
person.setLastName(context.getStringAttribute("sn"));
person.setDescription(context.getStringAttribute("description"));
returnperson;
}
}
}
注意
在很多种情况下,唯一的DN用做构建对象时的重要属性,例如上面的代码中一个人的country,company 和fullname都用到DN,这就意味着你要在LdapTree中找到Entry,然后才能用rename()去更新属性值。如果你要保持不变的话,可以禁止用户修改属性或者rename()它
分享到:
相关推荐
### Spring LDAP 参考文档详解 #### 前言 Spring LDAP 是一款为简化 LDAP (Lightweight Directory Access Protocol) 操作而设计的框架。它基于 Spring 框架,利用了 Spring 的强大功能来实现对 LDAP 目录的访问、...
由于提供的文件内容是关于Spring Security的参考资料,接下来将详细说明Spring Security 4.0.4.RELEASE版本中涉及的关键知识点。在展开知识点介绍之前,需要指出,由于原文件可能包含一些格式错误或 OCR 识别的问题...
根据给定的文件信息,以下是对“Spring-LDAP”参考文档的知识点总结与扩展: ### Spring-LDAP概述 Spring-LDAP是Spring框架的一部分,专注于提供与轻量级目录访问协议(LDAP)集成的功能。它简化了开发人员在Java...
2. `spring-ldap-reference.pdf`:这个文件很可能是 Spring LDAP 的官方参考文档,包含了框架的所有类、接口和方法的详细介绍,以及示例代码。通过阅读此文档,你可以深入理解 Spring LDAP 的工作原理,学习如何配置...
- **LDAP (spring-security-ldap.jar)**:提供 LDAP 认证和授权支持。 - **ACL (spring-security-acl.jar)**:提供了基于访问控制列表 (ACL) 的权限管理。 - **CAS (spring-security-cas.jar)**:支持使用 CAS 单点...
- LDAP (`spring-security-ldap.jar`):提供 LDAP 集成支持。 - ACL (`spring-security-acl.jar`):提供基于权限的访问控制功能。 - CAS (`spring-security-cas.jar`):提供对 CAS 协议的支持。 - OpenID (`...
### Spring Security 参考文档概览 #### 一、引言与基础知识 ##### 1.1 什么是 Spring Security? Spring Security 是一个强大的、高度可定制的身份验证和访问控制框架。它为应用程序提供了一种机制来保护自身免...
### Spring Security Reference中文版知识点概览 #### 一、Spring Security 概述 - **Spring Security** 是一个强大的和高度可定制的身份验证和访问控制框架。它为基于Spring的应用提供了声明式的安全服务。 ####...
标题:springsecurity3.1.pdf 描述:springsecurity3.1.pdf 标签:spring security3.1 部分内容:SpringSecurity Reference Documentation by Ben Alex and Luke Taylor 3.1.4.RELEASE **一、Spring Security 3.1...
首先,"Apache_Shiro_reference(中文版).pdf"是Shiro的官方中文参考手册。这个文档详细介绍了Shiro的各种组件和API,包括核心概念如Subject、Realms、Caches等,以及认证、授权、会话管理和密码策略等具体功能。通过...
`Reference_Guide_en-US.pdf`是关于JBoss Portal全面技术细节的参考文档,包括API详解、配置选项、系统架构等深入内容,适合开发者和高级用户查阅。 **8. 用户指南** `User_Guide_en-US.pdf`可能专注于用户界面和...