# 操纵相对专有名称（RDN）

> 原文： [https://docs.oracle.com/javase/tutorial/jndi/newstuff/rdn.html](https://docs.oracle.com/javase/tutorial/jndi/newstuff/rdn.html)

类 [`javax.naming.ldap.Rdn`](https://docs.oracle.com/javase/8/docs/api/javax/naming/ldap/Rdn.html)表示 [RFC 2253](http://www.ietf.org/rfc/rfc2253.txt) 中指定的相对可分辨名称（RDN）。 RDN 代表 DN 的一个组成部分，如 [Manipulating LdapName](ldapname.html) 课程中所述。 RDN 由类型和值对组成。 RDN 的示例是：

*   `OU =太阳`
*   `OU =销售额+ CN = J.Smith` 。
    上面的例子显示了多值 RDN 的表示。

[`Rdn` ](https://docs.oracle.com/javase/8/docs/api/javax/naming/ldap/Rdn.html)类提供访问 RDN 的名称/值对的方法，获取其字符串表示，检索 [`属性`](https://docs.oracle.com/javase/8/docs/api/javax/naming/directory/Attributes.html) 查看，比较和确定 RDN 的相等性以及要转义和忽略 RDN 值部分的方法。

`Rdn` 类是不可变的。

## 构建一个 Rdn

如果 Rdn 是单个名称/值配对 RDN，则可以使用指定的名称和值对构造 Rdn。对于多值 RDN，您应该创建一个由所有名称/值对组成的属性集，并使用以 `Attributes` 作为参数的构造函数。您还可以从 [RFC 2253](http://www.ietf.org/rfc/rfc2253.txt) 中指定的字符串表示创建 Rdn。最后，您可以使用其复制构造函数克隆 Rdn。这是 [`example`](examples/RdnConstructors.java) ，它使用不同类型的构造函数创建 RDN。

```
        Rdn rdn1 = new Rdn("ou= Juicy\\, Fruit");
        System.out.println("rdn1:" + rdn1.toString());

        Rdn rdn2 = new Rdn(rdn1);
        System.out.println("rdn2:" + rdn2.toString());

        Attributes attrs = new BasicAttributes();
        attrs.put("ou", "Juicy, Fruit");
        attrs.put("cn", "Mango");
        Rdn rdn3 = new Rdn(attrs);
        System.out.println("rdn3:" + rdn3.toString());

        Rdn rdn4 = new Rdn("ou", "Juicy, Fruit");
        System.out.println("rdn4:" + rdn4.toString());

```

## 访问 RDN 的类型/值对

可以使用以下方法获得和 RDN 的类型/值：

[`getType（）`](https://docs.oracle.com/javase/8/docs/api/javax/naming/ldap/Rdn.html#getType--)
[`getValue（）`](https://docs.oracle.com/javase/8/docs/api/javax/naming/ldap/Rdn.html#getValue--)
[`toAttributes（）`](https://docs.oracle.com/javase/8/docs/api/javax/naming/ldap/Rdn.html#toAttributes--)

对于由单一类型/值对组成的 RDN， [`getType（）`](https://docs.oracle.com/javase/8/docs/api/javax/naming/ldap/Rdn.html#getType--) 方法返回类型和 [`getValue（）`](https://docs.oracle.com/javase/8/docs/api/javax/naming/ldap/Rdn.html#getValue--) method 返回 RDN 的值。方法 [`toAttributes（）`](https://docs.oracle.com/javase/8/docs/api/javax/naming/ldap/Rdn.html#toAttributes--) 返回类型/值对的属性视图。下面的 [`example`](examples/RdnGetters.java) 打印 RDN 的类型/值对。

```
        Attributes attrs = new BasicAttributes();
        attrs.put("o", "Yellow");
        attrs.put("cn", "Mango");

        // create a binary value for the RDN
        byte[] mangoJuice = new byte[6];
        for (int i = 0; i < mangoJuice.length; i++) {
            mangoJuice[i] = (byte) i;
        }
        attrs.put("ou", mangoJuice);
        Rdn rdn = new Rdn(attrs);

        System.out.println();
        System.out.println("size:" + rdn.size());
        System.out.println("getType(): " + rdn.getType());
        System.out.println("getValue(): " + rdn.getValue());

        // test toAttributes
        System.out.println();
        System.out.println("toAttributes(): " + rdn.toAttributes());

```

## 获取字符串表示

为了获得根据 [RFC 2253](http://www.ietf.org/rfc/rfc2253.txt) 中指定的语法格式化的 RDN 的字符串表示，您可以使用：

[`toString（）`](https://docs.oracle.com/javase/8/docs/api/javax/naming/ldap/Rdn.html#toString--)

当您使用带有 `String` 参数的 Rdn 构造函数时，您提供 RDN 的字符串表示形式，并返回一个 Rdn 实例。要执行相反的操作，即获取 Rdn 实例的字符串表示形式，请使用 toString（）。 toString（）的结果可以反馈给 Rdn 构造函数，以生成一个等于原始 Rdn 实例的 Rdn 实例。

这是 [`example`](examples/RdntoString.java) ：

```
Rdn rdn = new Rdn("cn=Juicy\\,Fruit");
String str = rdn.toString();
System.out.println(str);
Rdn rdn2 = new Rdn(str);
System.out.println(rdn.equals(rdn2));    // true

```

## 比较 RDN

以下方法可以比较 RDN：

[`等于（对象 Rdn）`](https://docs.oracle.com/javase/8/docs/api/javax/naming/ldap/Rdn.html#equals-Object-)
[`compareTo（对象 Rdn）`](https://docs.oracle.com/javase/8/docs/api/javax/naming/ldap/Rdn.html#compareTo-Object-)

您可以使用 compareTo（）对 Rdn 实例列表进行排序。 equals（）允许您确定两个 Rdns 在语法上是否相等。如果两个 Rdns 都具有相同（大小写完全匹配）的类型/值对，则它们是相等的。多值 RDN 中的组件顺序并不重要。

这是 [`example`](examples/CompareRdns.java) ：

```
        Rdn one = new Rdn("ou=Sales+cn=Bob");
        Rdn two = new Rdn("cn=Bob+ou=Sales");
        Rdn three = new Rdn("ou=Sales+cn=Bob+c=US");
        Rdn four = new Rdn("cn=lowercase");
        Rdn five = new Rdn("cn=LowerCASE");
        System.out.println(one.equals(two));    // true
        System.out.println(two.equals(three));  // false
        System.out.println(one.equals(three));  // false
        System.out.println(four.equals(five));  // true

```

## 特殊字符的逃避和失败

Rdn 类的最佳用途之一是当必须处理由特殊字符组成的 DN 时。它会自动处理转义和转义特殊字符。根据 [RFC 2253](http://www.ietf.org/rfc/rfc2253.txt) ，具有'\'（反斜杠），'，'（逗号），+（加号）等字符具有特定的语义。您可以在 RFC2253 中找到所有特殊字符的列表。当这些字符在 DN 中用作文字时，必须使用'\'（黑色）转义它们。

例如，考虑 RDN：`cn=Juicy, Fruit` Juicy 和 Fruit 之间出现的字符（逗号）是一个特殊字符，需要通过'\'（blackslash）进行转义。生成的语法格式化的 RDN 如下所示：`cn=Juicy\, Fruit`但是，根据 Java 语言字符串语法，'\'（反斜杠）字符本身是一个特殊字符，它需要再次使用'\'（反斜杠）进行转义。 Java 语言字符串格式和 [RFC 2253](http://www.ietf.org/rfc/rfc2253.txt) 都使用'\'（反斜杠）来转义特殊字符。因此，Java 格式的 RDN 字符串如下所示：`cn=Juicy\\, Fruit`请注意，上述格式规则仅适用于 Rdn 的值组件。 `Rdn` 类提供两种`静态`方法来处理 RDN 值的自动转义和转义：

[`escapeValue（）`](https://docs.oracle.com/javase/8/docs/api/javax/naming/ldap/Rdn.html#escapeValue--)
[`unescapeValue（）`](https://docs.oracle.com/javase/8/docs/api/javax/naming/ldap/Rdn.html#unescapeValue--)

下面的 [`example`](examples/EscapingDNs.java) 显示了如何获取 DN 的字符串表示，而不必处理处理 [RFC 2253](http://www.ietf.org/rfc/rfc2253.txt) 中定义的特殊字符的语法。

```
    // DN with ',' (comma)
    String unformatted = "Juicy, Fruit";
    String formatted = Rdn.escapeValue(unformatted);
    LdapName dn = new LdapName("cn=" + formatted);
    System.out.println("dn:" + dn);

    unformatted = "true+false";
    formatted = Rdn.escapeValue(unformatted); 
    dn = new LdapName("cn=" + formatted);
    System.out.println("dn:" + dn);

    // DN with a binary value as one one of its attribute value
    byte[] bytes = new byte[] {1, 2, 3, 4};
    formatted = Rdn.escapeValue(bytes);
    System.out.println("Orig val: " + bytes + "Escaped val: " + formatted);

```

类似地，使用静态 `unescapeValue（）`方法可以从格式化的值中获取原始字符串。 [`Here`](examples/UnescapingValues.java) 是用于检索原始值的示例。

```
    // DN with ',' (comma)
    String unformatted = "Juicy, Fruit";
    String formatted = Rdn.escapeValue(unformatted);
    System.out.println("Formatted:" + formatted);
    Object original = Rdn.unescapeValue(formatted);
    System.out.println("Original:" +  original);  

    // DN with a '+' (plus)
    unformatted = "true+false";
    formatted = Rdn.escapeValue(unformatted); 
    System.out.println("Formatted:" + formatted);
    original = Rdn.unescapeValue(formatted);
    System.out.println("Original:" +  original);  

    // DN with a binary value as one one of its attribute value
    byte[] bytes = new byte[] {1, 2, 3, 4};
    formatted = Rdn.escapeValue(bytes);
    System.out.println("Formatted:" + formatted);
    original = Rdn.unescapeValue(formatted);
    System.out.println("Original:" +  original);  

```