物件目錄對映 (ODM)
物件關係對映框架(如 Hibernate 和 JPA)使開發人員能夠使用註解將關係資料庫表對映到 Java 物件。Spring LDAP 專案透過 LdapOperations 中的許多方法提供了類似的 LDAP 目錄對映能力
-
<T> T findByDn(Name dn, Class<T> clazz) -
<T> T findOne(LdapQuery query, Class<T> clazz) -
<T> List<T> find(LdapQuery query, Class<T> clazz) -
<T> List<T> findAll(Class<T> clazz) -
<T> List<T> findAll(Name base, SearchControls searchControls, Class<T> clazz) -
<T> List<T> findAll(Name base, Filter filter, SearchControls searchControls, Class<T> clazz) -
void create(Object entry) -
void update(Object entry) -
void delete(Object entry)
配置
LdapTemplate 構造了一個預設的 ObjectDirectoryMapper,通常無需額外配置。
使用 Boot 的轉換器
ObjectDirectoryMapper 支援 ConversionService,它允許您指定自定義 Converter 用於 Java 和 LDAP 之間的對映。
當您使用 Spring Boot 時,您可以像往常一樣釋出一個 Converter,Boot 提供的 ObjectDirectoryMapper bean 將會識別它們。
不使用 Boot 的轉換器
您還可以透過匯入 ObjectDirectoryMapperConfiguration 來將 ObjectDirectoryMapper 作為 @Bean 提供,如下所示
@Import(ObjectDirectoryMapperConfiguration.class)
@Configuration
public class LdapConfig {
// ...
}
然後您可以將其提供給您的 LdapTemplate 例項,如下所示
@Bean
LdapTemplate ldapTemplate(ContextSource contextSource, ObjectDirectoryMapper odm) {
LdapTemplate ldap = new LdapTemplate(contextSource);
ldap.setObjectDirectoryMapper(odm);
return ldap;
}
這樣做將使 Spring LDAP 使用您配置的 Converter 例項。
註解
使用物件對映方法管理的實體類需要使用 org.springframework.ldap.odm.annotations 包中的註解進行標註。可用的註解有
-
@Entry:類級別註解,指示實體對映到的objectClass定義。(必填) -
@Id:指示實體 DN。宣告此屬性的欄位必須是javax.naming.Name類的派生類。(必填) -
@Attribute:指示目錄屬性到物件類欄位的對映。 -
@DnAttribute:指示 DN 屬性到物件類欄位的對映。 -
@Transient:指示該欄位不持久化,應被OdmManager忽略。
@Entry 和 @Id 註解必須在託管類上宣告。@Entry 用於指定實體對映到哪些物件類,以及(可選)由該類表示的 LDAP 條目的目錄根。所有對映欄位的物件類都必須宣告。請注意,在建立託管類的新條目時,只使用已宣告的物件類。
為了使目錄條目被認為是與託管實體匹配,目錄條目宣告的所有物件類都必須由 @Entry 註解宣告。例如,假設您的 LDAP 樹中有具有以下物件類的條目:inetOrgPerson,organizationalPerson,person,top。如果您只對更改 person 物件類中定義的屬性感興趣,您可以用 @Entry(objectClasses = { "person", "top" }) 註解您的 @Entry。但是,如果您想管理 inetOrgPerson 物件類中定義的屬性,則需要使用以下內容:@Entry(objectClasses = { "inetOrgPerson", "organizationalPerson", "person", "top" })。
所有實體欄位都透過其欄位名對映到 LDAP 屬性。其餘註解 — @Id、@Attribute、@Transient 和 @DnAttribute — 影響該對映的發生方式。
首先,@Id 註解將條目的專有名稱對映到欄位。該欄位必須是 javax.naming.Name 的例項。
其次,@Attribute 註解將實體欄位對映到 LDAP 屬性。當屬性名與欄位名不同時,這非常方便。要使用 @Attribute,您必須宣告欄位對映到的屬性名稱。可選地,您還可以透過包含 LDAP 屬性的語法 OID 來保證精確匹配。最後,@Attribute 還提供了型別宣告,它允許您指示 LDAP JNDI 提供程式是將屬性視為二進位制還是基於字串。
第三,@Transient 註解指示給定實體欄位不對映到 LDAP 屬性。
最後,@DnAttribute 註解還將實體欄位對映到條目專有名稱的元件。
考慮一個具有以下註解的類
@DnAttribute(name="uid")
String uid;
以及如下所示的 DN
uid=carla,dc=springframework,dc=org
那麼 Spring LDAP 將使用 uid=carla 填充 uid,而不是尋找 uid 屬性。
Only fields of type `String` can be annotated with `@DnAttribute`. Other types are not supported.
您也可以如下提供一個索引
@DnAttribute(index=1)
String uid;
@DnAttribute(index=0)
String department;
這對於具有多個元件的 DN 很有用
uid=carla,department=engineering,dc=springframework,dc=org
使用 index 還允許 Spring LDAP 在建立或定位實體進行更新或刪除時為您計算 DN。對於更新場景,如果作為專有名稱一部分的屬性已更改,這還會自動處理樹中條目的移動。
Note that while both attributes are present on `@DnAttribute`, if `index` is specified, then `name` is ignored.
請記住,預設情況下所有欄位都對映到 LDAP 屬性。@DnAttribute 不會改變這一點;換句話說,用 @DnAttribute 註解的欄位也將對映到 LDAP 屬性,除非您還用 @Transient 註解該欄位。 |
執行
當所有元件都正確配置和註解後,LdapTemplate 的物件對映方法可以如下使用
@Entry(objectClasses = { "person", "top" }, base="ou=someOu")
public class Person {
@Id
private Name dn;
@Attribute(name="cn")
@DnAttribute(value="cn", index=1)
private String fullName;
// No @Attribute annotation means this will be bound to the LDAP attribute
// with the same value
private String description;
@DnAttribute(value="ou", index=0)
@Transient
private String company;
@Transient
private String someUnmappedField;
// ...more attributes below
}
public class OdmPersonRepo {
@Autowired
private LdapTemplate ldapTemplate;
public Person create(Person person) {
ldapTemplate.create(person);
return person;
}
public Person findByUid(String uid) {
return ldapTemplate.findOne(query().where("uid").is(uid), Person.class);
}
public void update(Person person) {
ldapTemplate.update(person);
}
public void delete(Person person) {
ldapTemplate.delete(person);
}
public List<Person> findAll() {
return ldapTemplate.findAll(Person.class);
}
public List<Person> findByLastName(String lastName) {
return ldapTemplate.find(query().where("sn").is(lastName), Person.class);
}
public Stream<Person> streamFindByLastName(String lastName) {
return ldapTemplate.findStream(query().where("sn").is(lastName), Person.class);
}
}
ODM 和作為屬性值的專有名稱
LDAP 中的安全組通常包含一個多值屬性,其中每個值都是系統中使用者的專有名稱。處理這類屬性的困難在 DirContextAdapter 和作為屬性值的專有名稱 中討論。
ODM 也支援 javax.naming.Name 屬性值,使得組修改變得容易,如下例所示
@Entry(objectClasses = {"top", "groupOfUniqueNames"}, base = "cn=groups")
public class Group {
@Id
private Name dn;
@Attribute(name="cn")
@DnAttribute("cn")
private String name;
@Attribute(name="uniqueMember")
private Set<Name> members;
public Name getDn() {
return dn;
}
public void setDn(Name dn) {
this.dn = dn;
}
public Set<Name> getMembers() {
return members;
}
public void setMembers(Set<Name> members) {
this.members = members;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void addMember(Name member) {
members.add(member);
}
public void removeMember(Name member) {
members.remove(member);
}
}
當您透過使用 setMembers、addMember 和 removeMember 修改組成員,然後呼叫 ldapTemplate.update() 時,屬性修改是使用專有名稱相等性計算的,這意味著在判斷它們是否相等時,專有名稱的文字格式將被忽略。