1. 概要

これは、JAXB(Java Architecture for XML Binding)の入門チュートリアルです。

最初に、JavaオブジェクトをXMLに、またはその逆に変換する方法を示します。

次に、JAXB-2 Mavenプラグインを使用して、XMLスキーマからJavaクラスを生成することに焦点を当てます。

2. JAXBの概要

JAXBは、JavaオブジェクトをXMLにマーシャリング(書き込み)し、XMLをオブジェクトにアンマーシャリング(読み取り)するための高速で便利な方法を提供します。 これは、Javaアノテーションを使用してXML要素と属性をJavaフィールドとプロパティにマップするバインディングフレームワークをサポートします。

JAXB-2 Mavenプラグインは、その作業のほとんどを、JDKが提供する2つのツールXJCおよびSchemagenのいずれかに委任します。

3. JAXBアノテーション

JAXBは、Javaアノテーションを使用して、生成されたクラスに追加情報を追加します。 このようなアノテーションを既存のJavaクラスに追加すると、JAXBランタイム用にそれらが準備されます。

まず、マーシャリングとアンマーシャリングを説明するための単純なJavaオブジェクトを作成しましょう。

@XmlRootElement(name = "book")
@XmlType(propOrder = { "id", "name", "date" })
public class Book {
    private Long id;
    private String name;
    private String author;
    private Date date;

    @XmlAttribute
    public void setId(Long id) {
        this.id = id;
    }

    @XmlElement(name = "title")
    public void setName(String name) {
        this.name = name;
    }

    @XmlTransient
    public void setAuthor(String author) {
        this.author = author;
    }
    
    // constructor, getters and setters
}

上記のクラスには、次のアノテーションが含まれています。

  • @XmlRootElement:T ルートXML要素の名前はクラス名から派生します。また、name属性を使用してXMLのルート要素の名前を指定することもできます。
  • @XmlType :フィールドがXMLファイルに書き込まれる順序を定義します
  • @XmlElement :使用される実際のXML要素名を定義します
  • @XmlAttribute:idフィールドが要素ではなく属性としてマップされることを定義します
  • @XmlTransient:XMLに含めたくないフィールドに注釈を付けます

JAXBアノテーションの詳細については、このリンクを確認してください。

4.4。 マーシャリング–JavaオブジェクトのXMLへの変換

マーシャリングにより、クライアントアプリケーションはJAXBから派生したJavaオブジェクトツリーをXMLデータに変換できます。 デフォルトでは、MarshallerはXMLデータを生成するときにUTF-8エンコーディングを使用します。 次に、JavaオブジェクトからXMLファイルを生成します。

JAXBContext を使用して簡単なプログラムを作成しましょう。これは、JAXBバインディングフレームワーク操作を実装するために必要なXML/Javaバインディング情報を管理するための抽象化を提供します。

public void marshal() throws JAXBException, IOException {
    Book book = new Book();
    book.setId(1L);
    book.setName("Book1");
    book.setAuthor("Author1");
    book.setDate(new Date());

    JAXBContext context = JAXBContext.newInstance(Book.class);
    Marshaller mar= context.createMarshaller();
    mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    mar.marshal(book, new File("./book.xml"));
}

javax.xml.bind.JAXBContext クラスは、JAXBAPIへのクライアントのエントリポイントを提供します。 デフォルトでは、JAXBはXMLドキュメントをフォーマットしません。 これにより、スペースが節約され、空白が誤って重要であると解釈されるのを防ぐことができます。

JAXBで出力をフォーマットするには、MarshallerMarshaller.JAXB_FORMATTED_OUTPUTプロパティをtrueに設定するだけです。 marshalメソッドは、オブジェクトと出力ファイルを使用して、生成されたXMLをパラメーターとして保管します。

上記のコードを実行すると、 book.xml の結果をチェックして、JavaオブジェクトがXMLデータに正常に変換されたことを確認できます。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<book id="1">
    <title>Book1</title>
    <date>2016-11-12T11:25:12.227+07:00</date>
</book>

5. アンマーシャリング–XMLをJavaオブジェクトに変換する

アンマーシャリングにより、クライアントアプリケーションはXMLデータをJAXBから派生したJavaオブジェクトに変換できます。

JAXB Unmarshaller を使用して、book.xmlをJavaオブジェクトにアンマーシャリングしてみましょう。

public Book unmarshall() throws JAXBException, IOException {
    JAXBContext context = JAXBContext.newInstance(Book.class);
    return (Book) context.createUnmarshaller()
      .unmarshal(new FileReader("./book.xml"));
}

上記のコードを実行すると、コンソール出力をチェックして、XMLデータがJavaオブジェクトに正常に変換されたことを確認できます。

Book [id=1, name=Book1, author=null, date=Sat Nov 12 11:38:18 ICT 2016]

6.6。 複雑なデータ型

JAXBで直接利用できない可能性のある複雑なデータ型を処理する場合、特定の型を管理する方法をJAXBに示すアダプターを作成できます。

これを行うには、JAXBの XmlAdapter を使用して、マップできないクラスをJAXBが処理できるものに変換するカスタムコードを定義します。 @XmlJavaTypeAdapter アノテーションは、カスタムマーシャリング用にXmlAdapterクラスを拡張するアダプターを使用します。

マーシャリング時に日付形式を指定するアダプターを作成しましょう。

public class DateAdapter extends XmlAdapter<String, Date> {

    private static final ThreadLocal<DateFormat> dateFormat 
      = new ThreadLocal<DateFormat>() {

        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };

    @Override
    public Date unmarshal(String v) throws Exception {
        return dateFormat.get().parse(v);
    }

    @Override
    public String marshal(Date v) throws Exception {
        return dateFormat.get().format(v);
    }
}

日付形式yyyy-MM-ddHH:mm:ss を使用して、マーシャリング時にDateStringに変換し、ThreadLocalを作成します。 DateFormatスレッドセーフ。

DateAdapterBookに適用してみましょう。

@XmlRootElement(name = "book")
@XmlType(propOrder = { "id", "name", "date" })
public class Book {
    private Long id;
    private String name;
    private String author;
    private Date date;

    @XmlAttribute
    public void setId(Long id) {
        this.id = id;
    }

    @XmlTransient
    public void setAuthor(String author) {
        this.author = author;
    }

    @XmlElement(name = "title")
    public void setName(String name) {
        this.name = name;
    }

    @XmlJavaTypeAdapter(DateAdapter.class)
    public void setDate(Date date) {
        this.date = date;
    }
}

上記のコードを実行すると、 book.xml の結果をチェックして、新しい日付形式yyyy-MM-ddHHを使用してJavaオブジェクトをXMLに正常に変換したことを確認できます。 mm:ss

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<book id="1">
    <title>Book1</title>
    <date>2016-11-10 23:44:18</date>final
</book>

7. JAXB-2Mavenプラグイン

このプラグインは、Java API for XML Binding(JAXB)バージョン2+を使用して、XMLスキーマ(およびオプションでバインディングファイル)からJavaクラスを生成するか、注釈付きのJavaクラスからXMLスキーマを作成します。

Webサービスを構築するには、 ContractLastContractFirstの2つの基本的なアプローチがあることに注意してください。 これらのアプローチの詳細については、このリンクを確認してください。

7.1. XSDからのJavaクラスの生成

JAXB-2 Mavenプラグインは、XSD(XMLスキーマ定義)からJavaクラスを生成するJAXBバインディングコンパイラツールであるJDK提供のツールXJCを使用します。

単純なuser.xsdファイルを作成し、JAXB-2 Mavenプラグインを使用して、このXSDスキーマからJavaクラスを生成してみましょう。

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="/jaxb/gen"
    xmlns:userns="/jaxb/gen"
    elementFormDefault="qualified">

    <element name="userRequest" type="userns:UserRequest"></element>
    <element name="userResponse" type="userns:UserResponse"></element>

    <complexType name="UserRequest">
        <sequence>
            <element name="id" type="int" />
            <element name="name" type="string" />
        </sequence>
    </complexType>

    <complexType name="UserResponse">
        <sequence>
            <element name="id" type="int" />
            <element name="name" type="string" />
            <element name="gender" type="string" />
            <element name="created" type="dateTime" />
        </sequence>
    </complexType>
</schema>

JAXB-2Mavenプラグインを構成しましょう。

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <version>2.3</version>
    <executions>
        <execution>
            <id>xjc</id>
            <goals>
                <goal>xjc</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <xjbSources>
            <xjbSource>src/main/resources/global.xjb</xjbSource>
        </xjbSources>
        <sources>
            <source>src/main/resources/user.xsd</source>
        </sources>
        <outputDirectory>${basedir}/src/main/java</outputDirectory>
        <clearOutputDir>false</clearOutputDir>
    </configuration>
</plugin>

デフォルトでは、このプラグインはXSDファイルを src / main /xsdに配置します。 pom.xml のこのプラグインの構成セクションを適宜変更することで、XSDルックアップを構成できます。

また、デフォルトでは、これらのJavaクラスは target /generated-resources /jaxbフォルダーに生成されます。 プラグイン構成にoutputDirectory要素を追加することにより、出力ディレクトリを変更できます。 このディレクトリ内のファイルが消去されないように、値がfalseのclearOutputDir要素を追加することもできます。

さらに、デフォルトのバインディングルールをオーバーライドするグローバルJAXBバインディングを構成できます。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings version="2.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    jaxb:extensionBindingPrefixes="xjc">

    <jaxb:globalBindings>
        <xjc:simple />
        <xjc:serializable uid="-1" />
        <jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime"
            parse="javax.xml.bind.DatatypeConverter.parseDateTime"
            print="javax.xml.bind.DatatypeConverter.printDateTime" />
    </jaxb:globalBindings>
</jaxb:bindings>

上記のglobal.xjbは、dateTimeタイプをjava.util.Calendarタイプにオーバーライドします。

プロジェクトをビルドすると、 src / main /javaフォルダーとパッケージcom.baeldung.jaxb.genにクラスファイルが生成されます。

7.2. JavaからのXSDスキーマの生成

同じプラグインは、JDKが提供するツールSchemagenを使用します。 これは、JavaクラスからXSDスキーマを生成できるJAXBバインディングコンパイラツールです。 JavaクラスがXSDスキーマ候補に適格であるためには、クラスに@XmlTypeアノテーションが付けられている必要があります。

前の例のJavaクラスファイルを再利用して、プラグインを構成します。

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <version>2.3</version>
    <executions>
        <execution>
            <id>schemagen</id>
            <goals>
                <goal>schemagen</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <sources>
            <source>src/main/java/com/baeldung/jaxb/gen</source>
        </sources>
        <outputDirectory>src/main/resources</outputDirectory>
        <clearOutputDir>false</clearOutputDir>
        <transformSchemas>
            <transformSchema>
                <uri>/jaxb/gen</uri>
                <toPrefix>user</toPrefix>
                <toFile>user-gen.xsd</toFile>
            </transformSchema>
        </transformSchemas>
    </configuration>
</plugin>

デフォルトでは、JAXBは src / main / java の下のすべてのフォルダーを再帰的にスキャンして、注釈付きのJAXBクラスを探します。 プラグイン構成にsource要素を追加することにより、JAXB注釈付きクラスに別のsourceフォルダーを指定できます。

XSDスキーマの命名を担当するポストプロセッサであるtransformSchemasを登録することもできます。 これは、namespaceをJavaクラスの@XmlTypeの名前空間と照合することで機能します。

プロジェクトをビルドすると、user-gen.xsdファイルがsrc/ main /resourcesディレクトリに生成されます。

8. 結論

この記事では、JAXBの概要について説明しました。 詳細については、JAXBホームページを参照してください。

この記事のソースコードはGitHubにあります。