CodeGym /Java blogg /Slumpmässig /Skapa en enkel webbapplikation med servlets och JSP:er (d...
John Squirrels
Nivå
San Francisco

Skapa en enkel webbapplikation med servlets och JSP:er (del 1)

Publicerad i gruppen
Kunskaper som krävs för att förstå artikeln: Du har redan mer eller mindre listat ut Java Core och skulle vilja titta på JavaEE-teknologier och webbprogrammering . Det skulle vara mest meningsfullt för dig att för närvarande studera Java Collections-uppdraget , som behandlar ämnen nära artikeln.
Skapa en enkel webbapplikation med servlets och JSP:er (del 1) - 1
Detta material är den logiska fortsättningen på min artikel Skapa det enklaste webbprojektet i IntelliJ Idea Enterprise . I den artikeln visade jag hur man skapar en fungerande webbprojektmall. Den här gången ska jag visa dig hur du skapar en enkel men helt attraktiv webbapplikation med Java Servlet API och JavaServer Pages API . Vår applikation kommer att ha en hemsida med två länkar:
  • en länk till en sida för att lägga till användare;
  • en länk till användarlistan.
Som tidigare kommer jag att använda IntelliJ Idea Enterprise Edition , Apache Maven (vi kopplar bara några beroenden) och Apache Tomcat . I slutändan kommer vi att "försköna" vår applikation med W3.CSS -ramverket. Vi antar att du redan har ett tomt projekt som vi nu ska lägga till. Om inte, gå igenom den första artikeln och gör en. Det tar bara några minuter :)

Lite om vår framtida applikations struktur

Vår hemsida (/) kommer att vara en högst vanlig statisk HTML- sida med en rubrik och två länkar/knappar:
  • lägg till en ny användare (navigerar till / add );
  • visa listan över användare (navigerar till / lista ).
Tomcat kommer att fånga förfrågningar för dessa adresser och skicka dem till en av de två servlets som vi ska göra (vi specificerar mappningen i web.xml ). Servletarna kommer sedan att bearbeta förfrågningarna, förbereda data (eller spara data, om vi lägger till en användare) och överföra kontrollen till lämpliga JSP-filer , som sedan "renderar" resultatet. Vi lagrar data i en vanlig vaniljlista (lista).

Skapa en statisk hemsida

Om du index.jsp i din webbmapp, ta bort den. Skapa istället en enkel HTML-fil som heter index.html i denna mapp:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My super project!</title>
</head>
<body>
    <!-- header -->
    <div>
        <h1>Super app!<//h1>
    </div>

    <div>       <!-- content -->
        <div>    <!-- button holder -->
            <button onclick="location.href='/list'">List users<//button>
            <button onclick="location.href='/add'">Add user<//button>
        </div>
    </div>
</body>
</html>
Det är inget komplicerat här. I titeltaggen anger vi titeln på vår sida. I sidkroppen har vi två huvudavdelningar: header och content . Innehålls -div innehåller en hållare för våra knappar. Och där har vi två knappar som tar dig till motsvarande adress med ett klick. Du kan köra projektet och se hur det ser ut nu. Om du klickar på knapparna får du 404-felsidor, eftersom vi motsvarande sidor inte finns ännu. Men vi kan säga att knapparna fungerar. Observera att detta inte är det mest universella tillvägagångssättet: om JavaScript är avstängt i webbläsaren, fungerar inte dessa knappar. Men vi antar att ingen inaktiverar JavaScript. :) Självklart kan du klara dig med enkla länkar, men jag föredrar knappar. Du kan göra det hur du vill. Och oroa dig inte för det faktum att mina exempel kommer att ha många divs . Vi kommer att fylla dem med stilar senare, och allt kommer att se vackrare ut. :)

Skapa JSP-filer för att rendera resultatet

Skapa en mapp i samma webbkatalog där vi lägger till våra JSP-filer . Jag kallade det " vyer ", men återigen kan du improvisera. I den här mappen skapar vi två JSP-filer:
  • add.jsp — en sida för att lägga till användare;
  • list.jsp — sida för att visa listan över användare.
Tilldela lämpliga sidrubriker till dem. Något som " Lägg till ny användare " och " Användarlista ", så lämnar vi det så.

Skapa två servlets

Servlets kommer att ta emot och behandla förfrågningarna som Tomcat skickar dem. I mappen src/main/java skapar du apppaketet , där vi lägger vår källkod. Andra paket kommer också dit. Så för att förhindra att dessa paket skapas inuti varandra skapar vi en klass i apppaketet ( vi tar bort det senare). Skapa nu tre olika paket i apppaketet :
  • entiteter — våra entiteter (klassen som beskriver användarobjekt) går hit;
  • modell — det är här vår modell går (vi ska prata om detta lite senare);
  • servlets — och det är här våra servlets går.
När du har gjort detta kan du lugnt ta bort den klassen från apppaketet (om du skapat den förstås). Skapa två klasser i servlets -paketet:
  • AddServlet — behandlar förfrågningar som skickas till/ lägg till ;
  • ListServlet — behandlar förfrågningar som skickas till / list .

Anslutande beroenden i Maven

Tomcat 9. * implementerar specifikationerna för Servlet 4.0 och JavaServer Pages 2.3 . Det är vad som står i den andra raden i första stycket i Tomcat 9:s officiella dokumentation. Det betyder att om du, som jag, använder den här versionen av Tomcat , så kommer koden du kommer att skriva och köra att använda dessa versioner. Men vi skulle vilja ha dessa specifikationer i vårt projekt, så att vår kod, som använder dem, åtminstone kompileras framgångsrikt. Och för att göra detta måste vi ladda dem i vårt projekt. Det är här Maven kommer till undsättning.

Den allmänna regeln är denna: om du behöver ansluta något till ditt projekt med Maven:

  • gå till arkivets webbplats från Maven;
  • hitta den nödvändiga versionen av det nödvändiga biblioteket;
  • hämta beroendekoden som måste klistras in i din pom.xml;
  • klistra! :)
Låt oss börja. Förbered först POM-filen . Någonstans efter /version- posten, men före /project , infogar du följande:

<dependencies>

</dependencies>
Vi gör detta för att indikera att vi kommer att lista de nödvändiga beroenden inom dessa taggar. Gå nu till mvnrepository.com . Det finns ett sökfält överst. För att börja, sök efter ' servlet '. Det första resultatet, som har använts mer än sju tusen gånger, passar oss. Kom ihåg att vi behöver version 4.0 (för Tomcat 9). Andra versioner kan vara lämpliga för äldre implementeringar. Det här är en ganska ny version, så det finns inte så många användningsområden. Men vi behöver det. En sida öppnas där du kan få koden för detta beroende för en mängd olika pakethanterare, eller så kan du helt enkelt ladda ner den. Men eftersom vi vill ansluta den med Maven, väljer vi koden på Maven-fliken. Vi kopierar och klistrar in i beroendedelen av vår POM-fil. Om du får ett meddelande som frågar om du vill aktivera automatisk import i det nedre högra hörnet av IDEA , gå vidare och godkänn det. Om du av misstag vägrade, gå till " Inställningar " och aktivera automatisk import manuellt: Inställningar (Ctrl + Alt + S) -> Build, Execution, Deployment -> Maven -> Importing .och IDEA-konfigurationsfilerna för detta projekt synkroniserat. Enligt samma princip kommer vi att hitta och ansluta JavaServer Pages 2.3 (sök efter "JSP"). Och eftersom vi redan har startat Maven, låt oss bara berätta att våra källfiler följer Java 8-syntaxen och att vi måste kompilera dem till bytekod för den versionen. Efter alla dessa steg kommer vår pom.xml att se ut ungefär så här:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cc.codegym.info.fatfaggy</groupId>
    <artifactId>my-super-project</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compile.source>1.8</maven.compile.source>
        <maven.compile.target>1.8</maven.compile.target>
    </properties>

    <dependencies>
        <!-- Servlet API 4.0 for tomcat 9 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- JavaServer Pages API 2.3 for tomcat 9 -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

</project>

Gör våra servlets till riktiga servlets

För tillfället är paret servlets vi skapade faktiskt vanliga klasser. De har ingen funktionalitet. Men nu har vi kopplat Servlet API till vårt projekt, och därför kan vi använda dess klasser. För att göra våra servlets "riktiga", allt vi behöver göra är att få dem att ärva HttpServlet -klassen.

Kartläggning eller markering

Nu skulle det vara trevligt att på något sätt berätta för Tomcat att förfrågningar om / add - adressen behandlas av vår AddServlet , och förfrågningar om / list - adressen hanteras av ListServlet . Denna process kallas mappning (markup). Detta görs i web.xml enligt samma princip:
  • för att starta, beskriv servleten (ange ett namn och ange sökvägen till själva klassen);
  • bind sedan denna servlet till en specifik adress (ange servletens namn, som vi precis gav den, och ange adressen vars förfrågningar ska skickas till denna servlet).
Beskriv servletten:

<servlet>
    <servlet-name>add</servlet-name>
    <servlet-class>app.servlets.AddServlet</servlet-class>
</servlet>
Bind den nu till adressen:

<servlet-mapping>
    <servlet-name>add</servlet-name>
    <url-pattern>/add</url-pattern>
</servlet-mapping>
Som du kan se är servlet-namn detsamma i båda fallen. Som ett resultat vet Tomcat att om en begäran om /add tas emot måste den skickas till app.servlets.AddServlet. Vi gör samma sak med den andra servletten. I slutändan har vår web.xml ungefär följande innehåll:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- add servlet -->
    <servlet>
        <servlet-name>add</servlet-name>
        <servlet-class>app.servlets.AddServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>add</servlet-name>
        <url-pattern>/add</url-pattern>
    </servlet-mapping>

    <!-- list servlet -->
    <servlet>
        <servlet-name>list</servlet-name>
        <servlet-class>app.servlets.ListServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>list</servlet-name>
        <url-pattern>/list</url-pattern>
    </servlet-mapping>
</web-app>
Förresten, vi skapade inte uppmärkning för startsidan (/). Faktum är att vi inte behöver det i det här fallet. Vår hemsida är en enkel HTML-fil som bara visar två knappar. Den har inget dynamiskt innehåll, så vi behöver inte skapa en separat servlet för förfrågningar från / som inte gör något annat än att vidarebefordra exekvering till någon JSP (som också skulle behöva skapas) för att rita två knappar åt oss. Vi behöver inte det här. En statisk sida passar oss. När Tomcat tar emot en förfrågan kommer den att kontrollera om det finns en enda servlet som kan behandla förfrågan för den adressen, och kommer sedan att se att den här adressen faktiskt redan innehåller den färdiga HTML- filen, som den kommer att servera. Vi kan köra vår applikation igen (starta om servern eller distribuera om den igen – vad du än föredrar) och se till att hemsidan renderas, att inget gick sönder och att övergångarna inträffar när vi klickar på knapparna (även om vi återigen får ett felmeddelande). Förresten, medan vi innan fick ett 404-fel, får vi nu ett 405. Det betyder att mappningen fungerade och servletarna hittades, men de hade ingen lämplig metod för att hantera begäran.

Kort avvikelse: vad händer "under huven"?

Du har förmodligen redan tänkt på hur vår applikation fungerar i Tomcat. Vad händer där inne? Och var är main()-metoden? Så fort du går till localhost:8080 i din webbläsare skickar webbläsaren en förfrågan till denna adress med hjälp av HTTP-protokollet. Jag hoppas att du redan är medveten om att det finns många olika typer av förfrågningar, och de mest populära är GET och POST. Varje begäran bör besvaras. En GET-begäran förväntas få ett svar med färdig HTML-kod, som returneras till webbläsaren. Webbläsaren ersätter sedan koden för alla vackra bokstäver, knappar och formulär. En POST-förfrågan är lite mer intressant, eftersom den också innehåller en del information. Anta till exempel att du anger inloggningsuppgifter i ett registrerings- eller inloggningsformulär på en webbplats och klickar på "Skicka". Detta gör att en POST-förfrågan med din personliga information skickas till servern. Servern tar emot denna information, bearbetar den och returnerar något svar (till exempel en HTML-sida med din profil). Den huvudsakliga skillnaden mellan dem är att GET-förfrågningar endast används för att hämta data från servern, medan POST-förfrågningar innehåller viss information (och data på servern kan ändras). När du till exempel laddar upp din bild till servern bärs den dit i en POST-förfrågan och servern lägger till den i databasen, det vill säga en ändring sker. Nu tillbaka till Tomcat. När den får en förfrågan från en klient tittar den på adressen. Den kontrollerar om det finns en lämplig servlet för att behandla förfrågningar för den adressen (eller en tillgänglig resurs som kan returneras omedelbart). Om den inte hittar något att returnera, då svarar den med ett 404-fel snarare än en HTML-sida. Men om den hittar en lämplig servlet som "sitter" på den adressen, så tittar den på förfrågningstypen (GET, POST eller något annat) och frågar servleten om den har en metod som kan hantera den här typen av frågor. Om servleten säger att den inte vet hur den ska hantera den här typen, dåTomcat returnerar en 405-kod. Och detta är precis vad som hände i vårt projekt. Men om en lämplig servlet hittas och den har en lämplig metod, skapar Tomcat ett servletobjekt, startar det på en ny tråd(som låter den köras på egen hand), och Tomcat fortsätter sitt eget arbete, accepterar och skickar förfrågningar. Dessutom skapar Tomcat ytterligare två objekt: en HttpServletRequest (som jag förkortar kallar "request") och en HttpServletResponse (som jag kallar "svaret"). Den lägger all data som tas emot från klientens begäran i det första objektet, så att all data kan extraheras från den. Och sedan efter allt detta skickar den dessa två dessa objekt till lämplig metod för servleten som startades på en separat tråd. Så fort servletten är klar med sitt arbete och har ett svar redo att skickas till klienten, viftar den med en flagga mot Tomcat och säger "Jag är klar. Allt är klart". Tomcat tar emot svaret och skickar det till klienten. Detta gör att Tomcat kan ta emot förfrågningar och skicka svar, utan att bli distraherad, och allt arbete utförs av servlets som körs på separata trådar. Det betyder att när vi skriver servletkoden bestämmer vi vilket arbete som ska utföras. Och du kan tänka dig att main()-metoden är placerad inuti själva Tomcat (ja, den är skriven i Java), och när vi "startar" Tomcat, startas main()-metoden. Skapa en enkel webbapplikation med servlets och JSP:er (del 1) - 2

Använd servlets för att fånga GET-metoder och skicka superenkla svar

För tillfället har våra servlets inga lämpliga metoder (GET), så Tomcat returnerar ett 405-fel. Låt oss skapa dem! Klassen HttpServlet, vi våra servlets ärver, deklarerar olika metoder. För att tilldela specifik kod till metoderna åsidosätter vi dem helt enkelt. I det här fallet måste vi åsidosätta doGet()metoden i båda servletarna.

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}
Som du kan se tar den här metoden två argument: req (begäran) och resp (svar). Det är just dessa objekt som Tomcat skapar och fyller på åt oss när den anropar lämplig metod i servleten. Till att börja med skapar vi de enklaste svaren. För att göra detta tar vi resp-objektet och hämtar ett PrintWriter-objekt från det. Den här typen av objekt används för att komponera ett svar. Vi kommer att använda den för att mata ut en enkel sträng.

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    PrintWriter writer = resp.getWriter();
    writer.println("GET method from AddServlet");
}
Vi kommer att göra något liknande i ListServlet, och sedan startar vi om vår server. Som ni ser fungerar allt! När du klickar på knapparna får du upp sidor med texten som vi "skrivit" med PrintWriter. Men JSP-filerna som vi förberedde för att generera sidor med svar används inte. Det beror helt enkelt på att de aldrig avrättas. Vår servlet skapar själva svaret och kör klart och signalerar till Tomcat att den är redo att svara klienten. Tomcat tar bara svaret och skickar tillbaka det till klienten. Låt oss överföra kontrollen från servletarna till JSP-filerna. Vi kommer att ändra koden för våra metoder enligt följande:
  • vi hämtar ett förfrågningsavsändarobjekt från förfrågningsobjektet och skickar det adressen till JSP-sidan som vi vill överföra kontrollen till;
  • vi använder det här objektet för att överföra kontrollen till den angivna JSP-sidan, utan att glömma att skicka förfrågnings- och svarsobjekten vi fick från Tomcat.

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp");
    requestDispatcher.forward(req, resp);
}
I body-taggen på JSP-sidorna kan du lägga till något så att vi tydligt kan se vilken sida som visas. När du har gjort det, starta om servern och kontrollera. Vi klickar på knapparna på huvudsidan och sidorna öppnas, vilket betyder att förfrågningarna skickas till servletarna. Sedan överförs kontrollen till JSP-sidorna, som nu renderas. Det var allt tills vidare. I nästa del av den här artikeln kommer vi att arbeta med funktionaliteten i vår applikation.
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION