Java Architecture for XML Binding giver en kraftfuld og praktisk måde at arbejde med XML-indhold fra Java-applikationer. Den nyligt udgivne JAXB 2.0 tilbyder mange nye funktioner, herunder fuld understøttelse af alle XML Schema-funktioner, betydeligt færre genererede klasser, genererede klasser, der er lettere at manipulere, og en mere fleksibel valideringsmekanisme.
For at forstå hvordan man behandler XML-dokumenter i Java med JAXB 2.0, skal vi se på de to vigtigste JAXB-komponenter:
- Bindingskompileren, som binder et givet XML-skema til et sæt genererede Java-klasser
- Den bindende runtime-ramme, der giver unmarshalling-, marshalling- og valideringsfunktioner
JAXB-bindingscompileren (eller xbj
) lader dig generere Java-klasser fra et givet XML-skema. JAXB-bindingscompileren omdanner et XML-skema til en samling af Java-klasser, der matcher strukturen beskrevet i XML-skemaet. Disse klasser er kommenteret med specielle JAXB-kommentarer, som giver runtime-rammen de tilknytninger, den har brug for til at behandle de tilsvarende XML-dokumenter.
Den bindende runtime-ramme tilvejebringer en effektiv og brugervenlig mekanisme til unmarshalling (eller læsning) og marshalling (eller skrivning) af XML-dokumenter. Det giver dig mulighed for at omdanne et XML-dokument til et hierarki af Java-objekter (unmarshalling) eller omvendt omdanne et Java-objekthierarki til XML-format (marshalling). Begrebet marshalling traditionelt henviser til bortskaffelse af tropper på en passende måde. I netværk refererer det til at placere dataelementer i en buffer, før de sendes over en kommunikationskanal.
Kombineret producerer disse to komponenter en teknologi, der gør det muligt for Java-udviklere nemt at manipulere XML-data i form af Java-objekter uden at skulle kende de detaljerede detaljer i Simple API til XML-behandling (SAX) eller Document Object Model (DOM) , eller endda finesser i XML-skema.
JAXB forudsætninger
For at komme i gang med JAXB 2.0 har du brug for:
- Java Platform, Standard Edition 5: JAXB 2.0 er stærkt afhængig af funktioner i Java SE 5, såsom kommentarer og generiske
- En implementering af JAXB 2.0
Denne artikel blev skrevet ved hjælp af frigivelseskandidaten GlassFish JAXB.
Generer Java-klasser ved hjælp af JAXB-kompilatoren
JAXB-compileren binder et XML-skema til et sæt Java-klasser. Et XML-skema er et XML-dokument, der meget nøjagtigt beskriver de elementer og attributter, der er godkendt i en bestemt type XML-dokument. I dette eksempel bruger vi et kursusbookingssystem, der kan acceptere ordrer i XML-format. En typisk ordre ser sådan ud:
10 Coyote Avenue, Arizona, USA
Det tilsvarende XML-skema beskriver, hvordan uddannelseskurset er booket, og indeholder detaljer om det reserverede kursus, de tilmeldte studerende, det firma, der foretager reservationen osv. En XML-skemabeskrivelse er ekstremt streng og kan omfatte detaljer såsom antallet af elementer, der er tilladt i en liste over objekter (kardinalitet), valgfri og obligatorisk attributter og mere. Skemaet til bookingen af kursusforløb (kaldet kursus-booking.xsd
) vises her:
Kommandolinjeværktøjet xjc
kører JAXB-kompilatoren. For at køre JAXB-kompilatoren mod vores skema, kører vi følgende kommando:
$ xjc kursusreservation.xsd -p nz.co.equinox.training.domæne.booking -d src / genereret
Dette genererer et sæt Java-klasser, der er kommenteret med JAXB 2.0-kommentarer. Nogle af de mere nyttige muligheder er beskrevet her:
-d
: Placer de genererede filer i denne mappe.-p
: Placer de genererede filer i denne pakke.-nv
: Udfør ikke streng validering af inputskemaet.-httpproxy
: Brug dette, hvis du står bag en proxy. Tager formatet[bruger [: adgangskode] @] proxyHost [: proxyPort]
.-klassesti
: Angiv om nødvendigt klassestien.-Læs kun
: Genererer skrivebeskyttede kildekodefiler, hvis dit operativsystem understøtter dette.
Der er også en ækvivalent myre
opgave, hvilket gør det ret nemt at integrere i en Ant- eller Maven-baseret byggeproces.
Listen over genererede klasser vises her:
CompanyType.java ContactType.java CourseBooking.java ObjectFactory.java StudentType.java
Brugere af tidligere versioner af JAXB bemærker muligvis, at dette er et glat sæt af kommenterede og fuldt dokumenterede Java-klasser snarere end det mere besværlige sæt grænseflader og implementeringer af tidligere versioner. Således har vi mindre genererede klasser og lettere og mere elegant kode. Og som du vil se i det næste afsnit, er det nemt at manipulere disse klasser.
Fjernelse af arkivering af et XML-dokument
Unmarshalling er processen med at konvertere et XML-dokument til et tilsvarende sæt Java-objekter. Det er let at afmontere i JAXB 2.0. Først opretter du en JAXBContext
kontekst objekt. Kontekstobjektet er udgangspunktet for marshalling, unmarshalling og validering. Her angiver du Java-pakken, der indeholder dine JAXB-kortlagte klasser:
JAXBContext jaxbContext = JAXBContext.newInstance ("nz.co.equinox.training.domain.booking");
For at fjerne markeringen af et XML-dokument opretter du et Unmarshaller
fra sammenhængen, som vist her:
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller ();
Det unmarshaller
kan behandle XML-data fra en lang række datakilder: filer, inputstrømme, URL'er, DOM-objekter, SAX-parsere og mere. Her giver vi en enkel Fil
objekt, der peger på vores XML-dokument. Det unmarshaller
returnerer en indtastet JAXBElement
, hvorfra vi kan hente vores umarmede objekt ved hjælp af getValue ()
metode:
JAXBElement bookingElement = (JAXBElement) unmarshaller.unmarshal (ny fil ("src / test / resources / xml / booking.xml"));
CourseBooking booking = bookingElement.getValue ();
Dokumentvalidering
Dokumentvalidering er processen med at sikre, at dit XML-dokument svarer til definitionen i det tilsvarende XML-skema. Det er et vigtigt aspekt af ethvert projekt, der involverer XML-udveksling, især hvis XML kommer fra andre systemer. Dokumentvalidering i JAXB 2.0 er lettere og mere fleksibel end i tidligere versioner. Du kan ganske enkelt vedhæfte en ValidatonEventHandler
til unmarshaller
inden afmontering af XML-dokumentet, som vist her:
unmarshaller.setEventHandler (ny BookingValidationEventHandler ());
En valideringshændelseshåndterer implementerer ValidationEventHandler
interface 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 (); // Udskriv besked fra valdationshændelse System.out.println ("Ugyldigt reservationsdokument:" + locator.getURL ()); System.out.println ("Fejl:" + ve.getMessage ()); // Output line and column number System.out.println ("Fejl ved kolonne" + locator.getColumnNumber () + ", line" + locator.getLineNumber ()); } returner sandt }}
Her udskriver vi bare detaljer om fejlen, men i en reel applikation kan en mindre triviel behandling være passende. I nogle tilfælde kan du endda overveje, at valideringsfejlen ikke er en show-stop, og at den ikke blokerer behandlingen. Ved at vende tilbage sandt, fortæller du det unmarshaller
at fortsætte unmarshalling-processen: falsk ville afslutte processen med en passende undtagelse.
Opbevaring af et dokument
Marshalling indebærer at omdanne dine Java-klasser til XML-format. I JAXB 2.0 er det enkelt at oprette og manipulere disse Java-klasser. I de fleste tilfælde kan du bare behandle dem som almindelige Java-klasser, som vist her:
CourseBooking booking = ny CourseBooking (); booking.setCourseReference ("UML-101"); booking.setTotalPrice (ny BigDecimal (10000)); ...
Bemærk, at du stadig kan bruge ObjectFactory
klasse på samme måde som hvordan du brugte den i JAXB 1.0, som vist i den følgende liste. I modsætning til JAXB 1.0 er der imidlertid ingen grænseflader eller implementeringsklasser: alle domæneobjekter er bare kommenterede JavaBeans-komponenter.
ObjectFactory-fabrik = ny ObjectFactory (); CourseBooking-booking = fabrik.createCourseBooking (); ...
Selvom de fleste XML-datatyper kortlægges direkte til normale Java-klasser, er der behov for særlig behandling for visse datatyper, f.eks. Datoer. I disse tilfælde skal du bruge DatatypeFabrik
som vist her:
DatatypeFactory datatypes = DatatypeFactory.newInstance (); booking.setCourseDate (datatyper.newXMLGregorianCalendarDate (2006,06,15,0));
Når dit domæneobjekt er initialiseret, skal du bruge JAXB-konteksten til at oprette en Marshaller
objekt og en maskinskrevet JAXBElement
. Oprettelse af marshaller
er simpelt:
Marshaller marshaller = jaxbContext.createMarshaller ();
Derefter opretter du en JAXBElement
objekt, der indkapsler dit domæneobjekt. Den typede JAXBElement
svarer til rodelementet complexType
af dit XML-dokument. Brug derefter det genererede ObjectFactory
klasse som følger:
JAXBElement bookingElement = (ny ObjectFactory ()) createBooking (reservation);
I dette eksempel indstiller vi en egenskab, så output bliver formateret til menneskelig brug og derefter skriver til standardoutput:
marshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.marshal (bookingElement, System.out);
En fuld 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 (datatyper.newXMLGregorianCalendarDate (2006,06,15,0)); booking.setTotalPrice (ny BigDecimal (10000)); booking.setInvoiceReference ("123456"); booking.getStudent (). tilføj (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 client street");
// 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);
At køre denne kode genererer noget som dette: