Oppheving av datoer ved bruk av JAXB

1. Introduksjon

I denne veiledningen, vi kommer til å se hvordan unmarshal datoobjekter med forskjellige formater bruker JAXB.

Først skal vi dekke standardformatet for skjemadato. Deretter vil vi utforske hvordan du bruker forskjellige formater. Vi får også se hvordan vi kan takle en felles utfordring som oppstår med disse teknikkene.

2. Skjema til Java Binding

Først, vi må forstå forholdet mellom XML Schema og Java datatypene. Spesielt er vi interessert i kartleggingen mellom et XML-skjema og Java-datoobjekter.

Ifølge Skjema til Java-kartlegging, det er tre skjemadatatyper som vi må ta i betraktning: xsd: dato, xsd: tid og xsd: dateTime. Som vi kan se, blir alle kartlagt til javax.xml.datatype.XMLGregorianCalendar.

Vi må også forstå standardformatene for disse XML-skjematypene. De xsd: dato og xsd: tid datatyper har “ÅÅÅÅ-MM-DD ” og “tt: mm: ss ” formater. De xsd: dateTime formatet er “ÅÅÅÅ-MM-DDThh: mm: ss ” hvor "T ” er en separator som indikerer starten på tidsseksjonen.

3. Bruke standard skjema datoformat

Vi skal bygge et eksempel på at unmarshals daterer objekter. La oss fokusere på xsd: dateTime datatype fordi det er et supersett av de andre typene.

La oss bruke en enkel XML-fil som beskriver en bok:

 Bok1 1979-10-21T03: 31: 12 

Vi vil kartlegge filen til tilsvarende Java Bok gjenstand:

@XmlRootElement (name = "book") public class Book {@XmlElement (name = "title", required = true) privat strengtittel; @XmlElement (navn = "publisert", obligatorisk = sann) privat XMLGregorianCalendar publisert; @ Override public String toString () {return "[title:" + title + "; publisert:" + published.toString () + "]"; }}

Til slutt må vi lage et klientprogram som konverterer XML-data til JAXB-avledede Java-objekter:

offentlig statisk bok unmarshalDates (InputStream inputFile) kaster JAXBException {JAXBContext jaxbContext = JAXBContext.newInstance (Book.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller (); return (Book) jaxbUnmarshaller.unmarshal (inputFile); }

I koden ovenfor har vi definert a JAXBContext som er inngangspunktet til JAXB API. Så har vi brukt en JAXB Unmarshaller på en inngangsstrøm for å lese objektet vårt:

Hvis vi kjører ovennevnte kode og skriver ut resultatet, får vi følgende Bok gjenstand:

[tittel: Book1; publisert: 1979-11-28T02: 31: 32]

Vi bør merke oss det, selv om standardkartleggingen for xsd: dateTime er den XMLGregorianCalendar, kunne vi også ha brukt de vanligste Java-typene: java.util.Date og java.util.Kalender, i henhold til JAXB brukerhåndbok.

4. Bruke et egendefinert datoformat

Ovennevnte eksempel fungerer fordi vi bruker standard skjemadatoformat, “ÅÅÅÅ-MM-DDThh: mm: ss”.

Men hva om vi vil bruke et annet format som “ÅÅÅÅ-MM-DD tt: mm: ss”, kvitte seg med “T” avgrense? Hvis vi skulle erstatte skilletegnet med et mellomromstegn i XML-filen, ville standard unmarshalling mislykkes.

4.1. Bygg en egendefinert XmlAdapter

For å kunne bruke et annet datoformat, må vi definere et XmlAdapter.

La oss også se hvordan vi kan kartlegge xsd: dateTime skriv til en java.util.Date objekt med vår skikk XmlAdapter:

public class DateAdapter utvider XmlAdapter {private static final String CUSTOM_FORMAT_STRING = "åååå-MM-dd HH: mm: ss"; @ Override public String marshal (Date v) {return new SimpleDateFormat (CUSTOM_FORMAT_STRING) .format (v); } @ Override public Date unmarshal (String v) kaster ParseException {returner nye SimpleDateFormat (CUSTOM_FORMAT_STRING) .parse (v); }}

I denne adapteren, vi har bruktSimpleDateFormat for å formatere datoen vår. Vi må være forsiktige som de SimpleDateFormat er ikke trådsikker. For å unngå at flere tråder opplever problemer med en delt SimpleDateFormat objekt, lager vi en ny hver gang vi trenger det.

4.2. De XmlAdapter’S Internals

Som vi kan se, er XmlAdapter har to typeparametere, i dette tilfellet, String og Dato. Den første er typen som brukes i XML og kalles verditype. I dette tilfellet vet JAXB hvordan man konverterer en XML-verdi til en String. Den andre kalles den bundne typen og relaterer seg til verdien i Java-objektet vårt.

Målet med en adapter er å konvertere mellom verditypen og en bundet type, på en måte som JAXB ikke kan gjøre som standard.

For å bygge en skikk XmlAdapter, må vi overstyre to metoder: XmlAdapter.marshal () og XmlAdapter.unmarshal ().

Under unmarshalling fjerner JAXBs bindende rammeverk først XML-representasjonen til a String og påkaller deretter DateAdapter.unmarshal () å tilpasse verditypen til en Dato. Under marshalling påberoper JAXB-bindende rammeverk DateAdapter.marshal () å tilpasse en Dato til String, som deretter marshales til en XML-representasjon.

4.3. Integrering via JAXB-merknader

De Datoadapter fungerer som et plugin til JAXB, og vi skal knytte det til datofeltet vårt ved hjelp av @XmlJavaTypeAdapter kommentar. De @XmlJavaTypeAdapter kommentar spesifiserer bruken av en XmlAdapter for tilpasset unmarshalling:

@XmlRootElement (name = "book") public class BookDateAdapter {// same as before @XmlElement (name = "published", required = true) @XmlJavaTypeAdapter (DateAdapter.class) private Dato publisert; // samme som før }

Vi bruker også standard JAXB-merknader: @XmlRootElement og @XmlElement kommentarer.

Til slutt, la oss kjøre den nye koden:

[tittel: Book1; publisert: ons. 28 nov 02:31:32 EET 1979]

5. Oppheving av datoer i Java 8

Java 8 introduserte en ny Dato tid API. Her skal vi fokusere på LocalDateTime klasse som er en av de mest brukte.

5.1. Bygge en LocalDateTime-basert XmlAdapter

Som standard, JAXB kan ikke automatisk binde en xsd: dateTime verdi til en LocalDateTime objekt uavhengig av datoformat. For å konvertere en XML Schema-datoverdi til eller fra en LocalDateTime objekt, må vi definere en annen XmlAdapter lik den forrige:

offentlig klasse LocalDateTimeAdapter utvider XmlAdapter {privat DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern ("åååå-MM-dd HH: mm: ss"); @Override public String marshal (LocalDateTime dateTime) {retur dateTime.format (dateFormat); } @Override public LocalDateTime unmarshal (String dateTime) {return LocalDateTime.parse (dateTime, dateFormat); }}

I dette tilfellet, vi har brukt en DateTimeFormatter i stedet for en SimpleDateFormat. Førstnevnte ble introdusert i Java 8, og den er kompatibel med den nye Dato tid API.

Merk at konverteringsoperasjonene kan dele a DateTimeFormatter objekt fordi de DateTimeFormatter er trådsikker.

5.2. Integrering av den nye adapteren

La oss nå erstatte den gamle adapteren med den nye i vår Bok klasse og også Dato med LocalDateTime:

@XmlRootElement (name = "book") public class BookLocalDateTimeAdapter {// same as before @XmlElement (name = "published", required = true) @XmlJavaTypeAdapter (LocalDateTimeAdapter.class) private LocalDateTime publisert; // samme som før }

Hvis vi kjører ovennevnte kode, får vi utdataene:

[tittel: Book1; publisert: 1979-11-28T02: 31: 32]

Merk at LocalDateTime.toString () legger til “T” avgrense mellom dato og klokkeslett.

6. Konklusjon

I denne veiledningen utforsket vi oppheving av datoer med JAXB.

Først så vi på XML Schema til Java datatypekartlegging og opprettet et eksempel ved hjelp av standard XML Schema datoformat.

Deretter lærte vi hvordan vi bruker et tilpasset datoformat basert på en tilpasset XmlAdapter og så hvordan du skal håndtere trådsikkerheten til SimpleDateFormat.

Til slutt utnyttet vi den overlegne, trådsikre, Java 8 Date / Time API og uminnede datoer med tilpassede formater.

Som alltid er kildekoden som brukes i opplæringen tilgjengelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found