Java Architecture for XML Binding gir en kraftig og praktisk måte å jobbe med XML-innhold fra Java-applikasjoner. Den nylig utgitte JAXB 2.0 tilbyr mange nye funksjoner, inkludert full støtte for alle XML Schema-funksjoner, betydelig færre genererte klasser, genererte klasser som er lettere å manipulere og en mer fleksibel valideringsmekanisme.
For å forstå hvordan du behandler XML-dokumenter i Java med JAXB 2.0, må vi se på de to viktigste JAXB-komponentene:
- Bindingskompilatoren, som binder et gitt XML-skjema til et sett med genererte Java-klasser
- Det bindende kjøretidsrammeverket, som gir funksjonalitet for uoppdatering, rangering og validering
JAXB-bindende kompilator (eller xbj
) lar deg generere Java-klasser fra et gitt XML-skjema. JAXB-bindende kompilatoren forvandler et XML-skjema til en samling Java-klasser som samsvarer med strukturen beskrevet i XML-skjemaet. Disse klassene er merket med spesielle JAXB-merknader, som gir kjøretidsrammeverket med kartleggingen det trenger for å behandle de tilsvarende XML-dokumentene.
Det bindende kjøretidsrammeverket gir en effektiv og brukervennlig mekanisme for unmarshalling (eller lesing) og marshalling (eller skriving) av XML-dokumenter. Den lar deg forvandle et XML-dokument til et hierarki av Java-objekter (unmarshalling), eller omvendt, transformere et Java-objekthierarki til XML-format (marshalling). Begrepet marshalling refererer tradisjonelt til å disponere tropper på en passende måte. I nettverk refererer det til å plassere dataelementer i en buffer før du sender dem over en kommunikasjonskanal.
Kombinert produserer disse to komponentene en teknologi som lar Java-utviklere enkelt manipulere XML-data i form av Java-objekter uten å måtte kjenne detaljene til Simple API for XML Processing (SAX) eller Document Object Model (DOM). , eller til og med finesser i XML-skjema.
JAXB forutsetninger
For å komme i gang med JAXB 2.0 trenger du:
- Java Platform, Standard Edition 5: JAXB 2.0 er avhengig av funksjoner i Java SE 5, for eksempel merknader og generiske
- En implementering av JAXB 2.0
Denne artikkelen ble skrevet ved hjelp av GlassFish JAXB referanse implementeringskandidat.
Generer Java-klasser ved hjelp av JAXB-kompilatoren
JAXB-kompilatoren binder et XML-skjema til et sett med Java-klasser. Et XML-skjema er et XML-dokument som, veldig presist, beskriver elementene og attributtene som er autorisert i en bestemt type XML-dokument. I dette eksemplet bruker vi et treningskursbestillingssystem som kan godta bestillinger i XML-format. En typisk ordre ser slik ut:
10 Coyote Avenue, Arizona, USA
Det tilsvarende XML-skjemaet beskriver hvordan opplæringskurset er booket, og inneholder detaljer om det bestilte kurset, de påmeldte studentene, selskapet som bestiller og så videre. En XML-skjemabeskrivelse er ekstremt streng og kan inneholde detaljer som antall elementer som er tillatt i en liste over objekter (kardinalitet), valgfrie og obligatoriske attributter og mer. Skjemaet for bestilling av kurs (kalles kursbestilling.xsd
) vises her:
Kommandolinjeverktøyet xjc
kjører JAXB-kompilatoren. For å kjøre JAXB-kompilatoren mot skjemaet vårt, kjører vi følgende kommando:
$ xjc kurs-booking.xsd -p nz.co.equinox.training.domain.booking -d src / generert
Dette vil generere et sett med Java-klasser kommentert med JAXB 2.0-merknader. Noen av de mer nyttige alternativene er beskrevet her:
-d
: Plasser de genererte filene i denne katalogen.-p
: Plasser de genererte filene i denne pakken.-nv
: Ikke utfør streng validering av inngangsskjemaet.-httpproxy
: Bruk dette hvis du står bak en fullmektig. Tar formatet[bruker [: passord] @] proxyHost [: proxyPort]
.-klassesti
: Spesifiser klassestien, om nødvendig.-les bare
: Genererer skrivebeskyttede kildekodefiler hvis operativsystemet ditt støtter dette.
Det er også en ekvivalent maur
oppgave, noe som gjør det ganske enkelt å integrere i en maur- eller Maven-basert byggeprosess.
Listen over genererte klasser vises her:
CompanyType.java ContactType.java CourseBooking.java ObjectFactory.java StudentType.java
Brukere av tidligere versjoner av JAXB kan legge merke til at dette er et glatt sett med kommenterte og fullt dokumenterte Java-klasser, i stedet for det mer tungvint settet med grensesnitt og implementeringer av tidligere versjoner. Dermed har vi mindre genererte klasser, og lettere og mer elegant kode. Og som du vil se i neste avsnitt, er det enkelt å manipulere disse klassene.
Unmarshalling et XML-dokument
Unmarshalling er prosessen med å konvertere et XML-dokument til et tilsvarende sett med Java-objekter. Unmarshalling i JAXB 2.0 er enkelt. Først oppretter du en JAXBContext
kontekstobjekt. Kontekstobjektet er utgangspunktet for marshalling, unmarshalling og validering. Her angir du Java-pakken som inneholder dine JAXB-tilordnede klasser:
JAXBContext jaxbContext = JAXBContext.newInstance ("nz.co.equinox.training.domain.booking");
For å oppheve arkivering av et XML-dokument, oppretter du et Unmarshaller
fra sammenhengen, som vist her:
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller ();
De unmarshaller
kan behandle XML-data fra et bredt utvalg av datakilder: filer, inngangsstrømmer, URL-er, DOM-objekter, SAX-parsere og mer. Her gir vi en enkel Fil
objekt som peker mot vårt XML-dokument. De unmarshaller
returnerer en maskinskrevet JAXBElement
, hvorfra vi kan få tak i vårt umarkerte objekt ved å bruke getValue ()
metode:
JAXBElement bookingElement = (JAXBElement) unmarshaller.unmarshal (ny fil ("src / test / resources / xml / booking.xml"));
CourseBooking booking = bookingElement.getValue ();
Dokumentvalidering
Dokumentvalidering er prosessen for å sikre at XML-dokumentet tilsvarer definisjonen gitt i det tilsvarende XML-skjemaet. Det er et viktig aspekt av ethvert prosjekt som involverer XML-utveksling, spesielt hvis XML kommer fra andre systemer. Dokumentvalidering i JAXB 2.0 er enklere og mer fleksibel enn i tidligere versjoner. Du kan ganske enkelt legge ved en ValidatonEventHandler
til unmarshaller
før du fjerner XML-dokumentet, som vist her:
unmarshaller.setEventHandler (ny BookingValidationEventHandler ());
En valideringshendelsesbehandler implementerer ValidationEventHandler
grensesnitt og handleEvent ()
metode, som vist her:
public class BookingValidationEventHandler implementerer ValidationEventHandler {
public boolean handleEvent (ValidationEvent ve) {
hvis (ve.getSeverity () == ValidationEvent.FATAL_ERROR || ve .getSeverity () == ValidationEvent.ERROR) {ValidationEventLocator locator = ve.getLocator (); // Skriv ut melding fra valdasjonshendelsen System.out.println ("Ugyldig bestillingsdokument:" + locator.getURL ()); System.out.println ("Feil:" + ve.getMessage ()); // Utgangslinje og kolonnenummer System.out.println ("Feil ved kolonne" + locator.getColumnNumber () + ", linje" + locator.getLineNumber ()); } returner sant; }}
Her skriver vi bare ut detaljer om feilen, men i en reell applikasjon kan noe mindre triviell behandling være passende. I noen tilfeller kan du til og med vurdere at valideringsfeilen ikke er en show-stopper, og at den ikke vil blokkere behandlingen. Ved å returnere sant, forteller du unmarshaller
å fortsette unmarshalling-prosessen: false ville avslutte prosessen med et passende unntak.
Marshalling et dokument
Marshalling innebærer å transformere Java-klassene dine til XML-format. I JAXB 2.0 er det enkelt å lage og manipulere disse Java-klassene. I de fleste tilfeller kan du bare behandle dem som vanlige Java-klasser, som vist her:
CourseBooking booking = ny CourseBooking (); booking.setCourseReference ("UML-101"); booking.setTotalPrice (ny BigDecimal (10000)); ...
Merk at du fremdeles kan bruke ObjectFactory
klasse på samme måte som hvordan du brukte den i JAXB 1.0, som vist i følgende liste. Imidlertid, i motsetning til JAXB 1.0, er det ingen grensesnitt eller implementeringsklasser: alle domeneobjekter er bare merkede JavaBeans-komponenter.
ObjectFactory fabrikk = ny ObjectFactory (); CourseBooking booking = factory.createCourseBooking (); ...
Selv om de fleste XML-datatyper tilordnes direkte til normale Java-klasser, er det behov for spesiell behandling for visse datatyper, for eksempel datoer. I disse tilfellene må du bruke DatatypeFabrikk
, som vist her:
DatatypeFactory datatypes = DatatypeFactory.newInstance (); booking.setCourseDate (datatypes.newXMLGregorianCalendarDate (2006,06,15,0));
Når domeneobjektet ditt er initialisert, bruk JAXB-konteksten til å opprette en Marshaller
objekt og en maskinskrevet JAXBElement
. Opprette marshaller
er enkelt:
Marshaller marshaller = jaxbContext.createMarshaller ();
Deretter oppretter du en JAXBElement
objekt som innkapsler domenegenemnet ditt. De typede JAXBElement
tilsvarer rotelementet complexType
av XML-dokumentet. Bruk deretter det genererte ObjectFactory
klasse som følger:
JAXBElement bookingElement = (ny ObjectFactory ()). CreateBooking (booking);
I dette eksemplet setter vi en egenskap slik at utdataene blir formatert for menneskelig bruk og deretter skriver til standardutdata:
marshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.marshal (bookingElement, System.out);
En fullstendig kodeeksempel vises her:
JAXBContext jaxbContext = JAXBContext.newInstance ("nz.co.equinox.training.domain.booking");
CourseBooking booking = ny CourseBooking (); booking.setCourseReference ("UML-101"); booking.setTotalPrice (ny BigDecimal (10000)); booking.setInvoiceReference ("123456"); DatatypeFactory datatypes = DatatypeFactory.newInstance (); booking.setCourseDate (datatypes.newXMLGregorianCalendarDate (2006,06,15,0)); booking.setTotalPrice (ny BigDecimal (10000)); booking.setInvoiceReference ("123456"); booking.getStudent (). legg til (ny StudentType ()); booking.getStudent (). get (0) .setFirstName ("John"); booking.getStudent (). get (0) .setSname ("Smith"); booking.setCompany (ny CompanyType ()); booking.getCompany (). setName ("Klienter inkl."); booking.getCompany (). setContact (ny ContactType ()); booking.getCompany (). getContact (). setName ("Paul"); booking.getCompany (). getContact (). setEmail ("[email protected]"); booking.getCompany (). getContact (). setTelephone ("12345678"); booking.getCompany (). setAddress ("10 klientgate");
// Marshal til System.out Marshaller marshaller = jaxbContext.createMarshaller (); JAXBElement bookingElement = (ny ObjectFactory ()). CreateBooking (booking); marshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal (bookingElement, System.out);
Å kjøre denne koden vil generere noe sånt som dette: