Fjernelse af data ved brug af JAXB

1. Introduktion

I denne vejledning vi skal se, hvordan man ophæver datoobjekter med forskellige formater ved hjælp af JAXB.

Først dækker vi standardformatet for skematisk dato. Derefter undersøger vi, hvordan du bruger forskellige formater. Vi ser også, hvordan vi kan håndtere en fælles udfordring, der opstår med disse teknikker.

2. Skema til Java Binding

Først, vi er nødt til at forstå forholdet mellem XML-skemaet og Java-datatyperne. Vi er især interesserede i kortlægningen mellem et XML-skema og Java-datoobjekter.

Ifølge Skema til Java-kortlægning, der er tre skema-datatyper, som vi skal tage i betragtning: xsd: dato, xsd: tid og xsd: dateTime. Som vi kan se, kortlægges dem alle javax.xml.datatype.XMLGregorianCalendar.

Vi har også brug for at forstå standardformaterne for disse XML-skematyper. Det xsd: dato og xsd: tid datatyper har “ÅÅÅÅ-MM-DD ” og “tt: mm: ss ” formater. Det xsd: dateTime formatet er “ÅÅÅÅ-MM-DDThh: mm: ss ” hvor "T ” er en separator, der angiver starten på tidsafsnittet.

3. Brug af standardskemaets datoformat

Vi skal bygge et eksempel på, at unmarshals daterer objekter. Lad os fokusere på xsd: dateTime datatype, fordi det er et supersæt af de andre typer.

Lad os bruge en simpel XML-fil, der beskriver en bog:

 Bog1 1979-10-21T03: 31: 12 

Vi vil kortlægge filen til det tilsvarende Java Bestil objekt:

@XmlRootElement (name = "book") public class Book {@XmlElement (name = "title", required = true) privat strengtitel; @XmlElement (navn = "offentliggjort", krævet = sand) privat XMLGregorianCalendar offentliggjort; @Override public String toString () {return "[title:" + title + "; offentliggjort:" + offentliggjort.toString () + "]"; }}

Endelig er vi nødt til at oprette en klientapplikation, der konverterer XML-data til JAXB-afledte Java-objekter:

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

I ovenstående kode har vi defineret en JAXBContext som er indgangspunktet i JAXB API. Så har vi brugt en JAXB Unmarshaller på en inputstrøm for at læse vores objekt:

Hvis vi kører ovenstående kode og udskriver resultatet, får vi følgende Bestil objekt:

[titel: Bog1; offentliggjort: 1979-11-28T02: 31: 32]

Vi skal bemærke det, selvom standardkortlægningen for xsd: dateTime er XMLGregorianCalendar, kunne vi også have brugt de mere almindelige Java-typer: java.util.Date og java.util.Kalender, ifølge JAXB-brugervejledningen.

4. Brug af et brugerdefineret datoformat

Ovenstående eksempel fungerer, fordi vi bruger standardskemaets datoformat, “ÅÅÅÅ-MM-DDThh: mm: ss”.

Men hvad nu hvis vi vil bruge et andet format som "ÅÅÅÅ-MM-DD tt: mm: ss", slippe af med “T” afgrænsning? Hvis vi skulle erstatte afgrænseren med et mellemrumstegn i vores XML-fil, ville standardafparsningen ikke mislykkes.

4.1. Opbygning af en brugerdefineret Xml-adapter

For at kunne bruge et andet datoformat skal vi definere et Xml-adapter.

Lad os også se, hvordan man kortlægger xsd: dateTime skriv til en java.util.Date objekt med vores skik Xml-adapter:

offentlig klasse DateAdapter udvider XmlAdapter {privat statisk endelig streng 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 adapter, vi har brugtSimpleDateFormat for at formatere vores dato. Vi skal være forsigtige som det SimpleDateFormat er ikke trådsikker. For at undgå, at flere tråde oplever problemer med en delt SimpleDateFormat objekt skaber vi en ny hver gang vi har brug for det.

4.2. Det Xml-adapter'S Internals

Som vi kan se, er Xml-adapter har to typeparametre, I dette tilfælde, Snor og Dato. Den første er den type, der bruges i XML og kaldes værditypen. I dette tilfælde ved JAXB, hvordan man konverterer en XML-værdi til en Snor. Den anden kaldes den bundne type og vedrører værdien i vores Java-objekt.

Målet med en adapter er at konvertere mellem værditypen og en bundet type på en måde, som JAXB ikke kan gøre som standard.

For at opbygge en brugerdefineret XmlAdapter, vi er nødt til at tilsidesætte to metoder: XmlAdapter.marshal () og XmlAdapter.unmarshal ().

Under unmarshalling fjerner JAXB-bindingsrammen først XML-repræsentationen til a Snor og påberåber sig derefter DateAdapter.unmarshal () at tilpasse værditypen til a Dato. Under marshalling påberåber JAXB's bindende ramme DateAdapter.marshal () at tilpasse en Dato til Snor, som derefter marskaleres til en XML-repræsentation.

4.3. Integrering via JAXB-annotationer

Det Datoadapter fungerer som et plugin til JAXB, og vi vedhæfter det til vores datofelt ved hjælp af @XmlJavaTypeAdapter kommentar. Det @XmlJavaTypeAdapteannotering angiver brugen af ​​et Xml-adapter til brugerdefineret unmarshalling:

@XmlRootElement (navn = "bog") offentlig klasse BookDateAdapter {// samme som før @XmlElement (navn = "offentliggjort", krævet = sand) @XmlJavaTypeAdapter (DateAdapter.class) privat Dato offentliggjort; // samme som før }

Vi bruger også standard JAXB-kommentarerne: @XmlRootElement og @XmlElement kommentarer.

Lad os endelig køre den nye kode:

[titel: Bog1; offentliggjort: ons. 28. nov. 02:31:32 EET 1979]

5. Afmontering af datoer i Java 8

Java 8 introducerede en ny Dato tid API. Her vil vi fokusere på LocalDateTime klasse, som er en af ​​de mest almindeligt anvendte.

5.1. Bygning af en LocalDateTime-baseret Xml-adapter

Som standard, JAXB kan ikke automatisk binde en xsd: dateTime værdi til en LocalDateTime objekt uanset datoformat. For at konvertere en XML-skema-datoværdi til eller fra en LocalDateTime objekt, skal vi definere en anden Xml-adapter svarende til den forrige:

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

I dette tilfælde, vi har brugt en DateTimeFormatter i stedet for en SimpleDateFormat. Førstnævnte blev introduceret i Java 8, og den er kompatibel med den nye Dato tid API.

Bemærk, at konverteringshandlingerne kan dele en DateTimeFormatter objekt fordi det DateTimeFormatter er trådsikker.

5.2. Integrering af den nye adapter

Lad os nu udskifte den gamle adapter med den nye i vores Bestil klasse og også Dato med LocalDateTime:

@XmlRootElement (navn = "bog") offentlig klasse BookLocalDateTimeAdapter {// samme som før @XmlElement (navn = "offentliggjort", krævet = sand) @XmlJavaTypeAdapter (LocalDateTimeAdapter.class) privat LocalDateTime offentliggjort; // samme som før }

Hvis vi kører ovenstående kode, får vi output:

[titel: Bog1; offentliggjort: 1979-11-28T02: 31: 32]

Bemærk, at LocalDateTime.toString () tilføjer “T” afgrænser mellem dato og klokkeslæt.

6. Konklusion

I denne vejledning udforskede vi ophævelse af datoer ved hjælp af JAXB.

Først kiggede vi på XML-skema til Java-datatypekortlægning og skabte et eksempel ved hjælp af standard XML-skema-datoformat.

Derefter lærte vi, hvordan man bruger et brugerdefineret datoformat baseret på en brugerdefineret Xml-adapter og så hvordan man håndterer trådsikkerheden af SimpleDateFormat.

Endelig udnyttede vi den overlegne, trådsikre, Java 8 Date / Time API og uhåndterede datoer med brugerdefinerede formater.

Som altid er kildekoden, der bruges i vejledningen, tilgængelig på GitHub.