Bài viết này cung cấp các thông tin cơ bản về những thành phần khác nhau trong một ứng dụng web, cũng như cách bạn có thể sử dụng Servlet và JSP để tạo ra một ứng dụng web Java đơn giản.
Ứng dụng web Java
Web server và client
Web server là một phần mềm có khả năng xử lý request (yêu cầu) từ client và gửi response (phản hồi) ngược lại. Nó chạy trên một máy chủ vật lý và listen (lắng nghe) các request từ client tại một port cụ thể. Ví dụ, Apache là một trong những web server thông dụng nhất.
Web client là phần mềm giúp người dùng giao tiếp với server. Một số ví dụ được sử dụng rộng rãi nhất bao gồm Firefox, Google Chrome, Safari, v.v. Khi ta gửi một request đến server (thông qua URL), web client sẽ tạo request đó, gửi nó đến server, sau đó xử lý response từ server và hiển thị kết quả cho người dùng.
HTML và HTTP
Do web server và client là hai phần mềm riêng biệt, chúng cần một ngôn ngữ chung để giao tiếp với nhau. HTML (viết tắt của HyperText Markup Language) chính là ngôn ngữ chung đó. Tương tự, web server và client cũng cần một protocol (giao thức truyền thông) chung, và HTTP (HyperText Transfer Protocol) là giao thức được sử dụng cho mục đích này.
HTTP hoạt động dựa trên giao thức TCP/IP. Một HTTP request bao gồm các phần quan trọng sau:
- HTTP Method (Phương thức được dùng): Hành động cần thực hiện, thường là GET, POST, PUT, v.v.
- URL: Trang cần truy cập.
- Form parameter (Tham số biểu mẫu): Tương tự như các tham số trong một phương thức Java (như thông tin user, password từ trang đăng nhập).
Ví dụ về HTTP request:
GET /FirstServletProject/jsps/hello.jsp HTTP/1.1
Host: localhost:8080
Cache-Control: no-cache
Một HTTP response bao gồm các phần quan trọng sau:
- Status Code (Mã trạng thái): Một số nguyên cho biết yêu cầu có thành công hay không. Một số status code phổ biến là 200 (thành công), 404 (Không tìm thấy – Not Found), và 403 (Truy cập bị cấm – Access Forbidden).
- Content Type (Loại nội dung): Định dạng nội dung như text, html, image, pdf, v.v. Còn được gọi là MIME type.
- Content (Nội dung): Dữ liệu thực tế được client render để hiển thị cho người dùng.
Ví dụ về HTTP Response:
200 OK
Date: Wed, 07 Aug 2013 19:55:50 GMT
Server: Apache-Coyote/1.1
Content-Length: 309
Content-Type: text/html;charset=US-ASCII
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<https://www.w3.org/TR/html4/loose.dtd>">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Hello</title>
</head>
<body>
<h2>Hi There!</h2>
<br>
<h3>Date=Wed Aug 07 12:57:55 PDT 2013
</h3>
</body>
</html>
MIME Type hoặc Content Type: Như ta đã thấy trong header của HTTP response mẫu ở trên, có một trường gọi là “Content-Type”. Đây cũng chính là MIME type, được server gửi đến client để thông báo về loại dữ liệu đang được truyền đi. Thông tin này giúp client render dữ liệu một cách chính xác cho người dùng. Một số MIME type phổ biến bao gồm text/html, text/xml, application/xml, v.v.
Tìm hiểu về URL
URL là từ viết tắt của Universal Resource Locator, được sử dụng để xác định vị trí của server và tài nguyên. Mỗi tài nguyên trên web đều có một địa chỉ duy nhất.
Ta hãy cùng xem xét các thành phần của một URL qua ví dụ sau:
https://localhost:8080/FirstServletProject/jsps/hello.jsp
- https://: Đây là phần đầu tiên của URL, xác định giao thức truyền thông được sử dụng giữa server và client.
- localhost: Địa chỉ của server. Trong hầu hết các trường hợp, đây là hostname của server, được ánh xạ tới một địa chỉ IP duy nhất. Đôi khi, nhiều hostname có thể cùng trỏ về một địa chỉ IP, và khi đó virtual host (host ảo) của web server sẽ chịu trách nhiệm gửi yêu cầu đến thực thể server cụ thể.
- 8080: Đây là port mà server đang lắng nghe. Phần này là tùy chọn. Nếu không được cung cấp trong URL, yêu cầu sẽ được gửi đến port mặc định của giao thức. Các port có số từ 0 đến 1023 là các port đã được đăng ký trước cho các dịch vụ phổ biến, ví dụ 80 cho HTTP, 443 cho HTTPS, 21 cho FTP, v.v.
- FirstServletProject/jsps/hello.jsp: Đây là tài nguyên (resource) được yêu cầu từ server. Tài nguyên này có thể là một trang HTML tĩnh, file PDF, JSP, servlet, PHP, v.v.
Tại sao ta cần Servlet và JSP?
Web server có thể tự xử lý tốt các nội dung tĩnh như trang HTML, nhưng lại không có khả năng tạo ra nội dung động hay lưu trữ dữ liệu vào database. Vì vậy, ta cần một công cụ khác để tạo ra nội dung động.
Hiện có nhiều ngôn ngữ lập trình hỗ trợ việc này, ví dụ như PHP, Python, Ruby on Rails, và cả Java (với Servlet và JSP). Servlet và JSP là các công nghệ phía server (server-side) giúp mở rộng tính năng của web server, hỗ trợ việc tạo phản hồi động và đảm bảo tính lưu trữ lâu dài của dữ liệu (data persistence).
Phát triển ứng dụng web với Java
Ứng dụng web đơn giản với Servlet và JSP
Ta sẽ sử dụng Eclipse IDE for Java EE Developers” để tạo ứng dụng servlet đầu tiên. Do servlet là một công nghệ phía server, ta sẽ cần một web container hỗ trợ công nghệ Servlet. Ở đây, ta sẽ dùng server Apache Tomcat.
Việc cài đặt Tomcat khá đơn giản nên sẽ không được trình bày chi tiết trong bài này. Ta có thể cấu hình Tomcat tích hợp với Eclipse để giúp việc triển khai (deploy) và chạy ứng dụng trở nên dễ dàng hơn.
Trong Eclipse, vào Preference
, chọn Server Runtime Environments
, sau đó chọn phiên bản Tomcat server bạn đang dùng (ví dụ, Tomcat 7).
Khai báo đường dẫn đến thư mục Apache Tomcat và thông tin JRE để thêm môi trường runtime. Tiếp theo, mở khung nhìn (view) Servers
và tạo một server mới với môi trường runtime vừa được thêm theo hướng dẫn trong hình dưới đây.
Lưu ý: Nếu không thấy tab Servers, vào Window
> Show View
> Servers
để hiển thị nó trong cửa sổ Eclipse. Hãy thử dừng và khởi động lại server để đảm bảo mọi thứ hoạt động ổn định. Nếu bạn đã khởi động server từ terminal, bạn cần dừng nó từ terminal trước khi khởi động lại từ Eclipse, nếu không nó có thể sẽ không hoạt động đúng.
Sau khi hoàn tất các bước thiết lập, ta có thể tạo servlet đầu tiên và chạy nó trên server Tomcat. Chọn File
> New
> Dynamic Web Project
và làm theo hướng dẫn trong hình dưới đây: chọn runtime là server đã cấu hình ở bước trước, và đặt module version là 3.0 để tạo servlet theo đặc tả (specs) Servlet 3.0.
Bạn có thể nhấn trực tiếp nút Finish
để tạo project, hoặc nhấn Next
để xem xét các tùy chọn khác. Tiếp theo, chọn File
> New
> Servlet
và làm theo hướng dẫn trong hình dưới đây để tạo servlet đầu tiên. Tương tự, ta có thể nhấn Finish
ngay hoặc chọn Next
để xem qua các tùy chọn khác.
Khi nhấn nút Finish
, Eclipse sẽ tự động tạo ra code khung (skeleton code) cho Servlet, nhờ đó ta không cần phải tự gõ lTài liệu này giới thiệu về việc phát triển ứng dụng web Java bằng cách sử dụng các công nghệ Servlets và JSPs. Chúng tôi sẽ đi qua các khái niệm cốt lõi và các bước thực hành để xây dựng một ứng dụng web đầu tiên.ại toàn bộ các phương thức và câu lệnh import.
Bây giờ, ta sẽ thêm một số mã HTML cùng với dữ liệu động vào phương thức doGet()
, phương thức này sẽ được gọi khi có yêu cầu HTTP GET . Servlet đầu tiên của chúng ta sẽ có dạng như sau:
package com.journaldev.first;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class FirstServlet
*/
@WebServlet(description = "My First Servlet", urlPatterns = { "/FirstServlet" , "/FirstServlet.do"}, initParams = {@WebInitParam(name="id",value="1"),@WebInitParam(name="name",value="pankaj")})
public class FirstServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public static final String HTML_START="<html><body>";
public static final String HTML_END="</body></html>";
/**
* @see HttpServlet#HttpServlet()
*/
public FirstServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
Date date = new Date();
out.println(HTML_START + "<h2>Hi There!</h2><br/><h3>Date="+date +"</h3>"+HTML_END);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
Trước phiên bản Servlet 3, ta cần khai báo thông tin url pattern (mẫu địa chỉ) trong deployment descriptor (mô ta triển khai) của ứng dụng web. Tuy nhiên, Servlet 3.0 sử dụng Java annotation, một cách tiếp cận vừa dễ hiểu hơn vừa giảm thiểu nguy cơ lỗi.
Bây giờ, từ cửa sổ editor của servlet, chọn Run
> Run on Server
và làm theo hướng dẫn trong các hình dưới đây để cấu hình các tùy chọn.
Sau khi nhấn Finish
, một trình duyệt nhúng trong Eclipse sẽ xuất hiện để hiển thị trang HTML như sau:
Bạn có thể tải lại (refresh) trang để kiểm tra xem thông tin ngày giờ có được cập nhật động và thay đổi liên tục hay không. Bạn cũng có thể mở trang này trong một trình duyệt bất kỳ bên ngoài Eclipse.
Ở ví dụ trên, servlet được dùng để tạo mã HTML và gửi nó đi trong response. Nếu xem code của doGet()
, bạn sẽ thấy rằng ta thực sự đang tạo một tài liệu HTML bằng cách ghi nội dung vào đối tượng PrintWriter
của response, và chèn thông tin động vào những vị trí cần thiết. Cách làm này phù hợp cho các ví dụ đơn giản, nhưng nếu response lớn với nhiều dữ liệu động, code sẽ dễ phát sinh lỗi, khó đọc và bảo trì.
Đây chính là lý do chủ yếu dẫn đến sự ra đời của JSP. Nó cũng là một công nghệ phía server, về cơ bản giống HTML nhưng được bổ sung các tính năng cho phép chèn nội dung động vào vị trí mong muốn. JSP rất phù hợp cho tầng trình bày (presentation) vì cú pháp của nó gần giống HTML nên dễ viết hơn.
Dưới đây là chương trình JSP đầu tiên của chúng ta, thực hiện chức năng tương tự như servlet ví dụ ở trên:
<%@page import="java.util.Date"%>
<%@ page language="java" contentType="text/html; charset=US-ASCII"
pageEncoding="US-ASCII"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<https://www.w3.org/TR/html4/loose.dtd>">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Hello</title>
</head>
<body>
<h2>Hi There!</h2>
<br>
<h3>Date=<%= new Date() %>
</h3>
</body>
</html>
Khi chạy file JSP trên, ta sẽ nhận được kết quả như hình dưới đây.
Cấu trúc project hoàn chỉnh trong Eclipse sẽ có dạng như hình dưới đây.
Bạn có thể tải về code hoàn chỉnh của ví dụ trên ở đây.
Ta sẽ tìm hiểu chi tiết hơn về Servlet và JSP trong các bài viết sau. Tuy nhiên, trước khi kết thúc bài viết này, bạn cần nắm vững một số khía cạnh quan trọng khác của ứng dụng web Java.
Web container
Tomcat là một web container. Khi Client gửi yêu cầu đến web server, nó sẽ chuyển tiếp yêu cầu này cho web container. Nhiệm vụ của web container là tìm đúng tài nguyên (servlet hoặc JSP) để xử lý yêu cầu, sau đó sử dụng kết quả từ tài nguyên này để tạo ra response cuối cùng và chuyển lại cho web server. Web server sau đó sẽ gửi response này về cho client.
Khi web container nhận được một yêu cầu, nếu đó là yêu cầu dành cho servlet, container sẽ tạo hai object là HTTPServletRequest
và HTTPServletResponse
. Tiếp theo, nó tìm servlet phù hợp dựa trên URL và tạo một thread riêng để xử lý yêu cầu này. Sau đó, container gọi phương thức service()
của servlet. Dựa vào HTTP method của yêu cầu, phương thức service()
sẽ tiếp tục gọi phương thức doGet()
hoặc doPost()
tương ứng.
Các phương thức trong servlet sẽ tạo ra nội dung động và ghi vào response. Khi thread xử lý servlet hoàn tất, container sẽ đóng gói response thành dạng HTTP response chuẩn rồi gửi lại cho client thông qua web server.
Một số nhiệm vụ quan trọng mà web container đảm nhận bao gồm:
- Hỗ trợ giao tiếp: Container tạo điều kiện giao tiếp thuận lợi giữa web server với các servlet và JSP. Nhờ có container, ta không cần phải tự xây dựng server socket để lắng nghe yêu cầu từ web server, phân tích yêu cầu và tạo response. Tất cả các tác vụ quan trọng và phức tạp này đều do container đảm nhiệm, giúp ta tập trung hoàn toàn vào business logic của ứng dụng.
- Quản lý vòng đời và tài nguyên: Container chịu trách nhiệm quản lý toàn bộ vòng đời của servlet, bao gồm việc tải servlet vào bộ nhớ, khởi tạo, gọi các phương thức của servlet và cuối cùng là hủy bỏ servlet. Container cũng cung cấp các tiện ích như JNDI cho việc quản lý và sử dụng tập hợp tài nguyên (resource pooling).
- Hỗ trợ đa luồng: Với mỗi yêu cầu gửi đến servlet, container sẽ tạo một thread mới để xử lý. Khi xử lý xong, thread đó sẽ kết thúc. Điều này có nghĩa là servlet không cần khởi tạo lại với mỗi yêu cầu, giúp tiết kiệm thời gian và bộ nhớ.
- Hỗ trợ JSP: JSP có cấu trúc khác với các class Java thông thường, và web container chính là thành phần giúp hỗ trợ để chạy JSP. Mỗi file JSP trong ứng dụng sẽ được container biên dịch và chuyển đổi thành một servlet. Sau đó, container sẽ quản lý các servlet này tương tự như những servlet khác.
- Các tác vụ khác: Web container còn quản lý resource pool, thực hiện các tối ưu hóa về bộ nhớ, chạy garbage collector (thu gom rác), cung cấp các cấu hình bảo mật, hỗ trợ chạy nhiều ứng dụng song song, hỗ trợ hot deployment (triển khai nóng), cùng nhiều tác vụ ngầm khác giúp đơn giản hóa công việc của lập trình viên.
Cấu trúc thư mục của ứng dụng web
Các ứng dụng web Java thường được đóng gói thành file Web Archive (WAR) với một cấu trúc thư mục được quy định rõ ràng. Bạn có thể xuất project web động đã tạo ở trên thành một file WAR, sau đó giải nén file này để tự mình kiểm tra cấu trúc đó.
Cấu trúc này sẽ tương tự như hình minh họa dưới đây.
Deployment Descriptor
File web.xml
chính là deployment descriptor của ứng dụng web. File này chứa các khai báo mapping cho servlet (đối với phiên bản trước Servlet 3.0), khai báo trang chào mừng, các cấu hình bảo mật, cài đặt session timeout (thời gian quá hạn phiên), v.v.
Tổng kết
Hy vọng rằng bài viết này đã mang đến cho bạn một cái nhìn tổng thể và những kiến thức nền tảng vững chắc để bắt đầu hành trình phát triển ứng dụng web Java dựa trên Servlet và JSP. Để thực sự làm chủ những gì đã học, chúng tôi đặc biệt khuyến khích bạn tải và khám phá project ví dụ mà chúng tôi đã cung cấp. Ngoài ra, hãy tìm đọc bài hướng dẫn riêng về Java Servlet trên của chúng tôi nếu bạn muốn khám phá sâu hơn nữa về công nghệ này.