Servlets, Tomcat & BlueJ Tutorial lavet af Jákup W. Hansen TSU 2006 3.semester 05.october 2007 Hvad er Servlets: For at forstå det, må vi først få styr på to begreber, nemlig statiske og dynamiske hjemmesider (hvor Servlets er for dynamiske). En statisk hjemmeside er faktisk bare en html side (dvs. F.eks. index.html) som ligger på serverene, og som hvergang en client kalder på den, bliver sent til clienten. Det er rimelig nemt at forstå, at sådan en sider vil se identisk ud hver gang den bliver kaldt på. Og den eneste måde hvorpå man kan ændre den, er ved at gå ind og ændreden manuelt og så gemme den igen. Hvis du nu er lidt fantasifuld, så kunne du forestille dig, at denne html fil som lå på din hardisk under en mappe i serveren, faktisk kunne tilgås fra f.eks. et Java program, lige som vi nogle gange har skrevet ned på en fil. Det vil så give muligheder for at vi når vi ønsker det, kunne skrive/ændre i denne html side når det passede os, og det ville så medføre, at når klienterne kaldte på side, ja så så den muligvis anderledes ud. Vi har på denne måde ændret på html filen og set fra klienterne er det en dynamisk side, fordi den ikke er det samme hele tiden. MEN, det triste med dette eksempel, er at siden selv, stadigvæk er død når den ligger i mappen i serveren, selv om vi kan ændre den meget let og ikke manuelt. Vi kan dog konkludere at med et javaprogram som ændrer en html fil er en mere dynamisk løsning en en html som ligger død og som ikke kan ændres uden at man gør det manuelt. Her er det at Servlets kommer ind, og tager vores javaprogram og gør det endnu mere dynamisk. Hvordan gør Servlets så det? Jo, istedet for at vi har en html side, som Java så ændrer i, ja så har vi INGEN html fil overhoved, selv om det er det vi MÅ have at sende til klienten, fordi browseren forstår KUN html sider. Her er fidusen med Servlets. Servlets er faktisk et normalt java program som til forskel udspytter html sider. Billede lånt fra: http://perso.orange.fr/emmanuel.remy/java/tutoriels/j2ee/servlet/conteneurservlet.png Billde lånt fra: http://www.exforsys.com/images/vbnet/sourecode/j2ee/2- Servlet%20Basics/request-response-model.jpg Man kan lege med tanken, at du har et program som har 10 klasser, med omkring samme antal objekter. Så når serveren starter, så tager den klasserne og instasierer disse til objekter, som så gør at vi har et kørende program I serveren (det er derfor man må genstarte serveren, hvis man ændrer i koden). Nu er dette program lige som normale programmer at det skal have en indgang (en main metode), og det gør vi ved at lave en speciel klasse som extender HttpServlets og den har så også et navn f.eks. MinServlet. Denne klasse/objekt istansierer så de andre objekter, dvs. At det er denne MinServlet som
HAR de andre objekter, og på denne måde bliver MinServlet så indgangen (grænsefladen) til hele den underliggende applikation. Det som MinServlet så gør er at lytte til indkommende kald, og de kommer fra serveren (Tomcat) og så er det ENESTE som den returnerer en HTML side. Dvs. At MinServlet skal lave indput og output til HTML, men den kan selv inden i, bruge de andre klasser lige som normale Java programmer. Den måde hvorpå MinServlet får indput fra Serveren er ved at serveren kalder doget eller dopost metoderne (de mest normale, der er dog nogle andre http funktioner). Og så returnerer den (bruger out.println og ikke return som vi normalt gør) html tekst. Tomcat Serveren: Vi har brug for en server til at modtage clienternes requests, og dertil bruger man en server. Det kunne i princippet være en hvilken som helst server, men efter som serveren skal kunne aktivere/bruge java servlets så kan vi ikke bare vælge som det passer os. F.eks. IIS (Internet Information Server, som Microsoft laver), kan (tror jeg) ikke køre Servlets. Vi bruger en GRATIS server fra Apache som er lavet til servlets og JSP, som kaldes Tomcat. Download Tomcat Serveren: Som sagt, den er gratis og findes under følgende link, som er start siden http://tomcat.apache.org/ og derfra kan du vælge forskellige udgaver. Jeg har valgt Tomcat 6.0 under Downloads, som var den nyeste i dag. Så kommer følgende side frem. Så valgte jeg at downloade Windows Service Installer og jeg gemte den bare på hardisken, men det behøves du ikke.
Installering af Tomcat Serveren: Når den så er downloadet kommer et vindue frem, som spørger om du vil installere serveren, og det ønsker vi jo. Se følgend serie...
Nu er Apaceh Tomcat Serveren installeret, og klar til brug. Prøv og skriv localhost i browseren så bør følgende side troppe op..jeg blev nød til at Slukke serveren og genstarte den før det virkede. Her ovenover der der 2 forsøg med localhost. Det første er en normal index.html side som kommer frem (når man ikke skriver hvilken fil man ønsker, så går serveren ud fra at det er index filen du får, og det får vi så her også). Det næste forsøg er index.jsp, og her får vi en meget lignende side, men nu er det en jsp side. JSP skal vi ikke snakke om nu. Nogle Servlets Exempler: Der er nogle eksempler med i installationen, som vi kan prøve af. Du finder dem længere ned på index siden.
Du vælger Servlets Examples, og så kommer følgende side frem. Så er der et par stykker vi kan prøve. Jeg prøver lige Hello World, og så kommer denne side frem..
Tomcat start og slut: Det er lidt irriterende når man arbejder med Tomcat, og man måske ændrer lidt i mapper, javacode osv. Så skal man huske at slukke og tænde Tomcat. Så for at undgå denne irritation, så kan man faktisk gå ind i Tomcat og ændre i en fil, så at det hele sker automatisk, se følgende billede... Browser start og slut: Du må også huske på, at når du ændrer i koden eller opsætningen og du så kører browseren igen, så husker den den sidste FUNGERENDE side, som vil sige at laver du en fejl, så ses dette ikke i browseren uden at du lukker den ned og åbner en ny browser.
Hvordan kører en Servlet på Tomcat Serveren: Ok, så nu kører HelloWorldExample, men hvad sker der i grunden bagved? Jeg vil først undersøge hvor denne HelloWorldExample class fil ligger. Jeg vælger at søge efter HelloWorldExample fra windows. Se mit resultat efter searchen... Ja der er noget mystisk her...man ville forvente at der var en folder inde i examples som hed servlets og så igen en under denne som hed servlet, og så derinde skulle vores Hello..class fil ligge, MEN sådan er virkelighede ikke, hvad sker der så her? Vi kan blive enige om at alle servletter og html filer ser ud til at skulle ligge i hvert fald under webapps, men hvad der sker efterfølgende er mystisk. Men vi ved at examples også er til fælles for både browser stien og det virkelige sti, så det må være inde i examples mappen at det hele går løs, hvad er så det? Jo, hvis vi går ind i examples mappen ser vi som det også ses i den virkelige sti at der ligger en WEB-INF mappe her, hvad laver den der, og hvorfor ser vi den ikke i Browser stien?
Svaret er, at her ligger fidusen begravet, og den er gemt i en fil som heder web.xml. Hvad der sker nå browseren kalder på en file, er at Tomcat serveren gå ind og kikker i WEB-INF mapperne (der kan være mange) og finde web.xml filen og så kikker den efter de stier som er definerede i denne fil. Og hvis vi kikker på vores web.xml fil så ser vi følgende... Se den nederste som kaldes <url-pattern> der står jo lige præsis det vi havde forventet at finde i mappe struktur, men nu ligger det i stedet for i en xml fil. Giver det mening? Ja, hvis vi kikker på hvor vi er, så er vi inde i examples mappen og så kikker serveren i WEB-INF (som vi ikke ser i browseren fordi den kun er lavet til Tomcat at bruge), og der i web.xml filen fider den resten af stien og så stemmer det hele. Nu ved Tomcat også hvilken fil der er tale om, nemlig den som ligger i classes (classes mappen SKAL være i WEB-INF når vi arbejder med Servlets) og så heder den HelloWorldExample.
Ok men hvad nu hvis jeg ønsker at stien skal være kortere end den er nu, kan jeg så det? Ja, det kan man godt. Man kunne f.eks fjerne /servlets/servlet/. Ok lad mig prøve dette og lad mig så vise dig hvordan web.xml file ser ud efter denne ændring... Her er alle tre dele vist i et billede. Vi ser browseren og dens sti, som peger på examples/hellow, så her kan man se ændringen fra før, hvor stien var noget længere pågrund af det som stod i web.xml filen. Om du kikker i web.xml filen så ser du for det første HELE filen, jeg har nemlig slettet alt det som ikke er nødvendig for vores eksempel. Men i mappen har jeg ikke slettet noget, men det kunne jeg sagtens, fordi som web.xml filen er nu, så kan ingen af de classer i mappen køre. Er servlet skal defineres i web.xml filen som servlet og som servlet-mapping, og disse to skal så knyttes sammen som den grønne forbindelse viser. URL en definerer så browserurlen som ses i rød. Blå er så selve classe fil plaseringen, som SKAL være i mappen classes.
Tomcat mappestruktur: Som du måske har forstået af teksten intil nu, så er der en bestemt mappe struktur, for at en Servlet skal kunne køre i Tomcat. Den er faktisk ikke så kompliceret som den umiddelbar ser ud. Det første man skal vide er at ALLE filerne skal ligge som minimum i webapps mappen. I vores eksempel ovenover har vi en mappe i webapps mappen som kaldes examples, og det var derfor at stien i Browseren havde /examples/ med i sig. Så er det selve oppbygningen. Se følgende billede af to eksempler som jeg fokuserer på.. Strukturer er sådan. webapps Mappe (du giver den navn) WEB-INF web.xml classes Fidusen er, at du laver en mappe, som din Servlet skal være i, og så kikker serveren automatisk ned i WEB-INF mappen efter web.xml filen, for at læse hvor servletten er placeret og hvad den kaldes, og når den er fundet, køres den.
BlueJ Hello eksempel: Før vi går i gang med BlueJ må vi lave én indstilling, for overhoved at kunne kompile servletterne. Du behøver ikke selv at have HelloWorldExaples eksemplet selv, bare du følger med fra punkt 2, så er det fint. Se billedet nedenfor... Her har vi prøvet at kompile HelloWorldExample, men der kommer en fejl ved import javax.servlet.*; Dvs. At der mangler disse klasser. Dem kan vi få fat på ved at gå under tools/preferences. Når man har installeret dette, så kører det. Nå men nu kører BlueJ, så nu skal vi snyde lidt. Fordi under normale omstændigheder ville vi kompile servletten til en class file, og flytte den over classes mappen manuelt. Men vi snyder lidt, vi laver nemlig et projekt som vi kalder classes og så kan vi kompile og så kører det ny program med det sammen. Lad os starte med at vælge en ny mappe, som jeg kalder for BlueJ, og den laver jeg under webapps se følgende billede...
Under BlueJ mappen SKAL vi så lave en WEB-INF mappe og en web.xml fil (kan bare kopiere en og ændre det til) som vi ændrer senere. Se billede for de nye tilstand... Nu kommer vi til det smart. Du starter BlueJ og så laver du et nyt projet. Går ind i denne WEB-INF mappe og kalder det nye projekt for classes. Så ser situationen sådan ud... Nu har vi et BlueJ projekt placeret i det rigtige sted, men vi har intet program endnu. Derofor må vi selvfølgelig lave en klasse og fylde den med nogen kode. Du kan kopiere følgende kode ind i BlueJ og kompile den, selvfølgelig går jeg ud fra at du er i classes projektet hele tiden... import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class JakupServletten extends HttpServlet public void doget(httpservletrequest request, HttpServletResponse response) throws IOException, ServletException response.setcontenttype("text/html"); PrintWriter out = response.getwriter(); out.println("<html>"); out.println("<head>"); out.println("<title>" + "Jákup s Servlette" + "</title>"); out.println("</head>"); out.println("<body bgcolor=\"green\">"); out.println("<h1>" + "Dette er Jákup s Servletten" + "</h1>"); out.println("</body>"); out.println("</html>");
Nu mangler vi kun en sidste ting, nemlig at fikse web.xml filen så at den peger på denne JakupServletten.class fil. Det gør jeg med følgende tekst i web.xml filen... <?xml version="1.0" encoding="iso-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/webapp_2_5.xsd" version="2.5"> <servlet> <servlet-name>serv</servlet-name> <servlet-class>jakupservletten</servlet-class> </servlet> <servlet-mapping> <servlet-name>serv</servlet-name> <url-pattern>/minservlette</url-pattern> </servlet-mapping> </web-app>
Så skulle det hele køre. Du kan for en sikkerheds skyld slukke og tænde serveren og måske starte en ny browser også. Resultatet skulle se sådan ud...
BlueJ eksempel som er mere dynamisk: Nu har vi så en kørende servlet, men problemet med denne er at den giver det samme resultat hele tiden, og derfor opfører sig som en statisk side. Vi kunne fikse den lidt op ved at give siden indput felt og kunne skrive ned på en fil, og så læse det gamle op igen. Det ville virkelig vise hvordan en dynamisk hjemmeside fungere og stadigvæk være en simpel servlet. Her kommer den nye Java kode, som jeg igen forventer at du arbejder fra classes projektet... import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; //Dette er en lille men smart webapplikation. Den modtager fra brugeren en tekst som //som bliver gemt i en fil. Den tekst som var på filen bliver sent tilbage til klienten, //mens den ny indkomne tekst bliver overskrevet på filen. public class FilSkriverServlet extends HttpServlet String navn; public void doget(httpservletrequest request, HttpServletResponse response) throws IOException, ServletException PrintWriter out = response.getwriter(); out.println("doget "); dopost(request, response); public void dopost(httpservletrequest request, HttpServletResponse response) throws IOException, ServletException response.setcontenttype("text/html" ); PrintWriter out = response.getwriter(); out.println("dopost "); out.println("<html>"); out.println("<body>"); out.println("<body bgcolor=\"yellow\">"); String firstname = request.getparameter("firstname"); if (firstname!= null) out.println(" Hentet fra filen: " + LæsFileArrayList() ); out.println("<br>"); out.println(" Gemt på filen: "+ firstname+"<br>"); GemFileArrayList(firstName); else // out.println("velkommen: Skriv en tekst i boxen nedenfor og tryk på knappen..." +"<br>"); out.println("<p>"); out.print("<form action=\""); out.print("filservlet\" "); out.println("method=post>"); //Se her at POST bliver brugt, her kunne man vælge GET i stedt for // men hvis GET bruges, så ses det som sendes tilbage til serveren i addresse vinduet i Browseren. out.println("<input type=text size=20 name=firstname>"); out.println("<br>"); out.println("<input type=submit value=gemtekst"); out.println("</form>"); out.println("</body>"); out.println("</html>"); //doget(request, response); //--------------FILE afdelingen---------------------------------------------
public void GemFileArrayList(String s) try FileWriter writer = new FileWriter("Gemmer.txt"); writer.write(s); writer.close(); catch(ioexception e) System.out.println("filen kunne ikke gemmes"); public String LæsFileArrayList() try BufferedReader reader = new BufferedReader(new FileReader("Gemmer.txt")); navn = reader.readline(); reader.close(); catch(filenotfoundexception e) System.out.println("filen blev ikke funden"); catch(ioexception e) System.out.println("gik galt med læsing eller lukning"); return navn; Det vil resultere i at BlueJ grænsefladen ser sådan ud efter at du har kompilet på ny... Der er nu 2 classer i vores classes projekt.
Nu mangler jeg så at ændre i web.xml filen så at serveren kan finde min nye FilSkriverServlet.class fil. Det gør jeg sådan og i web browseren ser det sådan ud efter at jeg har køre nogle tekster igennem... Hvis jeg trykker på GemTekst igen, så vil resultatet se sådan ud... Nu har vi en dynamisk web side, og det er kun fantasien som stop er. Man kunne sagtens forestille sig, at text filen som vi har i dette eksempel blev udskifte med en database og en udvidelse af textboxe osv. Men jeg håber at have vist den grundlæggende ide med servlets og at du kan få Tomcat, BlueJ at køre sammen så at du kan lave SERVLETS. Tak for denne gang. Jákup Wenningstedt Hansen.