- Sản phẩm & Dịch vụSản phẩm & Dịch vụ
- Giải phápGiải pháp
- Bảng giáBảng giá
- Công tyCông ty
- Tài liệuTài liệu
vi
vi
Chuyên mục với các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.
Technical Writer
I have over 5 years of experience writing technical documentation for tech products, making them accessible and user-friendly. My focus is always on providing clear and precise information. @#@ Tôi đã có hơn 5 năm kinh nghiệm viết tài liệu kỹ thuật cho các sản phẩm công nghệ, giúp người dùng dễ dàng tiếp cận và sử dụng. Tôi luôn tập trung vào việc cung cấp thông tin chính xác và dễ hiểu.
Thảo luận (0)
Đăng nhập để thảo luận
Chào mừng bạn đến với Hướng dẫn lập trình Java JSP cho người mới bắt đầu. Trong một số bài viết gần đây, tôi đã chia sẻ khá nhiều về Java Servlet và nhận được phản hồi rất tích cực từ bạn đọc. Vì vậy, tôi bắt đầu một chuỗi bài mới về JSP, và đây là bài viết đầu tiên trong chuỗi đó.

Trong hướng dẫn JSP có ví dụ minh họa này, chúng ta sẽ tìm hiểu các kiến thức cơ bản về JSP, những ưu điểm của JSP so với Servlet, vòng đời của JSP, các interface và lớp trong JSP API, cũng như vị trí đặt các file JSP trong ứng dụng web.
Chúng ta cũng sẽ điểm qua các thành phần như chú thích trong JSP (JSP Comments), Scriptlets, Directives, Expression, Declaration và các thuộc tính trong JSP. Một số chủ đề trong số này rất quan trọng và sẽ được trình bày chi tiết hơn trong các bài viết tiếp theo.
JSP (JavaServer Pages) là một công nghệ phía máy chủ (server-side) dùng để tạo ra các ứng dụng web động bằng Java. Có thể xem JSP như một phần mở rộng của công nghệ Servlet, vì nó cung cấp các tính năng hỗ trợ việc xây dựng giao diện người dùng một cách dễ dàng hơn.
Một trang JSP gồm mã HTML, đồng thời cho phép chèn mã Java để tạo nội dung động. Vì các ứng dụng web thường chứa rất nhiều màn hình giao diện, JSP được sử dụng rộng rãi trong các dự án web. Để thu hẹp khoảng cách giữa mã Java và HTML trong JSP, công nghệ này cung cấp các tính năng bổ sung như JSP Tags (thẻ JSP), Expression Language (ngôn ngữ biểu thức) và Custom Tags (thẻ tùy chỉnh). Những tính năng này giúp mã dễ hiểu hơn và hỗ trợ lập trình viên web phát triển các trang JSP một cách nhanh chóng.
Vòng đời của JSP cũng được quản lý bởi container. Thông thường, mỗi web container có chứa servlet container thì cũng sẽ có JSP container để quản lý các trang JSP. Các giai đoạn trong vòng đời của một trang JSP bao gồm:
Các phương thức vòng đời của JSP bao gồm:
Chúng ta có thể sử dụng Eclipse IDE để xây dựng dự án web động với các JSP và sử dụng Tomcat để chạy nó. Vui lòng đọc hướng dẫn [Java Web Applications](/community/tutorials/java-web-application-tutorial-for-beginners#first-web-app-servlet) để tìm hiểu cách tạo JSP trong Eclipse một cách dễ dàng và chạy nó trên Tomcat. Một ví dụ trang JSP đơn giản là: `home.jsp`
<%@ 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>First JSP</title> </head> <%@ page import=”java.util.Date” %> <body> <h3>Hi Pankaj</h3><br> <strong>Current Time is</strong>: <%=new Date() %>
</body> </html>
Nếu bạn có một JSP đơn giản chỉ sử dụng các lớp của JRE, thì không cần phải đóng gói nó thành file WAR. Chỉ cần tạo một thư mục trong thư mục `webapps` của Tomcat và đặt file JSP của bạn vào thư mục vừa tạo. Ví dụ, nếu file JSP của bạn nằm tại `apache-tomcat/webapps/test/home.jsp`, thì bạn có thể truy cập nó trên trình duyệt với URL `https://localhost:8080/test/home.jsp`. Nếu host và port của bạn khác, thì bạn cần điều chỉnh URL cho phù hợp.
Chúng ta có thể đặt các file JSP ở bất kỳ vị trí nào trong file WAR, tuy nhiên nếu đặt nó bên trong thư mục `WEB-INF`, chúng ta sẽ không thể truy cập trực tiếp từ phía client. Chúng ta có thể cấu hình JSP giống như servlet trong file `web.xml`, ví dụ nếu tôi có một trang JSP ví dụ như sau nằm trong thư mục `WEB-INF`: `test.jsp`.
<%@ 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>Test JSP</title> </head> <body> Test JSP Page inside WEB-INF folder.<br> Init Param “test” value =<%=config.getInitParameter(“test”) %><br> HashCode of this object=<%=this.hashCode() %> </body> </html>
Và tôi cấu hình nó trong file web.xml như sau:
<?xml version=”1.0″ encoding=”UTF-8″?> <web-app xmlns:xsi=”https://www.w3.org/2001/XMLSchema-instance” xmlns=”https://java.sun.com/xml/ns/javaee” xsi:schemaLocation=”https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd” version=”3.0″> <display-name>FirstJSP</display-name>
<servlet> <servlet-name>Test</servlet-name> <jsp-file>/WEB-INF/test.jsp</jsp-file> <init-param> <param-name>test</param-name> <param-value>Test Value</param-value> </init-param> </servlet>
<servlet-mapping> <servlet-name>Test</servlet-name> <url-pattern>/Test.do</url-pattern> </servlet-mapping>
<servlet> <servlet-name>Test1</servlet-name> <jsp-file>/WEB-INF/test.jsp</jsp-file> </servlet>
<servlet-mapping> <servlet-name>Test1</servlet-name> <url-pattern>/Test1.do</url-pattern> </servlet-mapping> </web-app>
Sau đó, tôi có thể truy cập nó bằng cả hai URL: `https://localhost:8080/FirstJSP/Test.do` và `https://localhost:8080/FirstJSP/Test1.do`. Lưu ý rằng container sẽ tạo hai instance trong trường hợp này và cả hai sẽ có đối tượng servlet config riêng, bạn có thể xác nhận điều này bằng cách truy cập các URL đó trên trình duyệt. Với URI `Test.do`, bạn sẽ nhận được phản hồi như bên dưới.
Test JSP Page inside WEB-INF folder. Init Param “test” value =Test Value HashCode of this object=1839060256
For Test1.do URI, you will get response like below.
Test JSP Page inside WEB-INF folder. Init Param “test” value =null HashCode of this object=38139054
Lưu ý rằng giá trị của init param trong trường hợp thứ hai là null vì nó không được định nghĩa cho servlet thứ hai, đồng thời cũng lưu ý rằng mã hashcode là khác nhau. Nếu bạn thực hiện các yêu cầu tiếp theo, giá trị hashcode sẽ không thay đổi vì các yêu cầu được xử lý bằng cách tạo một luồng mới bởi container. Bạn có để ý việc sử dụng biến **config** trong ví dụ JSP ở trên nhưng không có biến nào được khai báo không? Đó là vì nó là một trong 9 đối tượng ngầm định có sẵn trong trang JSP, tìm hiểu thêm về chúng tại [**JSP Implicit Objects**](/community/tutorials/jsp-implicit-objects "JSP Implicit Objects with Examples").
Tất cả các interface và class cốt lõi của JSP được định nghĩa trong gói `javax.servlet.jsp`. Các interface và class của Expression Language API thuộc gói `javax.servlet.jsp.el`. Các interface và class của JSP Tag Libraries được định nghĩa trong gói `javax.servlet.jsp.tagext`. Tại đây, chúng ta sẽ tìm hiểu về các interface và class của Core JSP API.
Giao diện JspPage mở rộng từ giao diện Servlet và khai báo hai phương thức vòng đời của trang JSP là jspInit() và jspDestroy().
Giao diện HttpJspPage ****mô tả cách thức tương tác mà một lớp triển khai trang JSP phải tuân theo khi sử dụng giao thức HTTP. Giao diện này khai báo phương thức xử lý của trang JSP cho giao thức HTTP dưới dạng: public void _jspService(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException.
Tương tự như PrintWriter trong servlet nhưng có thêm khả năng hỗ trợ bộ đệm (buffering). Đây là một trong những biến ngầm định (implicit variables) trong trang JSP với tên là “out”. Lớp này mở rộng từ java.io.Writer và container sẽ cung cấp phần hiện thực cụ thể cho lớp trừu tượng này khi chuyển trang JSP thành servlet. Chúng ta có thể lấy đối tượng của nó thông qua phương thức PageContext.getOut(). Lớp hiện thực cụ thể của JspWriter trong Apache Tomcat là org.apache.jasper.runtime.JspWriterImpl.
JspContext đóng vai trò là lớp cơ sở cho lớp PageContext và trừu tượng hóa tất cả thông tin không đặc thù cho servlet. JspContext cung cấp cơ chế để lấy đối tượng JspWriter dùng để xuất dữ liệu, cơ chế làm việc với các thuộc tính và API để quản lý các không gian tên theo từng phạm vi khác nhau.
PageContext mở rộng từ JspContext để cung cấp thông tin ngữ cảnh hữu ích khi JSP được sử dụng cho các ứng dụng web. Một thể hiện của PageContext cung cấp quyền truy cập vào tất cả các không gian tên liên quan đến một trang JSP, truy cập vào nhiều thuộc tính của trang, cũng như là một lớp trừu tượng bên trên các chi tiết hiện thực. Các đối tượng ngầm định được tự động thêm vào pageContext.
JspFactory ****là một lớp định nghĩa một số phương thức nhà máy có sẵn cho trang JSP trong thời gian chạy, nhằm mục đích tạo ra các thể hiện của nhiều giao diện và lớp khác nhau được sử dụng để hỗ trợ JSP.
Chứa thông tin về một lỗi, được sử dụng cho các trang xử lý lỗi.
Một ngoại lệ được sử dụng bởi Tag Handler để chỉ ra rằng đã xảy ra một lỗi nghiêm trọng không thể khắc phục được.
Ngoại lệ được dùng để chỉ ra rằng trang đang gọi phải dừng việc xử lý tiếp theo. Ngoại lệ này thường được ném ra bởi một simple tag handler để yêu cầu phần còn lại của trang không được thực thi nữa. Ngoại lệ này không nên được ném thủ công trong một trang JSP.
Vì JSP được xây dựng dựa trên HTML, chúng ta có thể viết chú thích trong file JSP giống như chú thích HTML như `<-- This is HTML Comment -->`. Những chú thích này được gửi đến client và chúng ta có thể xem chúng bằng tùy chọn xem mã nguồn của trình duyệt. Chúng ta có thể đặt chú thích trong file JSP như: `<%-- This is JSP Comment--%>`. Chú thích này phù hợp cho các nhà phát triển để ghi chú ở cấp độ mã vì chúng không được gửi trong phản hồi đến client.
Scriptlet tags là cách dễ nhất để chèn mã Java vào một trang JSP. Một scriptlet tag bắt đầu với `<%` và kết thúc với `%>`. Bất kỳ mã nào được viết bên trong scriptlet tags sẽ được đưa vào phương thức `_jspService()`. Ví dụ: `<% Date d = new Date(); System.out.println("Current Date=" + d); %>`
Vì hầu hết thời gian chúng ta in dữ liệu động trong trang JSP bằng phương thức *out.print()*, nên có một cách viết tắt để thực hiện điều này thông qua JSP Expressions. JSP Expression bắt đầu với `<%=` và kết thúc với `%>`. `<% out.print("Pankaj"); %>` có thể được viết bằng JSP Expression là `<%= "Pankaj" %>`. Lưu ý rằng bất kỳ nội dung nào nằm giữa `<%= %>` sẽ được truyền làm tham số cho phương thức `out.print()`. Cũng lưu ý rằng scriptlet có thể chứa nhiều câu lệnh Java và luôn kết thúc bằng dấu chấm phẩy (;) nhưng expression thì không kết thúc bằng dấu chấm phẩy.
JSP Directives được sử dụng để đưa ra các chỉ dẫn đặc biệt cho container trong quá trình trang JSP được biên dịch thành mã nguồn servlet. JSP directives bắt đầu với `<%@` và kết thúc với `%>`. Ví dụ, trong ví dụ JSP ở trên, tôi đang sử dụng *page* directive để hướng dẫn trình biên dịch JSP của container import lớp Date.
JSP Declarations được sử dụng để khai báo các phương thức và biến thành viên của lớp servlet. JSP Declarations bắt đầu với `<%!` và kết thúc với `%>`. Ví dụ, chúng ta có thể tạo một biến int trong JSP ở cấp độ lớp như sau: `<%! public static int count=0; %>`
Once JSP files are translated to Servlet source code, the source code (.java) and compiled classes both are place in **Tomcat/work/Catalina/localhost/FirstJSP/org/apache/jsp** directory. If the JSP files are inside other directories of application, the directory structure is maintained. For JSPs inside WEB-INF directory, its source and class files are inside **Tomcat/work/Catalina/localhost/FirstJSP/org/apache/jsp/WEB\\_002dINF** directory. Here is the source code generated for above test.jsp page. `test_jsp.java`
/*
the last modified time of the source file after
generation to assist with modification tracking.
*/ package org.apache.jsp.WEB_002dINF;
import javax.servlet.; import javax.servlet.http.; import javax.servlet.jsp.*;
public final class test_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent {
private static final javax.servlet.jsp.JspFactory _jspxFactory = javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() { return _jspx_dependants; }
public void _jspInit() { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); }
public void _jspDestroy() { }
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException {
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html; charset=US-ASCII");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\n");
out.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"<https://www.w3.org/TR/html4/loose.dtd\">\n">);
out.write("<html>\n");
out.write("<head>\n");
out.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=US-ASCII\">\n");
out.write("<title>Test JSP</title>\n");
out.write("</head>\n");
out.write("<body>\n");
out.write("Test JSP Page inside WEB-INF folder.<br>\n");
out.write("Init Param \"test\" value =");
out.print(config.getInitParameter("test") );
out.write("<br>\n");
out.write("HashCode of this object=");
out.print(this.hashCode() );
out.write("\n");
out.write("</body>\n");
out.write("</html>");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try { out.clearBuffer(); } catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
} }
Notice following points in above servlet code;
- The package of class starts with org.apache.jsp and if JSPs are inside other folders, it includes directory hierarchy too. Usually we dont care about it.
- The generates servlet class is final and can't be extended.
- It extends `org.apache.jasper.runtime.HttpJspBase` that is similar to HttpServlet except that it's internal to Tomcat JSP Translator implementation. HttpJspBase extends HttpServlet and implements HttpJspPage interface.
- Notice the local variables at the start of \\_jspService() method implementation, they are automatically added by JSP translator and available for use in service methods, i.e in scriptlets.As a java programmer, sometimes it helps to look into the generated source for debugging purposes.
Chúng ta có thể định nghĩa các tham số khởi tạo cho trang JSP như trong ví dụ ở trên và có thể truy xuất chúng trong JSP bằng đối tượng ngầm định **config**, chúng ta sẽ tìm hiểu chi tiết hơn về các đối tượng ngầm định trong JSP trong các bài viết sau.
Chúng ta có thể ghi đè phương thức khởi tạo của JSP để tạo các tài nguyên được sử dụng bởi phương thức `service()` của JSP bằng cách sử dụng JSP Declaration tags, chúng ta có thể ghi đè `jspInit()`, `jspDestroy()` hoặc bất kỳ phương thức nào khác. Tuy nhiên, chúng ta không nên ghi đè phương thức `_jspService()` vì bất kỳ nội dung nào được viết trong JSP đều sẽ được đưa vào phương thức này.
Ngoài các thuộc tính chuẩn của servlet với phạm vi request, session và context, trong JSP chúng ta còn có một phạm vi khác cho các thuộc tính, đó là Page Scope, có thể truy xuất thông qua đối tượng `pageContext`. Chúng ta sẽ tìm hiểu tầm quan trọng của nó trong bài hướng dẫn về custom tags. Đối với lập trình JSP thông thường, chúng ta không cần quan tâm đến page scope.
Đó là tất cả cho hướng dẫn ví dụ JSP dành cho người mới bắt đầu. Tôi hy vọng nó sẽ giúp bạn hiểu được các khái niệm cơ bản về JSP và hỗ trợ bạn trong việc bắt đầu. Chúng ta sẽ tìm hiểu thêm các tính năng khác của JSP trong các bài viết sau.