Xin chào tất cả mọi người! Bạn sẽ làm quen với servlet như một khái niệm cơ bản về phát triển web và bạn sẽ có thể viết một ứng dụng đơn giản sử dụng chúng. Để tránh những hành động không cần thiết, chúng tôi sẽ không bắt đầu lại từ đầu. Chúng ta sẽ tiếp tục làm việc với ứng dụng của mình từ bài viết trước của tôi về Hibernate . Nhưng vì chúng ta mới bắt đầu làm quen với servlet nên tôi đã loại bỏ mọi thứ liên quan đến lớp Auto khỏi ứng dụng và chỉ để lại lớp User và các hành động liên quan đến nó. Dự án sẽ được cấu trúc như thế này: Vì vậy, servlet! Wikipedia tuyên bố: "Một Java servlet là một thành phần phần mềm Java giúp mở rộng khả năng của máy chủ. Mặc dù các servlet có thể đáp ứng nhiều loại yêu cầu, nhưng chúng thường triển khai các bộ chứa web để lưu trữ các ứng dụng web trên máy chủ web và do đó đủ tiêu chuẩn là máy chủ- API web bên dịch vụ." Điều này hoàn toàn đúng. Ở đây, lần đầu tiên chúng ta bắt gặp khái niệm về "kiến trúc ứng dụng máy khách-máy chủ". Nó khá đơn giản ở cốt lõi của nó. Máy khách truy cập máy chủ bằng cách gửi yêu cầu HTTP. Máy chủ tạo dữ liệu cần thiết (ví dụ: tìm nạp dữ liệu từ cơ sở dữ liệu) và trả lại cho máy khách. Ví dụ đơn giản nhất là khi bạn nhấp vào nút "Bạn bè" trên một mạng xã hội nhất định, từ đó gửi yêu cầu đến máy chủ. Máy chủ cập nhật danh sách bạn bè của bạn trong cơ sở dữ liệu và trả về cho bạn (máy khách). Danh sách các yêu cầu HTTP khá lớn, vì vậy nếu bạn chưa từng gặp chúng trước đây, thì tốt nhất bạn nên đọc về chúng ở nơi khác, ví dụ:đây . Mục tiêu của chúng tôi là: Tạo một ứng dụng CRUD bằng các servlet. Ứng dụng phải có khả năng tạo, đọc, cập nhật và xóa người dùng khỏi cơ sở dữ liệu bằng cách sử dụng một servlet xử lý các yêu cầu HTTP. Ứng dụng của chúng tôi từ bài báo Hibernate đã có thể thực hiện việc này, nhưng nó được điều khiển trực tiếp từ mã Java, chính xác hơn là từ phương thức main(). Lần này, chính khách hàng sẽ gửi yêu cầu, tức là bạn :) Điều đầu tiên chúng ta cần làm là thêm các phụ thuộc mới vào tệp pom.xml của mình.
<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>
Chúng tôi đã thêm 3 phụ thuộc:
- Bản thân thư viện javax.servlet-api
- Thư viện thẻ JSTL. Nó sẽ là cần thiết để tạo phía máy khách, cụ thể là các trang JSP
- Mùa xuân-WebMVC. Chúng ta sẽ cần một lớp Spring, chúng ta sẽ nói về lớp này sau.
- Nếu không có servlet trong vùng chứa:
- Lớp servlet được tải bởi vùng chứa.
- Bộ chứa tạo một thể hiện của lớp servlet.
- Container gọi phương thức init(). Phương thức này khởi tạo servlet và được gọi trước, trước khi servlet có thể phục vụ các yêu cầu. Trong toàn bộ vòng đời, phương thức init() chỉ được gọi một lần.
- Dịch vụ khách hàng yêu cầu. Mỗi yêu cầu được xử lý trên luồng riêng biệt của nó. Vùng chứa gọi phương thức service() cho mỗi yêu cầu. Phương thức này xác định loại yêu cầu đến và gửi nó đến phương thức thích hợp để xử lý. Nhà phát triển servlet phải cung cấp các triển khai cho các phương pháp này. Nếu một yêu cầu đến cho một trình xử lý không được triển khai, thì phương thức của lớp cha được gọi và thường kết thúc bằng việc trả về một lỗi cho người yêu cầu.
- Nếu bộ chứa cần loại bỏ servlet, nó sẽ gọi phương thức hủy(), phương thức này sẽ đưa servlet ra khỏi hoạt động. Giống như phương thức init(), phương thức này cũng được gọi một lần trong toàn bộ chu trình của servlet.
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");
}
}
Như bạn có thể thấy, nó chứa phương thức init(), được mô tả ở trên và triển khai 4 phương thức trùng khớp với 4 yêu cầu HTTP: doPost(), doGet(), doPut() và doDelete(). Họ cho phép chúng tôi tạo, đọc, cập nhật và xóa người dùng. Các phương thức chấp nhận các thể hiện của các lớp javax.servlet.http.HttpServletRequest và javax.servlet.http.HttpServletResponse làm đầu vào, tức là các yêu cầu được gửi đến máy chủ và các phản hồi mà máy khách nhận được. Trong nội bộ, các phương thức gọi các phương thức có liên quan của lớp UserService và phản hồi cho ứng dụng khách được tạo và chuyển hướng đến URL /users. Ví dụ, trong phương thức doGet(), chúng ta có một danh sách tất cả người dùng. Tiếp theo, chúng ta tạo một đối tượng RequestDispatcher, đối tượng này cho phép chúng ta đưa các đối tượng vào một yêu cầu HTTP và chuyển hướng nó đến một tài nguyên cụ thể (ví dụ: đến một trang JSP máy khách). Trong phương thức doPut() (cập nhật dữ liệu người dùng), chúng tôi xử lý một yêu cầu HTTP, trích xuất các tham số id, tên và tuổi, tìm người dùng có id được chỉ định, gán cho nó tên và tuổi trong yêu cầu và trả về đến trang/người dùng. Nhưng để tất cả các phương thức này hoạt động chính xác, chúng ta cần cấu hình servlet. Để làm điều này, chúng tôi sử dụng tệp web.xml trong thư mục 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>
Tất cả các thẻ trong tệp này khá trực quan, nhưng hãy xem qua chúng theo thứ tự. <welcome-file-list> - Trang bắt đầu JSP được chỉ định, trang này sẽ được mở đầu tiên khi ứng dụng khởi động. Trong trường hợp của chúng tôi, đây là index.jsp. <servlet> - Đăng ký lớp UserSimpleServlet của chúng ta như một servlet. <servlet-mapping> - một thẻ rất quan trọng. Nó xác định các URL sẽ được xử lý bởi servlet. Trong trường hợp của chúng tôi, đó là tất cả các URL, vì vậy chúng tôi chỉ cần chỉ ra "/". Nhưng nếu chúng ta có một ứng dụng liên quan đến người dùng và ô tô của họ (ô tô), thì chúng ta có thể tạo một servlet thứ hai (SimpleAutoServlet). Sau đó, ánh xạ của servlet người dùng sẽ là "/users" (nghĩa là các yêu cầu về người dùng) và ánh xạ của servlet tự động sẽ là "/autos". Và cuối cùng, <bộ lọc>. Bên trong, nó định nghĩa một thể hiện của org. lớp springframework.web.filter.HiddenHttpMethodFilter. Bài viết này không nói về Spring nên tôi sẽ không mô tả chi tiết. Tôi sẽ chỉ nói rằng nó chỉ được đưa vào ứng dụng của chúng tôi như một tính năng bổ sung. Vấn đề là chúng ta sẽ sử dụng các trang JSP để tạo phía máy khách. Dữ liệu của chúng tôi sẽ được hiển thị trên trang dưới dạng bảng có danh sách người dùng. Bên trong các trang JSP, các thẻ HTML <form/> sẽ được sử dụng. Nhưng chỉ có thể sử dụng các yêu cầu HTTP GET và POST để gửi dữ liệu từ <form/>. Nói cách khác, đối với cả ba thao tác — cập nhật, xóa và tạo người dùng — chúng ta sẽ chỉ phải sử dụng các yêu cầu POST. Sử dụng các yêu cầu PUT và DELETE sẽ không phải là một tùy chọn cho chúng tôi. Về nguyên tắc, điều này khá bình thường và dễ thực hiện nhưng lớp HiddenHttpMethodFilter cho phép chúng ta sử dụng chúng. Bằng cách này, người đọc sẽ thấy rõ hơn sự khác biệt giữa các thao tác trong ứng dụng. Cuối cùng, hãy chuyển sang phía khách hàng. Nó được đại diện bởi năm trang JSP. chỉ mục.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>
xóaUser.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>
cập nhậtUser.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>
Trang JSP (Trang JavaServer) chứa hai loại văn bản: dữ liệu nguồn tĩnh có thể được định dạng dưới dạng văn bản (HTML, SVG, WML hoặc XML) và các phần tử JSP được sử dụng để xây dựng nội dung động. Để giúp bạn hiểu trang JSP là gì, tôi đã sao chép một đoạn văn từ một bài báo rất hay. "Về cơ bản, lần đầu tiên một JSP được yêu cầu, nó biến thành một servlet và hoạt động như một servlet. Điều này rất quan trọng cần hiểu. Một trang JSP KHÔNG giống như một trang HTML — một lập trình viên mới bắt đầu phải hiểu rõ rằng đây là một servlet khác — chỉ là bạn không cần phải viết để lập trình cách nó được hiển thị. Nó có thể được vẽ đơn giản. Và thêm dữ liệu khi cần thiết. Nhưng vì một trang JSP gợi nhớ đến HTML, nên một nhà thiết kế rõ ràng sẽ thấy dễ dàng hơn. Và một lần nữa, một lần nữa NHẤN MẠNH MẠNH MẼ cho người mới bắt đầu,một trang JSP là một SERVLET. Nó được tạo, bao gồm cả việc thêm tất cả dữ liệu, trên máy chủ. Đây là nơi tất cả dữ liệu được chèn vào. Và trong trình duyệt, người dùng nhận được trang HTML đã hoàn thành, không có dấu hiệu của Java." Bạn có thể chắc chắn rằng một trang JSP thực sự là một servlet, bởi vì mỗi trang có một phương thức cần được thực thi. Ví dụ: chỉ mục .jsp chỉ ra rằng khi bạn nhấp vào nút "Bắt đầu làm việc với cơ sở dữ liệu", phương thức get sẽ được thực thi (method="get") Trang addUser.jsp chịu trách nhiệm tạo người dùng mới sẽ thực thi phương thức post (method="post") khi bạn nhấp vào nút lưu. Phần còn lại của trang JSP được tạo thành từ đánh dấu HTML tĩnh thông thường, vì vậy chúng tôi sẽ không bàn sâu về nó. Đó là một chủ đề cho một bài viết khác và còn rất nhiều điều về chủ đề này chủ đề trên Internet. Vì vậy, chúng tôi' đã tạo ứng dụng của chúng tôi! Bây giờ chúng ta cần kiểm tra nó trong hành động! Để làm điều này, chúng ta cần bộ chứa servlet Apache Tomcat đã đề cập ở trên. Bạn có thể tải xuống vùng chứatừ trang web chính thức (tôi sử dụng phiên bản 8). Tiếp theo, chúng ta cần tạo cấu hình trong IDEA để chạy ứng dụng của mình thông qua Tomcat. Để thực hiện việc này, hãy mở tab "Chỉnh sửa cấu hình", tạo cấu hình mới và chọn "Máy chủ Tomcat cục bộ". Trên tab "Máy chủ ứng dụng", chỉ định đường dẫn đến thư mục Tomcat Tiếp theo, chuyển đến tab "Triển khai". Ở đây, chúng tôi định cấu hình việc triển khai ứng dụng của mình trên máy chủ cục bộ. Nhấn "+", chọn "Artifact" -> YourProjectName:war (chúng tôi sẽ xây dựng ứng dụng thành tệp chiến tranh). Và đó là về tổng hợp nó lên! Trên trang "Máy chủ", bạn có thể thấy rằng ứng dụng của chúng tôi sẽ chạy tại http://localhost:8080/. Lưu cấu hình và đặt tên cho nó (tôi gọi cấu hình của mình là "Tommy"). Tiếp theo, trên tab Maven trong IDEA (ở bên phải), chúng tôi sẽ sử dụng plugin chiến tranh để xây dựng dự án của chúng tôi thành tệp chiến tranh (Plugin -> war -> war: war). Sau khi quá trình xây dựng hoàn tất, hãy chạy ứng dụng và đợi. Thành công! Trang bắt đầu đã được đưa ra. Bây giờ chúng tôi nhấp vào nút "Bắt đầu làm việc với cơ sở dữ liệu". index.jsp của chúng tôi sẽ tạo một yêu cầu GET sẽ được máy chủ xử lý. Máy chủ sẽ tạo phản hồi và gửi lại cho chúng tôi dưới dạng danh sách tất cả người dùng hiện có (tất nhiên là giả sử rằng có người dùng trong cơ sở dữ liệu). Và họ đây rồi! Đó là bạn có nó! Bạn đã viết ứng dụng đầu tiên của mình bằng Java servlet. Điều đó không tệ lắm phải không? :) Đối với bài tập về nhà, bạn có thể khôi phục chức năng ô tô từ bài viết trước. Nói cách khác, tạo một trang servlet và trang JSP riêng biệt cho ô tô và hướng dẫn ứng dụng cách liệt kê ô tô của người dùng, thêm ô tô mới cho người dùng, chỉnh sửa và xóa chúng. PS Servlets và JavaServer Pages là những công nghệ khá cổ xưa. Trên Internet, bạn thường có thể tìm thấy những bình luận như "Ai cần thứ rác cũ này?" Câu trả lời khá đơn giản: chủ yếu là những người sẽ làm việc trong các dự án thực tế, nơi họ có thể gặp rất nhiều mã sử dụng các công nghệ này. Và ngay cả khi không hiểu nó hoạt động như thế nào, thì vẫn rất vui khi cắt "rác cũ" thành một cái gì đó mới :) Để tìm hiểu kỹ hơn về JSP và servlet, bạn có thể tham khảo cuốn sách " Head First Servlets and JSP". Nó được viết bởi cùng các tác giả với siêu cuốn sách nổi tiếng "Head First Java", cuốn sách mà nhiều người sẽ coi là sự đảm bảo về chất lượng :) Tôi hy vọng bài viết này hữu ích! Cảm ơn sự quan tâm của bạn, và chúc may mắn trong học tập!
GO TO FULL VERSION