Dag iedereen! U raakt vertrouwd met servlets als basisconcept van webontwikkeling en u kunt een eenvoudige toepassing schrijven die ze gebruikt. Om onnodige handelingen te voorkomen, beginnen we niet vanaf nul. We blijven werken aan onze applicatie uit mijn vorige artikel over Hibernate . Maar aangezien we nog maar net beginnen kennis te maken met servlets, heb ik alles met betrekking tot de klasse Auto uit de toepassing verwijderd en alleen de klasse User en de bijbehorende acties overgelaten. Het project zal als volgt worden gestructureerd: Dus, servlets! Wikipedia stelt: "Een Java-servlet is een Java-softwarecomponent die de mogelijkheden van een server uitbreidt. Hoewel servlets op veel soorten verzoeken kunnen reageren, implementeren ze meestal webcontainers voor het hosten van webapplicaties op webservers en kwalificeren ze zich dus als een server- side servlet web-API." Dit is precies waar. Hier komen we voor het eerst het concept tegen van een 'client-server applicatie-architectuur'. In de kern is het vrij eenvoudig. De client krijgt toegang tot de server door een HTTP-verzoek te verzenden. De server genereert de benodigde gegevens (haalt deze bijvoorbeeld op uit een database) en stuurt deze terug naar de client. Het eenvoudigste voorbeeld is wanneer u op de knop "Vrienden" op een bepaald sociaal netwerk klikt en daarmee een verzoek naar de server stuurt. De server werkt de lijst met uw vrienden in de database bij en stuurt deze naar u (de client) terug. De lijst met HTTP-verzoeken is vrij groot, dus als u ze nog nooit eerder bent tegengekomen, kunt u er het beste elders over lezen, bijvoorbeeldhier . Ons doel is om: Een CRUD-toepassing te maken met behulp van servlets. De applicatie moet in staat zijn om gebruikers aan te maken, te lezen, bij te werken en te verwijderen uit de database met behulp van een servlet die HTTP-aanvragen verwerkt. Onze toepassing uit het Hibernate-artikel kon dit al doen, maar werd rechtstreeks vanuit Java-code aangestuurd, meer bepaald vanuit de methode main(). Deze keer is het de klant die de verzoeken verstuurt, dus jij :) Het eerste wat we moeten doen is nieuwe afhankelijkheden toevoegen aan ons pom.xml-bestand.
<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>com.itis4</groupId>
<artifactId>UsersDaoProject</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
</plugin>
</plugins>
</build>
<dependencies>
<!-- PostgreSQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4.1212.jre7</version>
</dependency>
<!-- Hibernate 5.2.6 Final -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.6.Final</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
</dependencies>
</project>
We hebben 3 afhankelijkheden toegevoegd:
- De javax.servlet-api-bibliotheek zelf
- De JSTL-tagbibliotheek. Het is nodig om de clientzijde te maken, namelijk de JSP-pagina's
- Spring-WebMVC. We hebben één voorjaarsles nodig, waarover we later zullen praten.
- Als er geen servlet in de container zit:
- De servletklasse wordt geladen door de container.
- De container maakt een instantie van de servletklasse.
- De container roept de methode init() aan. Deze methode initialiseert de servlet en wordt eerst aangeroepen voordat de servlet verzoeken kan verwerken. Gedurende de gehele levenscyclus wordt de methode init() slechts één keer aangeroepen.
- Bedien het verzoek van de klant. Elk verzoek wordt verwerkt op zijn eigen aparte thread. De container roept voor elk verzoek de methode service() aan. Deze methode bepaalt het type inkomend verzoek en stuurt het naar de juiste methode voor verwerking. De servletontwikkelaar moet implementaties voor deze methoden leveren. Als er een verzoek binnenkomt voor een handler die niet is geïmplementeerd, wordt de methode van de bovenliggende klasse aangeroepen en wordt meestal een fout teruggestuurd naar de aanvrager.
- Als de container de servlet moet verwijderen, roept hij de methode destroy() aan, waardoor de servlet buiten werking wordt gesteld. Net als de methode init() wordt deze methode ook één keer aangeroepen tijdens de hele servletcyclus.
package servlets;
import models.User;
import services.UserService;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
public class UserSimpleServlet extends HttpServlet {
private UserService service = new UserService();
public void init(ServletConfig servletConfig) {
try {
super.init(servletConfig);
} catch (ServletException e) {
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<User> users = service.findAllUsers();
req.setAttribute("users", users);
RequestDispatcher dispatcher = req.getRequestDispatcher("/showUsers.jsp");
dispatcher.forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String name = req.getParameter("name");
int age = Integer.parseInt(req.getParameter("age"));
User user = new User(name, age);
service.saveUser(user);
resp.sendRedirect("/users");
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id = Integer.parseInt(req.getParameter("id"));
User user = service.findUser(id);
user.setName(req.getParameter("name"));
user.setAge(Integer.parseInt(req.getParameter("age")));
service.updateUser(user);
resp.sendRedirect("/users");
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException {
int id = Integer.parseInt(req.getParameter("id"));
service.deleteUser(service.findUser(id));
resp.sendRedirect("/users");
}
}
Zoals je kunt zien, bevat het de init() methode, die hierboven is beschreven, en implementeert het 4 methoden die samenvallen met vier HTTP-verzoeken: doPost(), doGet(), doPut() en doDelete(). Ze laten ons gebruikers aanmaken, lezen, updaten en verwijderen. De methoden accepteren instanties van de klassen javax.servlet.http.HttpServletRequest en javax.servlet.http.HttpServletResponse als invoer, dwz verzoeken die naar de server worden verzonden en antwoorden die door de client worden ontvangen. Intern roepen de methoden de relevante methoden van de klasse UserService aan en wordt er een antwoord voor de client gegenereerd en omgeleid naar de URL /users. In de methode doGet() krijgen we bijvoorbeeld een lijst met alle gebruikers. Vervolgens maken we een RequestDispatcher-object, waarmee we objecten kunnen opnemen in een HTTP-verzoek en dit kunnen omleiden naar een specifieke bron (bijvoorbeeld naar een JSP-clientpagina). In de methode doPut() (die gebruikersgegevens bijwerkt), verwerken we een HTTP-verzoek, extraheren we de id-, naam- en leeftijdsparameters, vinden we de gebruiker met het opgegeven id, wijzen hem de naam en leeftijd toe die in het verzoek staan, en retourneren naar de /users-pagina. Maar om al deze methoden correct te laten werken, moeten we de servlet configureren. Hiervoor gebruiken we het bestand web.xml in de map WEB-INF.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1"
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">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>UserSimpleServlet</servlet-name>
<servlet-class>servlets.UserSimpleServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserSimpleServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<servlet-name>UserSimpleServlet</servlet-name>
</filter-mapping>
</web-app>
Alle tags in dit bestand zijn redelijk intuïtief, maar laten we ze in volgorde doornemen. <welcome-file-list> - De JSP-startpagina wordt aangegeven, die als eerste wordt geopend wanneer de applicatie start. In ons geval is dat index.jsp. <servlet> - Registratie van onze UserSimpleServlet-klasse als een servlet. <servlet-mapping> - een zeer belangrijke tag. Het definieert de URL's die door de servlet zullen worden verwerkt. In ons geval zijn het allemaal URL's, dus we geven gewoon "/" aan. Maar als we een applicatie hadden waarbij gebruikers en hun auto's (auto's) betrokken waren, dan zouden we een tweede servlet kunnen maken (SimpleAutoServlet). De toewijzing van de gebruikersservlet zou dan "/users" zijn (dwz verzoeken over gebruikers), en de toewijzing van de automatische servlet zou "/autos" zijn. En tot slot, <filter>. Intern definieert het een exemplaar van de organisatie. springframework.web.filter.HiddenHttpMethodFilter klasse. Dit artikel gaat niet over de lente, dus ik zal het niet in detail beschrijven. Ik zal alleen zeggen dat het alleen als extra functie in onze applicatie is geschroefd. Het punt is dat we JSP-pagina's gaan gebruiken om de clientzijde te maken. Onze gegevens worden op de pagina weergegeven als een tabel met een lijst met gebruikers. Binnen de JSP-pagina's worden <form/> HTML-tags gebruikt. Maar alleen HTTP GET- en POST-verzoeken kunnen worden gebruikt voor het verzenden van gegevens vanuit een <formulier/>. Met andere woorden, voor alle drie de bewerkingen - bijwerken, verwijderen en een gebruiker maken - zouden we alleen POST-verzoeken moeten gebruiken. Het gebruik van PUT- en DELETE-verzoeken zou voor ons geen optie zijn. In principe is dit vrij normaal en gemakkelijk te implementeren, maar de klasse HiddenHttpMethodFilter laat ons ze gebruiken. Op deze manier, de lezer zal duidelijker het verschil zien tussen bewerkingen in de applicatie. Laten we ten slotte doorgaan naar de clientzijde. Het wordt vertegenwoordigd door vijf JSP-pagina's. index.jsp.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Hello!</title>
</head>
<body>
If you want to start working with the user database,<br>
click the button below:
<form action = "users" method="get">
<input type="submit" value="Start working with database">
</form>
</body>
</html>
addUser.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Add new user</title>
</head>
<body>
<form action = "/users" method="post">
<input required type="text" name="name" placeholder="Name">
<input required type="text" name="age" placeholder="Age">
<input type="submit" value="Save">
</form>
</body>
</html>
deleteUser.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Delete user</title>
</head>
<body>
Are you sure you want to delete the user ${param.id}?
&lform action="/users/${param.id}" method="post">
<input type="hidden" name="id" value="${param.id}">
<input type="hidden" name="_method" value="delete">
<input type="submit" value="Delete">
</form>
</body>
</html>
showUsers.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>User list</title>
</head>
<body>
<table border="2">
<tr>
<td>ID</td>
<td>Name</td>
<td>Age</td>
<td>Actions</td>
</tr>
<c:forEach items="${users}" var = "user">
<tr>
<td>${user.getId()}</td>
<td>${user.getName()}</td>
<td>${user.getAge()}</td>
<td>
<form action = "updateUser.jsp" method="post">
<input type="hidden" name="id" value="${user.getId()}">
<input type="hidden" name="name" value="${user.getName()}">
<input type="hidden" name="age" value="${user.getAge()}">
<input type="submit" value="Modify" style="float:left">
</form>
<form action="deleteUser.jsp" method="post">
<input type="hidden" name="id" value="${user.getId()}">
<input type="submit" value="Delete" style="float:left">
</form></td>
</tr>
</c:forEach>
</table>
<form action = "addUser.jsp">
<input type="submit" value="Add new user">
</form>
</body>
</html>
updateUser.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Modify user data</title>
</head>
<body>
Edit user
<form action="/users/${param.id}" method="post">
<input type="hidden" name = "id" value="${param.id}">
<input type="text" name="name" value="${param.name}" placeholder=${param.name}>
<input type="text" name="age" value="${param.age}" placeholder=${param.age}>
<input type="hidden" name="_method" value="put">
<input type="submit" value="Update">
</form>
</body>
</html>
Een JSP-pagina (JavaServer Page) bevat twee typen tekst: statische brongegevens die kunnen worden opgemaakt als tekst (HTML, SVG, WML of XML) en JSP-elementen die worden gebruikt om dynamische inhoud samen te stellen. Om u te helpen begrijpen wat een JSP-pagina is, heb ik een passage uit een heel goed artikel gekopieerd. "Kortom, de eerste keer dat een JSP wordt aangevraagd, verandert het in een servlet en werkt het als een servlet. Dit is erg belangrijk om te begrijpen. Een JSP-pagina IS NIET zoals een HTML-pagina - een beginnende programmeur moet duidelijk begrijpen dat dit een andere servlet is "Je hoeft alleen niet te schrijven hoe het wordt weergegeven. Het kan gewoon worden getekend. En waar nodig gegevens toevoegen. Maar omdat een JSP-pagina doet denken aan HTML, zal een ontwerper het natuurlijk gemakkelijker vinden. En nogmaals STERK BENADRUKKEN aan beginners,een JSP-pagina is een SERVLET. Het wordt gegenereerd, inclusief het toevoegen van alle gegevens, op de server. Hier worden alle gegevens ingevoerd. En in de browser krijgt de gebruiker de voltooide HTML-pagina, die geen tekenen van Java vertoont." U kunt er zeker van zijn dat een JSP-pagina echt een servlet is, omdat elke pagina een methode heeft die moet worden uitgevoerd. Index .jsp geeft aan dat wanneer u op de knop "Start werken met de database" klikt, de methode get wordt uitgevoerd (methode = "get"). De pagina addUser.jsp, die verantwoordelijk is voor het aanmaken van nieuwe gebruikers, voert de methode post uit (method = "post") wanneer u op de knop Opslaan klikt. De rest van de JSP-pagina bestaat uit gewone statische HTML-opmaak, dus we zullen er niet verder op ingaan. Dat is een onderwerp voor een ander artikel en er zijn er genoeg over onderwerp op internet. Dus we' we hebben onze applicatie gemaakt! Nu moeten we het in actie testen! Hiervoor hebben we de hierboven genoemde Apache Tomcat-servletcontainer nodig. U kunt de houder downloadenvan de officiële website (ik gebruik versie 8). Vervolgens moeten we een configuratie in IDEA maken om onze applicatie via Tomcat te laten werken. Open hiervoor het tabblad "Configuraties bewerken", maak een nieuwe configuratie aan en selecteer "Tomcat Server Local". Geef op het tabblad "Applicatieserver" het pad naar de Tomcat-map op . Ga vervolgens naar het tabblad "Deployment". Hier configureren we de implementatie van onze applicatie op de lokale server. Druk op "+", selecteer "Artifact" -> YourProjectName:war (we bouwen de applicatie naar een war-bestand). En dat vat het zo ongeveer samen! Op de "Server"-pagina kunt u zien dat onze applicatie zal draaien op http://localhost:8080/. Sla de configuratie op en geef het een naam (ik noem mijn configuratie "Tommy"). Vervolgens zullen we op het tabblad Maven in IDEA (aan de rechterkant) de war-plug-in gebruiken om ons project naar een oorlogsbestand te bouwen (Plug-ins -> oorlog -> oorlog: oorlog). Nadat de build is voltooid, voert u de toepassing uit en wacht u. Succes! De startpagina werd gelanceerd. Nu klikken we op de knop "Begin met werken met de database". Onze index.jsp genereert een GET-verzoek dat door de server wordt verwerkt. De server genereert een antwoord en stuurt dit naar ons terug in de vorm van een lijst van alle bestaande gebruikers (ervan uitgaande dat er natuurlijk gebruikers in de database zijn). En daar zijn ze! Dat daar heb je het! Je hebt je eerste applicatie geschreven met behulp van Java-servlets. Dat was niet zo erg, toch? :) Voor huiswerk zou je de autofunctionaliteit uit het vorige artikel kunnen herstellen. Met andere woorden, maak een aparte servlet en JSP-pagina's voor auto's en leer de toepassing hoe de auto's van een gebruiker in een lijst moet worden weergegeven, hoe nieuwe auto's aan een gebruiker kunnen worden toegevoegd en hoe deze kunnen worden bewerkt en verwijderd. PS-servlets en JavaServer-pagina's zijn vrij oude technologieën. Op internet kun je vaak opmerkingen vinden als "Wie heeft deze oude rotzooi nodig?" Het antwoord is vrij eenvoudig: voornamelijk mensen die aan echte projecten zullen werken, waar ze mogelijk veel code tegenkomen die deze technologieën gebruikt. En zelfs zonder te begrijpen hoe het werkt, is het nog steeds leuk om "oude rotzooi" op te knippen tot iets nieuws :) Voor een meer grondige studie van JSP en servlets, kun je het boek "Head First Servlets and JSP" raadplegen. Het is geschreven door dezelfde auteurs als het beroemde superboek "Head First Java", dat velen zullen beschouwen als een garantie voor kwaliteit :) Ik hoop dat dit artikel nuttig is geweest! Bedankt voor je aandacht en veel succes met leren!
GO TO FULL VERSION