Programmering

Server-Side Java: Bruk XML og JSP sammen

For formålet med denne artikkelen vil jeg anta at du vet hva JavaServer Pages (JSP) og Extensible Markup Language (XML) er, men du kan være litt uklar på hvordan du kan bruke dem. JSP-bruk er ganske lett å forsvare. Det lar deg designe et nettsted som er laget av filer som ser ut som HTML. Den eneste forskjellen er at JSP-er også handler dynamisk - for eksempel kan de behandle skjemaer eller lese databaser - ved hjelp av Java som skriptspråk på serversiden. XML-bruk er vanskeligere å rettferdiggjøre. Selv om det virker som om hvert nytt produkt støtter det, ser det ut til at de bruker XML for et annet formål.

I denne artikkelen vil du lære å designe et system ved hjelp av XML på en ganske beskjeden måte. Mange nettsteder har enorme samlinger av data som vises på en mer eller mindre standard måte. Jeg vil designe et system som bruker XML-filer til å lagre data på en webserver og JSP-filer for å vise disse dataene.

XML versus relasjonsdatabaser

"Men vent," spør du kanskje, "du bruker XML til å lagre data? Hvorfor ikke bruke en database?" Godt spørsmål. Svaret er at for mange formål er en database overkill. For å bruke en database, må du installere og støtte en egen serverprosess, som ofte også krever installasjon og støtte av en databaseadministrator. Du må lære SQL og skrive SQL-spørsmål som konverterer data fra en relasjon til en objektstruktur og tilbake igjen. Hvis du lagrer dataene dine som XML-filer, mister du overhead på en ekstra server. Du får også en enkel måte å redigere dataene på: bare bruk et tekstredigeringsprogram, i stedet for et komplisert databaseverktøy. XML-filer er også lettere å sikkerhetskopiere, dele med vennene dine eller laste ned til klientene dine. Du kan også enkelt laste opp nye data til nettstedet ditt ved hjelp av FTP.

En mer abstrakt fordel med XML er at den, som et hierarkisk snarere enn et relasjonelt format, kan brukes på en mye mer enkel måte for å designe datastrukturer som passer dine behov. Du trenger ikke å bruke en enhetsrelasjonsredigerer eller normalisere skjemaet ditt. Hvis du har ett element som inneholder et annet element, kan du representere det direkte i formatet, i stedet for å bruke en sammenføyningstabell.

Merk at et filsystem for mange applikasjoner ikke er tilstrekkelig. Hvis du har et stort volum av oppdateringer, kan et filsystem bli forvirret eller ødelagt av samtidig skriving. databaser støtter vanligvis transaksjoner, som tillater samtidighet uten korrupsjon. Videre er en database et utmerket verktøy hvis du trenger å gjøre kompliserte spørsmål, spesielt hvis de vil variere fra tid til annen. Databaser bygger indekser, og er optimalisert for å holde indeksene oppdatert med et stadig skiftende datasett. Relasjonsdatabaser har også mange andre fordeler, inkludert et rikt spørringsspråk, modne redigerings- og skjemadesignverktøy, bevist skalerbarhet, finkornet tilgangskontroll og så videre.

(Merk: Du kan bruke enkel fillåsing for å gi en fattig manns transaksjonsserver. Og du kan også implementere et XML-indeks-og-søkeverktøy i Java, men det er et emne for en annen artikkel.)

I dette tilfellet, som i de fleste publiseringsbaserte nettsteder med lavt til middels volum, kan du anta følgende: det meste av datatilgangen er lese, ikke skrive; dataene, selv om de er potensielt store, er relativt uendrede; du trenger ikke å gjøre kompliserte søk, men hvis du gjør det, bruker du en egen søkemotor. Fordelene med å bruke en moden RDBMS blekner, mens fordelen med å bruke en objektorientert datamodell kommer til syne.

Til slutt er det fullt mulig å tilby en innpakning til databasen din som lager SQL-spørsmål og oversetter dem til XML-strømmer, slik at du kan ha det begge veier. XML blir en mer robust, programmerervennlig frontend til en moden database for lagring og søk. (Oracles XSQL-servlet er et eksempel på denne teknikken.)

Søknaden: Et online fotoalbum

Alle elsker bilder! Folk elsker å vise bilder av seg selv, vennene, kjæledyrene og feriene. Internett er det ultimate mediet for selvfornøyende lukkerfugler - de kan irritere sine slektninger tusenvis av miles unna. Mens et fullverdig nettsted for fotoalbum vil kreve en komplisert objektmodell, vil jeg fokusere på å definere en enkelt Bilde gjenstand. (Kildekoden for dette programmet er tilgjengelig i Ressurser.) Objektet som representerer et bilde trenger felt som representerer tittelen, datoen det ble tatt, en valgfri billedtekst og åpenbart en peker til bildekilden.

Et bilde trenger i sin tur noen egne felt: plasseringen av kildefilen (en GIF eller JPEG) og høyden og bredden i piksler (for å hjelpe deg med å bygge koder). Her er det en fin fordel med å bruke filsystemet som din database: du kan lagre bildefilene i samme katalog som datafilene.

Til slutt, la oss utvide bildeopptaket med et element som definerer et sett med miniatyrbilder for bruk i innholdsfortegnelsen eller andre steder. Her bruker jeg det samme konseptet av bilde Jeg definerte tidligere.

XML-representasjonen av et bilde kan se slik ut:

 Alex On The Beach 1999-08-08 Prøver forgjeves å få en brunfarge alex-beach.jpg 340 200 alex-beach-sm.jpg 72 72 alex-beach-med.jpg 150 99 

Merk at ved å bruke XML, legger du all informasjon om et enkelt bilde i en enkelt fil, i stedet for å spre det mellom tre eller fire separate tabeller. La oss kalle dette en .pix fil - slik at filsystemet ditt kan se slik ut:

 summer99 / alex-beach.pix summer99 / alex-beach.jpg summer99 / alex-beach-sm.jpg summer99 / alex-beach-med.jpg summer99 / alex-snorkeling.pix etc. 

Teknikker

Det er mer enn en måte å flå en katt på, og det er mer enn en måte å bringe XML-data på JSP-siden din. Her er en liste over noen av disse måtene. (Denne listen er ikke uttømmende; mange andre produkter og rammer vil tjene like bra.)

  • DOM: Du kan bruke klasser som implementerer DOM-grensesnittet for å analysere og inspisere XML-filen
  • XMLEntryList: Du kan bruke koden min til å laste XML inn i en java.util.Liste av navn-verdi-par
  • XPath: Du kan bruke en XPath-prosessor (som Resin) til å finne elementer i XML-filen etter stienavn
  • XSL: Du kan bruke en XSL-prosessor til å transformere XML til HTML
  • Kokong: Du kan bruke Cocoon-rammeverket med åpen kildekode
  • Rull din egen bønne: Du kan skrive en wrapper-klasse som bruker en av de andre teknikkene for å laste inn dataene i en tilpasset JavaBean

Merk at disse teknikkene kan brukes like godt på en XML-strøm du mottar fra en annen kilde, for eksempel en klient eller en applikasjonsserver.

JavaServer-sider

JSP-spesifikasjonen har hatt mange inkarnasjoner, og forskjellige JSP-produkter implementerer forskjellige, inkompatible versjoner av spesifikasjonen. Jeg vil bruke Tomcat av følgende grunner:

  • Den støtter de mest oppdaterte versjonene av JSP og servlet-spesifikasjonene
  • Det er godkjent av Sun og Apache
  • Du kan kjøre den frittstående uten å konfigurere en egen webserver
  • Det er åpen kildekode

(For mer informasjon om Tomcat, se Ressurser.)

Du er velkommen til å bruke hvilken som helst JSP-motor du liker, men å konfigurere den er opp til deg! Forsikre deg om at motoren støtter minst JSP 1.0-spesifikasjonen; det var mange endringer mellom 0,91 og 1,0. JSWDK (Java Server Web Development Kit) fungerer helt fint.

JSP-strukturen

Når du bygger et JSP-drevet nettsted (også kjent som en Webapp), Jeg foretrekker å plassere vanlige funksjoner, import, konstanter og variable erklæringer i en egen fil som heter init.jsp, som ligger i kildekoden for denne artikkelen.

Jeg laster deretter den filen inn i hver JSP-fil ved hjelp av . De direktiv fungerer som C-språkene #inkludere, trekker inn teksten til den inkluderte filen (her, init.jsp) og kompilere det som om det var en del av den inkluderende filen (her, bilde.jsp). Derimot tag kompilerer filen som en egen JSP-fil og legger inn et anrop til den i den kompilerte JSP.

Finne filen

Når JSP starter, er det første det trenger å gjøre etter initialisering, å finne XML-filen du vil ha. Hvordan vet den hvilken av de mange filene du trenger? Svaret er fra en CGI-parameter. Brukeren vil påkalle JSP med URL-en picture.jsp? file = summer99 / alex-beach.pix (eller ved å passere en fil parameter gjennom et HTML-skjema).

Men når JSP mottar parameteren, er du fortsatt bare halvveis der. Du må fremdeles vite hvor rotkatalogen ligger på filsystemet. For eksempel på et Unix-system kan den faktiske filen være i katalogen /home/alex/public_html/pictures/summer99/alex-beach.pix. JSP-er har ikke et konsept med en gjeldende katalog mens de kjøres, så du må oppgi et absolutt stienavn til java.io pakke.

Servlet API gir en metode for å gjøre en URL-bane, i forhold til gjeldende JSP eller Servlet, til en absolutt filsystembane. Metoden ServletContext.getRealPath (streng) gjør susen. Hver JSP har en ServletContext gjenstand kalt applikasjon, så koden ville være:

String picturefile = application.getRealPath ("/" + request.getParameter ("file")); 

eller

String picturefile = getServletContext (). GetRealPath ("/" + request.getParameter ("file")); 

som også fungerer inne i en servlet. (Du må legge til en / fordi metoden forventer å bli bestått resultatene av request.getPathInfo ().)

En viktig merknad: Når du får tilgang til lokale ressurser, må du være veldig forsiktig med å validere innkommende data. En hacker, eller en uforsiktig bruker, kan sende falske data for å hacke nettstedet ditt. Tenk for eksempel på hva som ville skje hvis verdien fil = .. / .. / .. / .. / etc / passwd ble angitt. Brukeren kan på denne måten lese serverens passordfil.

Dokumentobjektmodellen

DOM står for Dokumentobjektmodell. Det er en standard API for surfing av XML-dokumenter, utviklet av World Wide Web Consortium (W3C). Grensesnittene er i pakken org.w3c.dom og er dokumentert på W3C-nettstedet (se Ressurser).

Det er mange DOM-parserimplementeringer tilgjengelig. Jeg har valgt IBMs XML4J, men du kan bruke hvilken som helst DOM-parser. Dette er fordi DOM er et sett med grensesnitt, ikke klasser - og alle DOM-parsere må returnere objekter som trofast implementerer disse grensesnittene.

Dessverre, selv om det er standard, har DOM to store feil:

  1. APIen, selv om den er objektorientert, er ganske tungvint.
  2. Det er ingen standard API for en DOM-parser, så mens hver parser returnerer en org.w3c.dom.Document objektet, er midlene til å initialisere parseren og laste inn selve filen alltid parserspesifikk.

Den enkle bildefilen beskrevet ovenfor er representert i DOM av flere objekter i en trestruktur.

Document Node -> Element Node "picture" -> Text Node "\ n" (whitespace) -> Element Node "title" -> Text Node "Alex On The Beach" -> Element Node "date" - -> ... etc. 

Å skaffe seg verdien Alex On The Beach du må foreta flere metodeanrop, gå DOM-treet. Videre kan parseren velge å blande et hvilket som helst antall hvite mellomromstekstnoder, som du må løkke gjennom og enten ignorere eller sammenkoble (du kan rette dette ved å ringe normalisere () metode). Parseren kan også inkludere separate noder for XML-enheter (som f.eks &), CDATA-noder eller andre elementnoder (for eksempel de stor Bjørn ville forvandles til minst tre noder, hvorav den ene er en b element som inneholder en tekstnode som inneholder teksten stor). Det er ingen metode i DOM å bare si "få meg tekstverdien til tittelelementet." Kort sagt, å gå DOM er litt tungvint. (Se XPath-delen i denne artikkelen for et alternativ til DOM.)

Fra et høyere perspektiv er problemet med DOM at XML-objektene ikke er tilgjengelige direkte som Java-objekter, men de må nås stykkevis via DOM API. Se konklusjonen min for en diskusjon av Java-XML Data Binding-teknologi, som bruker denne rett til Java-tilnærmingen for tilgang til XML-data.

Jeg har skrevet en liten nytteklasse, kalt DOMUtils, som inneholder statiske metoder for å utføre vanlige DOM-oppgaver. For eksempel å skaffe tekstinnholdet i tittel underordnet element av roten (bilde) -element, vil du skrive følgende kode:

Dokument doc = DOMUtils.xml4jParse (bildefil); Element nodeRoot = doc.getDocumentElement (); Node nodeTitle = DOMUtils.getChild (nodeRoot, "title"); Streng tittel = (nodeTitle == null)? null: DOMUtils.getTextValue (nodeTitle); 

Å få verdiene for bildedelene er like greie:

Node nodeImage = DOMUtils.getChild (nodeRoot, "image"); Node nodeSrc = DOMUtils.getChild (nodeImage, "src"); Streng src = DOMUtils.getTextValue (nodeSrc); 

Og så videre.

Når du har Java-variabler for hvert relevante element, er alt du trenger å gjøre å legge inn variablene i HTML-markeringen din, ved hjelp av standard JSP-koder.

Se hele kildekoden for mer informasjon. HTML-utdata produsert av JSP-filen - et HTML-skjermbilde, hvis du vil - er i bilde-dom.html.

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