openplanning

Hướng dẫn lập trình Java Servlet cho người mới bắt đầu

  1. Servlet là gì?
  2. Vòng đời của Servlet
  3. Cài đặt Tomcat Web Server
  4. Tạo Web Project bắt đầu với Servlet
  5. Cấu hình Eclipse để chạy ứng dụng trên tomcat
  6. Một số class tham gia vào các ví dụ
  7. Tạo Servlet đầu tiên của bạn
  8. Tham số khởi tạo Servlet
  9. Cấu hình Servlet sử dụng Annotation
  10. Servlet Url Pattern
  11. Lấy các thông tin cơ bản của Servlet
  12. Forward (Chuyển tiếp)
  13. Redirect (Chuyển hướng)
  14. Phiên làm việc (Session)
  15. Hướng dẫn sử dụng Servlet-Filter
  16. Hướng dẫn lập trình JSP

1. Servlet là gì?

Java Servlet là chương trình chạy trên một Web hoặc ứng dụng máy chủ (Application Server) và hành động như một lớp trung gian giữa một yêu cầu đến từ một trình duyệt Web hoặc HTTP khách (Client) khác và cơ sở dữ liệu hoặc các ứng dụng trên máy chủ HTTP (HTTP Server).

Sử dụng Servlet, bạn có thể thu thập đầu vào từ người dùng thông qua các hình thức trang web, từ một cơ sở dữ liệu hoặc một nguồn khác, và tạo ra các trang web động.

2. Vòng đời của Servlet

Hình dưới đây minh họa về vòng đời của một Servlet. Từ khi nó được tạo ra, xử lý các đòi hỏi từ người dùng, cho tới lúc nó bị hủy.
Có 5 bước:
  • Tải lớp Servlet vào bộ nhớ.
  • Tạo đối tượng Servlet.
  • Gọi phương thức init() của Servlet.
  • Gọi phương thức service() của Servlet.
  • Gọi phương thức destroy() của Servlet.

Bước 1, 2 và 3 được thực thi một lần duy nhất, khi mà Servlet được nạp lần đầu. Mặc định các Servlet không được tải (load) lên cho tới khi nó nhận một đòi hỏi đầu tiên từ người dùng. Bạn có thể bắt buộc Servlet Container (Bộ chứa các Servlet) tải các Servlet khi nó khởi động.

Bước 4 được thực thi nhiều lần, mỗi khi có đòi hỏi từ phía người dùng tới Servlet.
Bước 5 được thực thi khi bộ chứa Servlet (Servlet Container) gỡ bỏ tải (unloaded) một Servlet.
Bạn có thể xem hình minh họa tiếp theo để hiểu hơn về vòng đời của Servlet.
Khi yêu cầu (request) của người dùng gửi tới Servlet, Servlet sẽ gọi phương thức service() để phục vụ yêu cầu của người dùng, service() sẽ gọi một trong hai phương thức doGet() hoặc doPost(). Trong Servlet của bạn, bạn cần ghi đè và xử lý tại các phương thức này.
Như vậy khi người dùng gửi yêu cầu một Servlet, Servlet sẽ được tạo ra tại thời điểm có yêu cầu lần đầu tiên tới, đồng thời sẽ gọi phương thức init() của servlet để khởi tạo cho nó, init() được gọi duy nhất 1 lần. Phương thức destroy() dùng để hủy servlet, nó sẽ được gọi một lần duy nhất khi bạn gỡ bỏ triển khai (undeloy) ứng dụng web hoặc tắt (shutdown) Web Server (Máy chủ web).

3. Cài đặt Tomcat Web Server

Để bắt đầu với Servlet, bạn cần download Tomcat Web Server và khai báo nó với Eclipse. Bạn có thể xem hướng dẫn tại:

4. Tạo Web Project bắt đầu với Servlet

  • File/New/Other
  • Project Name: ServletTutorial
Đây là hình ảnh Project được tạo ra:
Tạo file index.html:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

   <h1>Hello World</h1>

</body>
</html>

5. Cấu hình Eclipse để chạy ứng dụng trên tomcat

Cho tới lúc này, chúng ta vẫn chưa làm gì tới Servlet. Và giờ chúng ta cấu hình để chạy được ứng dụng web trên. Sau đó chúng mới bắt đầu với Servlet.
Trên eclipse, nhấn phải vào Project ServletTutorial, chọn Properties:
Chọn đến vị trí cài đặt Tomcat 8 của bạn.
Nhấn phải chuột vào project ServletTutorial, chọn "Run As/Run on Server".
Website đang chạy trên trình duyệt của Eclipse.
Nguyên tắc hoạt động:
Khi bạn nhập vào đường dẫn:
Thì website sẽ trả về nội dung trang index.html, điều này hoàn toàn dễ hiểu.

Tuy nhiên, nếu bạn nhập vào đường dẫn:
Điều đó có nghĩa là bạn không chỉ định rõ trang nào, webserver sẽ tìm trang mặc định khai báo trong thẻ <welcome-file> mà bạn khai báo trong web.xml để trả về.
Ghi chú: /ServletTutorial được gọi là Context-Path, mỗi website đều có Context-Path, bạn có thể cấu hình cho nó một giá trị khác, hoặc để rỗng. Trong trường hợp rỗng bạn có thể truy cập vào web của bạn theo cách:
http://localhost:8080
http://localhost:8080/index.html
Khi chạy với Tomcat mặc định nó lấy tên Project làm Context-Path.
Hãy xem hình minh họa sau:

6. Một số class tham gia vào các ví dụ

Một số class sẽ tham gia vào các ví dụ tiếp theo của tài liệu này.
Constants.java
package org.o7planning.tutorial.beans;

public class Constants {

  public static final String ATTRIBUTE_USER_NAME_KEY ="ATTRIBUTE_USER_NAME_KEY";
   
  public static final String SESSION_USER_KEY ="SESSION_USER_KEY";
   
  public static final String CALLBACK_URL_KEY ="CALLBACK_URL_KEY";
   
}
UserInfo.java
package org.o7planning.tutorial.beans;

public class UserInfo {

   public String userName;
   private int post;
   private String country;
   
   public UserInfo(String userName, String country, int post)  {
       this.userName= userName;
       this.country= country;
       this.post= post;
   }

   public int getPost() {
       return post;
   }

   public void setPost(int post) {
       this.post = post;
   }

   public String getCountry() {
       return country;
   }

   public void setCountry(String country) {
       this.country = country;
   }

   public void setUserName(String userName) {
       this.userName = userName;
   }

   public UserInfo(String userName) {
       this.userName = userName;
   }

   public String getUserName() {
       return this.userName;
   }
}

7. Tạo Servlet đầu tiên của bạn

HelloServlet.java
package org.o7planning.tutorial.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class HelloServlet extends HttpServlet {
   
   private static final long serialVersionUID = 1L;

   
   public HelloServlet() {
   }

   @Override
   protected void doGet(HttpServletRequest request,
           HttpServletResponse response) throws ServletException, IOException {
       
       ServletOutputStream out = response.getOutputStream();
       
       out.println("<html>");
       out.println("<head><title>Hello Servlet</title></head>");
       
       out.println("<body>");
       out.println("<h3>Hello World</h3>");
       out.println("This is my first Servlet");
       out.println("</body>");
       out.println("<html>");
   }

   @Override
   protected void doPost(HttpServletRequest request,
           HttpServletResponse response) throws ServletException, IOException {
       this.doGet(request, response);
   }

}
Đây là hình ảnh HelloServlet vừa được tạo ra với đầy lỗi. Các lỗi này đơn giản chỉ là bạn chưa khai báo thư viện Servlet.
Cần khai báo thư viện Servlet, các thư viện này chỉ là các thư viện Runtime của Servlet, nó có sẵn trên các Web Server, ở đây chúng ta dùng Tomcat, vì vậy hãy khai báo chúng.

Nhấn phải chuột vào Project chọn Properties:
Lúc này project đã không còn thông báo lỗi.
Tiếp theo bạn cần khai báo HelloServlet và đường dẫn để truy cập vào nó trong web.xml. Bạn cần thêm đoạn cấu hình sau:
<!-- Định nghĩa servlet có tên helloServlet, gắn với class HelloServlet -->
<servlet>
   <servlet-name>helloServlet</servlet-name>
   <servlet-class>org.o7planning.tutorial.servlet.HelloServlet</servlet-class>
</servlet>

<!-- Định nghĩa đường dẫn truy cập vào Servlet này -->
<servlet-mapping>
   <servlet-name>helloServlet</servlet-name>
   <url-pattern>/hello</url-pattern>
</servlet-mapping>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id="WebApp_ID" version="3.0">
   <display-name>ServletTutorial</display-name>

   
   <servlet>
       <servlet-name>helloServlet</servlet-name>
       <servlet-class>org.o7planning.tutorial.servlet.HelloServlet</servlet-class>
   </servlet>

   <servlet-mapping>
       <servlet-name>helloServlet</servlet-name>
       <url-pattern>/hello</url-pattern>
   </servlet-mapping>


   <welcome-file-list>
       <welcome-file>index.html</welcome-file>
       <welcome-file>index.htm</welcome-file>
       <welcome-file>index.jsp</welcome-file>
       <welcome-file>default.html</welcome-file>
       <welcome-file>default.htm</welcome-file>
       <welcome-file>default.jsp</welcome-file>
   </welcome-file-list>


</web-app>
Chạy lại project bằng cách nhấn phải chuột chọn:
  • Run As/Run on Server
Bạn có thể xem nguyên tắc hoạt động của nó theo hình minh họa dưới đây:
Khi một Servlet được gọi tới, tùy tình huống mà một trong hai phương thức doGet(..) hoặc doPost(..) sẽ được gọi.
  • Cụ thể khi nào gọi doGet(..) và khi nào gọi doPost(..) chúng ta sẽ bàn sau.
Trong doGet() hoặc doPost() bạn có thể lấy ra đối tượng ServletOutputStream, đây là luồng đầu ra (ouput stream), nó gửi dữ liệu về trình duyệt của người dùng. Gọi ServletOutputStream.println(..) để ghi các dòng text vào trong luồng (stream).
// Luồng đầu ra (Output Stream),
// gửi dữ liệu về phía trình duyệt của người dùng.
ServletOutputStream out = response.getOutputStream();

8. Tham số khởi tạo Servlet

Khi khai báo servlet trong web.xml bạn có thể truyền các tham số khởi tạo cho nó.
InitParamServlet.java
package org.o7planning.tutorial.servlet;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class InitParamServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private String emailSupport1;

	public InitParamServlet() {
	}

	// Phương thức này luôn luôn được gọi 1 lần
	// ngay sau khi đối tượng Servlet được tạo ra.
	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);

		// Lấy ra giá trị của tham số khởi tạo (initialization parameter) của Servlet.
		// (Theo Cấu hình của Servlet này trong web.xml).
		this.emailSupport1 = config.getInitParameter("emailSupport1");
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// Lấy ra giá trị của tham số khởi tạo (initialization parameter) theo một cách
		// khác.
		String emailSupport2 = this.getServletConfig().getInitParameter("emailSupport2");

		ServletOutputStream out = response.getOutputStream();

		out.println("<html>");
		out.println("<head><title>Init Param</title></head>");

		out.println("<body>");
		out.println("<h3>Init Param</h3>");
		out.println("<p>emailSupport1 = " + this.emailSupport1 + "</p>");
		out.println("<p>emailSupport2 = " + emailSupport2 + "</p>");
		out.println("</body>");
		out.println("<html>");
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}

}
Cấu hình servlet trong web.xml:
<servlet>
    <servlet-name>initParamServlet</servlet-name>
    <servlet-class>org.o7planning.tutorial.servlet.InitParamServlet</servlet-class>
    
    <init-param>
        <param-name>emailSupport1</param-name>
        <param-value>abc@example.com</param-value>
    </init-param>

    <init-param>
        <param-name>emailSupport2</param-name>
        <param-value>tom@example.com</param-value>
    </init-param>

</servlet>    


<servlet-mapping>
    <servlet-name>initParamServlet</servlet-name>
    <url-pattern>/initParam</url-pattern>
</servlet-mapping>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id="WebApp_ID" version="3.0">
   <display-name>ServletTutorial</display-name>

   
   <servlet>
       <servlet-name>helloServlet</servlet-name>
       <servlet-class>org.o7planning.tutorial.servlet.HelloServlet</servlet-class>
   </servlet>

   <servlet-mapping>
       <servlet-name>helloServlet</servlet-name>
       <url-pattern>/hello</url-pattern>
   </servlet-mapping>


   <servlet>
       <servlet-name>initParamServlet</servlet-name>
       <servlet-class>org.o7planning.tutorial.servlet.InitParamServlet</servlet-class>
       
       <init-param>
           <param-name>emailSupport1</param-name>
           <param-value>abc@example.com</param-value>
       </init-param>
       
       <init-param>
           <param-name>emailSupport2</param-name>
           <param-value>tom@example.com</param-value>
       </init-param>
       
   </servlet>    
   
   
   <servlet-mapping>
       <servlet-name>initParamServlet</servlet-name>
       <url-pattern>/initParam</url-pattern>
   </servlet-mapping>


   
   <welcome-file-list>
       <welcome-file>index.html</welcome-file>
       <welcome-file>index.htm</welcome-file>
       <welcome-file>index.jsp</welcome-file>
       <welcome-file>default.html</welcome-file>
       <welcome-file>default.htm</welcome-file>
       <welcome-file>default.jsp</welcome-file>
   </welcome-file-list>


</web-app>
Chạy lại ứng dụng web:

9. Cấu hình Servlet sử dụng Annotation

Với Servlet phiên bản 3.0 trở lên bạn có thể cấu hình Servlet sử dụng Annotation, trong project này chúng ta đang sử dụng Servlet phiên bản 3.x vì vậy chúng ta có thể sử dụng Annotation để cấu hình. Hãy xem một ví dụ minh họa.
AnnotationExampleServlet.java
package org.o7planning.tutorial.servlet;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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;

// Bạn có thể cấu hình một hoặc nhiều 'mẫu của URL' (URL pattern)
// có thể truy cập vào Servlet này.
@WebServlet(urlPatterns = { "/annotationExample", "/annExample" }, initParams = {
		@WebInitParam(name = "emailSupport1", value = "abc@example.com"),
		@WebInitParam(name = "emailSupport2", value = "tom@example.com") })
public class AnnotationExampleServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private String emailSupport1;

	public AnnotationExampleServlet() {
	}

	// Phương thức này được gọi trước lần phục vụ đầu tiên của Servlet này.
	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);

		this.emailSupport1 = config.getInitParameter("emailSupport1");
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String emailSupport2 = this.getServletConfig().getInitParameter("emailSupport2");

		ServletOutputStream out = response.getOutputStream();

		out.println("<html>");
		out.println("<head><title>Init Param</title></head>");

		out.println("<body>");
		out.println("<h3>Servlet with Annotation configuration</h3>");
		out.println("<p>emailSupport1 = " + this.emailSupport1 + "</p>");
		out.println("<p>emailSupport2 = " + emailSupport2 + "</p>");
		out.println("</body>");
		out.println("<html>");
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}

}
Bạn có thể truy cập Servlet này theo một trong 2 đường dẫn sau:

10. Servlet Url Pattern

Có 4 cách để cấu hình một đường dẫn cho Servlet:
URL Pattern
Ví dụ
/*
http://example.com/contextPath
/*
http://example.com/contextPath/status/abc
/status/abc/*
http://example.com/contextPath/status/abc
/status/abc/*
http://example.com/contextPath/status/abc/mnp
/status/abc/*
http://example.com/contextPath/status/abc/mnp?date=today
/status/abc/*
http://example.com/contextPath/test/abc/mnp
*.map
http://example.com/contextPath/status/abc.map
*.map
http://example.com/contextPath/status.map?date=today
*.map
http://example.com/contextPath/status/abc.MAP
/
Đây là Servlet mặc định.
Khi người dùng nhập vào một đường dẫn trên trình duyệt, nó sẽ được gửi tới WebContainer. WebContainer cần phải quyết định xem Servlet nào sẽ phục vụ yêu cầu này từ phía người dùng.

Hình dưới đây minh họa cách WebContainer quyết định sử dụng Servlet nào để phục vụ yêu cầu từ Client.
Ví dụ tạo một Servlet với url-pattern có dấu hoa thị, chẳng hạn:
  • url-pattern = "/any/*";
AsteriskServlet.java
package org.o7planning.tutorial.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = { "/any/*" })
public class AsteriskServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	public AsteriskServlet() {
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		ServletOutputStream out = response.getOutputStream();

		out.println("<html>");
		out.println("<head><title>Asterisk</title></head>");

		out.println("<body>");

		out.println("<h3>Hi, your URL match /any/*</h3>");

		out.println("</body>");
		out.println("<html>");
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}

}
Các URL có dạng sau đều được phục vụ bởi AsteriskServlet (/any/*).
Servlet mặc định:
Servlet với url-pattern = /

Là một servlet mặc định, servlet này sẽ được sử dụng để xử lý các yêu cầu (request) mà có đường dẫn không khớp với bất kỳ một url-pattern nào của các Servlet khác được khai báo trong ứng dụng của bạn.
Hãy xem một ví dụ minh họa với Servlet mặc định:
MyDefaultServlet.java
package org.o7planning.tutorial.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = { "/" })
public class MyDefaultServlet extends HttpServlet {

   private static final long serialVersionUID = 1L;

   public MyDefaultServlet() {
   }

   @Override
   protected void doGet(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException {

       ServletOutputStream out = response.getOutputStream();

       out.println("<html>");
       out.println("<head><title>Page not found</title></head>");

       out.println("<body>");
       out.println("<h3>Sorry! Page not found</h3>");
       out.println("<h1>404</h1>");
       out.println("Message from servlet: " + this.getClass().getName());
       out.println("</body>");
       out.println("<html>");
   }

   @Override
   protected void doPost(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException {
       this.doGet(request, response);
   }

}
Bạn có thể chạy lại ứng dụng web, và truy cập đường dẫn:
Đường dẫn ở trên có servletPath = /news/tomAndJerry, không khớp với đường dẫn của Servlet nào bạn đã khai báo. Khi đó "Servlet mặc định" sẽ phục vụ request này.

11. Lấy các thông tin cơ bản của Servlet

Bạn có thể lấy ra các thông tin liên quan tới lần phục vụ của Servlet chẳng hạn:
  1. Thông tin request từ client.
  2. Thông tin Server
  3. Thông tin Client
  4. Thông tin Header gửi theo request
  5. ....
ExampleInfoServlet.java
package org.o7planning.tutorial.servlet;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/other/exampleInfo")
public class ExampleInfoServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	public ExampleInfoServlet() {
		super();
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		ServletOutputStream out = response.getOutputStream();

		out.println("<style> span {color:blue;} </style>");

		String requestURL = request.getRequestURL().toString();
		out.println("<br><span>requestURL:</span>");
		out.println(requestURL);

		String requestURI = request.getRequestURI();
		out.println("<br><span>requestURI:</span>");
		out.println(requestURI);

		String contextPath = request.getContextPath();
		out.println("<br><span>contextPath:</span>");
		out.println(contextPath);

		out.println("<br><span>servletPath:</span>");
		String servletPath = request.getServletPath();
		out.println(servletPath);

		String queryString = request.getQueryString();
		out.println("<br><span>queryString:</span>");
		out.println(queryString);

		String param1 = request.getParameter("text1");
		out.println("<br><span>getParameter text1:</span>");
		out.println(param1);

		String param2 = request.getParameter("text2");
		out.println("<br><span>getParameter text2:</span>");
		out.println(param2);

		// Server Infos
		out.println("<br><br><b>Server info:</b>");

		out.println("<br><span>serverName:</span>");
		String serverName = request.getServerName();
		out.println(serverName);

		out.println("<br><span>serverPort:</span>");
		int serverPort = request.getServerPort();
		out.println(serverPort + "");

		// Client Infos
		out.println("<br><br><b>Client info:</b>");

		out.println("<br><span>remoteAddr:</span>");
		String remoteAddr = request.getRemoteAddr();
		out.println(remoteAddr);

		out.println("<br><span>remoteHost:</span>");
		String remoteHost = request.getRemoteHost();
		out.println(remoteHost);

		out.println("<br><span>remoteHost:</span>");
		int remotePort = request.getRemotePort();
		out.println(remotePort + "");

		out.println("<br><span>remoteUser:</span>");
		String remoteUser = request.getRemoteUser();
		out.println(remoteUser);

		// Header Infos
		out.println("<br><br><b>headers:</b>");

		Enumeration<String> headers = request.getHeaderNames();
		while (headers.hasMoreElements()) {
			String header = headers.nextElement();
			out.println("<br><span>" + header + "</span>: " + request.getHeader(header));
		}

		// Servlet Context info:
		out.println("<br><br><b>Servlet Context info:</b>");
		ServletContext servletContext = request.getServletContext();

		// Vị trí của ứng dụng web trên ổ cứng (hard disk).
		out.println("<br><span>realPath:</span>");
		String realPath = servletContext.getRealPath("");
		out.println(realPath);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}

}
Hãy xem hình minh họa dưới đây, với các thông tin mà bạn quan tâm:
Chạy lại ứng dụng web và truy cập vào đường dẫn:
Kết quả nhận được:

12. Forward (Chuyển tiếp)

Chuyển tiếp (Forward): Khi một yêu cầu (request) của trình duyệt gửi tới một Servlet, nó có thể chuyển tiếp yêu cầu tới một trang khác (hoặc một servlet khác). Địa chỉ trên trình duyệt của người dùng vẫn là đường dẫn của trang đầu tiên, nhưng nội dung của trang do trang được chuyển tiếp tới tạo ra.

Trang được chuyển tiếp tới bắt buộc phải là môt trang (hoặc Servlet) nằm trong ứng dụng web của bạn.

Với Forward bạn có thể sử dụng request.setAttribute() để truyền dữ liệu từ trang 1 sang trang thứ 2.
ForwardDemoServlet.java
package org.o7planning.tutorial.servlet.other;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.o7planning.tutorial.beans.Constants;

@WebServlet("/other/forwardDemo")
public class ForwardDemoServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	// Request:
	// http://localhost:8080/ServletTutorial/other/forwardDemo?forward=true
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// Lấy giá trị tham số (parameter) trên URL.
		String forward = request.getParameter("forward");

		if ("true".equals(forward)) {
			System.out.println("Forward to ShowMeServlet");

			// Sét dữ liệu vào thuộc tính (attribute) của request.
			request.setAttribute(Constants.ATTRIBUTE_USER_NAME_KEY, //
					"Hi, I'm Tom come from Walt Disney !");

			RequestDispatcher dispatcher //
					= request.getServletContext().getRequestDispatcher("/showMe");
			dispatcher.forward(request, response);

			return;
		}
		ServletOutputStream out = response.getOutputStream();
		out.println("<h3>Text of ForwardDemoServlet</h3>");
		out.println("- servletPath=" + request.getServletPath());
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}

}
Chạy lại Webserver và chạy lần lượt 2 URL:
Trong trường hợp 1: Không có forward, dữ liệu nhìn thấy trên trang là của ForwardDemoServlet tạo ra.
Trường hợp 2: Có chuyển tiếp (forward) sang servlet ShowMeServlet. Trong trường hợp này URL trên trang là không đổi, trong khi dữ liệu là của ShowMeServlet tạo ra.
Forward (chuyển tiếp) thường được sử dụng trong một số tình huống chẳng hạn người dùng yêu cầu servlet A, tuy nhiên trang này bắt buộc phải login trước, trong servlet A kiểm tra thấy nếu chưa login thì chuyển tiếp sang servlet Login.
Quay lại với RequestDispatcher, chúng ta có 2 cách để lấy đối tượng RequestDispatcher.
Trường hợp request.getServletContext().getRequestDispatcher(url) trả về RequestDispatcher có vị trí tương đối với contextPath (có vị trí tương đối với thư mục gốc của website).
  • http://localhost:8080/contextPath
  • http://localhost:8080/ServletTutorial
Còn gọi request.getRequestDispatcher(url) trả về RequestDispatcher có vị trí tương đối với trang hiện tại.
  • http://localhost:8080/ServletTutorial/other/forwardDemo

Chú ý:

  • Redirect (Chuyển hướng) cho phép bạn chuyển hướng tới các trang bao gồm cả các trang nằm ngoài Website.
  • Forward (Chuyển tiếp) chỉ cho phép chuyển tới các trang nằm trong Website, đồng thời có thể chuyển dữ liệu giữa 2 trang thông qua request.setAttribute.

13. Redirect (Chuyển hướng)

Chuyển hướng (Redirect): Khi một yêu cầu (request) từ phía người dùng tới một Servlet (Trang A), servlet này có thể chuyển yêu cầu này tới một trang khác (Trang B), và kết thúc nhiệm vụ của nó. Trang được chuyển hướng tới có thể là trang trong ứng dụng của bạn, hoặc có thể là một trang bất kỳ. Địa chỉ trên trình duyệt của người dùng lúc này sẽ hiển thị đường dẫn của trang B.

Khác với chuyển tiếp (Forward). Với Redirect bạn không thể sử dụng request.setAttribute(..) để truyền dữ liệu từ trang A sang trang B.
ShowMeServlet.java
package org.o7planning.tutorial.servlet.other;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.o7planning.tutorial.beans.Constants;

@WebServlet("/showMe")
public class ShowMeServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// Lấy giá trị trong 1 thuộc tính (attribute) của request.
		String value = (String) request.getAttribute(Constants.ATTRIBUTE_USER_NAME_KEY);

		ServletOutputStream out = response.getOutputStream();

		out.println("<h1>ShowMeServlet</h1>");
		out.println(value);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}

}
RedirectDemoServlet.java
package org.o7planning.tutorial.servlet.other;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/other/redirectDemo")
public class RedirectDemoServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	// Request:
	// http://localhost:8080/ServletTutorial/other/redirectDemo?redirect=true
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// Lấy ra giá trị của tham số (parameter) trên URL.
		String redirect = request.getParameter("redirect");

		if ("true".equals(redirect)) {
			System.out.println("Redirect to ShowMeServlet");

			// contextPath: Là một String rỗng "" hoặc khác rỗng.
			// Nếu khác rỗng, nó luôn bắt đầu bởi /
			// và không kết thúc bởi /
			String contextPath = request.getContextPath();

			// ==> /ServletTutorial/showMe
			response.sendRedirect(contextPath + "/showMe");
			return;
		}

		ServletOutputStream out = response.getOutputStream();
		out.println("<h3>Text of RedirectDemoServlet</h3>");
		out.println("- servletPath=" + request.getServletPath());
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}

}
Chạy lại webserver và truy cập lần lượt 2 đường dẫn sau lên trình duyệt:
Với đường dẫn thứ nhất nhận được:
Với đường dẫn thứ 2, request đã chuyển hướng sang ShowMeServlet, đường dẫn URL bạn thấy trên trình duyệt là đường dẫn của servlet ShowMeServlet.

14. Phiên làm việc (Session)

Đối tượng HttpSession mô tả một phiên làm việc (session) của người dùng. Một phiên làm việc của người dùng chứa nhiều thông tin người dùng, và xuyên suốt trên các yêu cầu (request) đã gửi tới HTTP server.

Khi lần đầu tiên người dùng vào trang web của bạn, người dùng sẽ nhận được một ID duy nhất phân biệt với các người dùng khác. ID này thường được lưu trữ trong cookie hoặc tham số của request.

Đây là đoạn code để bạn truy cập vào đối tượng session:
protected void doGet(HttpServletRequest request,
   HttpServletResponse response)
       throws ServletException, IOException {

   HttpSession session = request.getSession();
}
Bạn có thể lưu trữ các giá trị vào đối tượng session, và lấy chúng ra sau đó, có thể là tại một trang khác. Trước hết, hãy xem cách bạn có thể lưu trữ giá trị vào trong đối tượng session:
// Lấy ra đối tượng HttpSession
HttpSession session = request.getSession();

// Giả sử người dùng đã login thành công.
UserInfo loginedInfo = new UserInfo("Tom", "USA", 5);

// Lưu trữ thông tin người dùng vào 1 thuộc tính (attribute) của Session. 
// Bạn có thể lấy lại thông tin này bằng phương thức getAttribute.
session.setAttribute(Constants.SESSION_USER_KEY, loginedInfo);
Và lấy lại các thông tin đã lưu trữ trong Session tại một trang nào đó.
// Lấy ra đối tượng HttpSession.
HttpSession session = request.getSession();

// Lấy ra đối tượng UserInfo đã được lưu vào session
// sau khi người dùng login thành công.
UserInfo loginedInfo 
    = (UserInfo) session.getAttribute(Constants.SESSION_USER_KEY);
Xem ví dụ đầy đủ:
LoginServlet.java
package org.o7planning.tutorial.servlet.session;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.o7planning.tutorial.beans.Constants;
import org.o7planning.tutorial.beans.UserInfo;

@WebServlet(urlPatterns = { "/login" })
public class LoginServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	public LoginServlet() {
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		ServletOutputStream out = response.getOutputStream();

		// Lấy ra đối tượng HttpSession
		HttpSession session = request.getSession();

		// Giả sử người dùng đã login thành công.
		UserInfo loginedInfo = new UserInfo("Tom", "USA", 5);

		// Lưu trữ thông tin người dùng vào 1 thuộc tính (attribute) của Session.
		session.setAttribute(Constants.SESSION_USER_KEY, loginedInfo);

		out.println("<html>");
		out.println("<head><title>Session example</title></head>");

		out.println("<body>");
		out.println("<h3>You are logined!, info stored in session</h3>");

		out.println("<a href='userInfo'>View User Info</a>");
		out.println("</body>");
		out.println("<html>");
	}

}
UserInfoServlet.java
package org.o7planning.tutorial.servlet.session;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.o7planning.tutorial.beans.Constants;
import org.o7planning.tutorial.beans.UserInfo;

@WebServlet(urlPatterns = { "/userInfo" })
public class UserInfoServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	public UserInfoServlet() {
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		ServletOutputStream out = response.getOutputStream();

		// Lấy ra đối tượng HttpSession.
		HttpSession session = request.getSession();

		// Lấy ra đối tượng UserInfo đã được lưu vào session
		// sau khi người dùng login thành công.
		UserInfo loginedInfo = (UserInfo) session.getAttribute(Constants.SESSION_USER_KEY);

		// Chưa login, Redirect (chuyển hướng) về trang login (LoginServlet).
		if (loginedInfo == null) {
			// ==> /ServletTutorial/login
			response.sendRedirect(this.getServletContext().getContextPath() + "/login");
			return;
		}

		out.println("<html>");
		out.println("<head><title>Session example</title></head>");

		out.println("<body>");

		out.println("<h3>User Info:</h3>");

		out.println("<p>User Name:" + loginedInfo.getUserName() + "</p>");
		out.println("<p>Country:" + loginedInfo.getCountry() + "</p>");
		out.println("<p>Post:" + loginedInfo.getPost() + "</p>");

		out.println("</body>");
		out.println("<html>");
	}

}
Chạy ví dụ:

15. Hướng dẫn sử dụng Servlet-Filter

Tiếp theo bạn có thể xem tiếp tài liệu về Servlet Filter (Bộ lọc servlet):

16. Hướng dẫn lập trình JSP

Tiếp theo Servlet bạn có thể tìm hiểu tiếp JSP tại đây: