6.20.2016

Web Service - JAXB, что нужно знать, часть третья …



Осталось еще  несколько интересных вещей в JAXB, первое это тег @XmlSeeAlso(), он применяется при наследовании от абстракного класса или когда вы работаете с интерфейсами. Если вы задействуете тег в интерфейсе или абстрактном классе, то при этом вам не придется описывать все зависимости в JAXB  контексте, т.е. не нужно будет описывать его в методе при создании контекста JAXBContext.newInstance(…);. Давайте я вам все поясню на примере, напишем для начала наш абстрактный класс:

package com.vit.fly;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public abstract class Vit6 {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Потом можно написать множество классов которые наследуются от нашего абстракного класса Vit6.class, нам для примера хватит одного:

package com.vit.fly;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Vit7 extends Vit6 {
    @Override
    public void setName(String name) {
        super.setName(name);
    }
}

Далее нам нужно написать класс который использует наш абстрактый класс Vit6.class:

package com.vit.fly;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;

@XmlRootElement()
@XmlSeeAlso(value = {Vit7.class})
public class Vit8 {
  private Vit6 v;

    public Vit6 getV() {
        return v;
    }

    public void setV(Vit6 v) {
        this.v = v;
    }
}

В аннотации @XmlSeeAlso(value = {Vit7.class}) мы говорим, что можно использовать реализацию класса Vit7.class, замете что  он у нас не описан в контексте JAXBContext.newInstance(Vit8.class). взглянем на программу:

public class MainVit1 {
    static public void main(String args[]) {
        Vit6 vit6 = new Vit7(); vit6.setName("Lopanov");
        Vit8 vit8 = new Vit8(); vit8.setV(vit6);
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(Vit8.class);
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);
            marshaller.marshal(vit8, System.out);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}

Смотрим на вывод программы:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<vit8>
    <v xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="vit7">
        <name>Lopanov</name>
    </v>
</vit8>

Давайте познакомимся с двумя аннотациями которые позволяют нам работать с бинарнами данными, первая из них это аннотация @XmlInlineBinaryData(), которая применяется к массиву байт и он кодируется в  xml файле как тип xs:base64Binary. Вторая аннотация @XmlMimeType(value = "image/jpeg") применяется к типам данных java.awt.Image или javax.xml.transform.Source, которые так же приобразуются к типу  xs:base64Binary.  Расмотрим простой пример, в котором одно поле представляет из себя  массив байт. Создадим класс Vit9 с полем типа byte[]:

package com.vit.fly;

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Vit9 {
    //@XmlMimeType(value = "image/jpeg")
    @XmlInlineBinaryData
    private byte[] data;

    public byte[] getData() {
        return data;
    }

    public void setData(byte[] data) {
        this.data = data;
    }
}

Напишем программу для запуска нашего примера, закодируем фразу "Hello JAXB" в байты:

package com.vit.fly;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

public class MainVit3 {
    public static void main(String args[]) throws JAXBException {
        Vit9 Data = new Vit9();
        Data.setData("Hello JAXB".getBytes());  //encoded in xs:base64Binary by default
        JAXBContext context = JAXBContext.newInstance(Vit9.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        m.marshal(Data, System.out);
    }
}

В итоге получим в выводе base64 закодированное значение фразы  "Hello JAXB":

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<vit9>
    <data>SGVsbG8gSkFYQg==</data>
</vit9>

По умолчанию если поле имеет null  значение, то оно не отображается в xml файле посредством тега, для вывода пустого тега нужно в аннотации выставить значение nillable в true. И так расмотрим предыдуший пример и закоментируем в программе строчку  Data.setData("Hello JAXB".getBytes()):

import javax.xml.bind.Marshaller;

public class MainVit3 {
    public static void main(String args[]) throws JAXBException {
        Vit9 Data = new Vit9();
       //Data.setData("Hello JAXB".getBytes());  //encoded in xs:base64Binary by default
        JAXBContext context = JAXBContext.newInstance(Vit9.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        m.marshal(Data, System.out);
    }
}

Получим вывод:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<vit9/>

Добавим в классе Vit9 аннотацию @XmlElement(nillable = true) :

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Vit9 {
    @XmlInlineBinaryData
    @XmlElement(nillable = true)
    private byte[] data;
    …..
}

Получим вывод тега, даже если значение null:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<vit9>
    <data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</vit9>


Комментариев нет:

Отправить комментарий