Understanding Servlets in Web Development
Basic Introduction
Tomcat serves as a fundamental tool in Java server development, as all developed servers must be deployed on Tomcat. It acts as the foundation for all servers. To better handle HTTP operations, Tomcat encapsulates the native APIs into Servlets, which allows developers to efficiently perform HTTP-related operations.
When learning about Servlets, focus primarily on these three classes:
- HttpServlet
- HttpRequestServlet
- HttpResponseServlet
Mastering these three classes enables effective utilization of Servlet technology.
HttpServlet
HttpServlet is the core class in Servlet technology; all classes created for interaction must inherit from HttpServlet.
Common HttpServlet Methods
- The
init()method is automatically called after a Servlet object is created, performing initialization operations. - The
destroy()method is invoked before the Servlet object is destroyed, handling resource cleanup tasks. - The
service()method is not typically used directly; instead, it's replaced bydoGet()anddoPost()methods.
In actual development, init(), destroy(), and service() methods are rarely used directly, as Tomcat automatically calls them at appropriate times. These methods often appear in classic interview questions:
Classic Interview Question: Servlet Lifecycle
The Servlet lifecycle refers to the process from Servlet instance creation to destruction. It can be divided into the following stages:
- Servlet Instance Creation: When a client sends a request, the server creates a Servlet instance to handle it through the constructor.
- Initialization: After creation, the
init()method is automatically called to perform initialization tasks like reading configuration files, establishing database connections, and initializing resources. - Request Processing: When an HTTP request arrives from a client, the Servlet calls the
service()method to determine the request type. Based on the HTTP method (GET, POST, etc.), it routes to the appropriate handler method (doGet(),doPost(), etc.). - Instance Destruction: When the Servlet is no longer needed (no more requests or manual shutdown), the
destroy()method is called to perform cleanup tasks like closing database connections and releasing resources.
This process resembles the stages of a lifecycle: birth, growth, operation, and end, each with specific tasks and objectives.
In summary, our code should inherit from the HttpServlet class, override its methods, and integrate these overrides into Tomcat's existing framework. We only need to focus on data processing, while other operations are handled automatically by Tomcat.
Introduction
HttpServletRequest represents an HTTP request class used to receive HTTP requests from clients. Many attributes in HttpServletRequest correspond to request header attributes, so understanding request headers helps in learning this class.
An HTTP request consists of four parts:
- First line = Method + URL + Version
- Request headers: Composed of key-value pairs
- Empty line
- Body
Common HttpServletRequest Methods
Obtaining First Line Information and Header Data
@WebServlet("/requestInfo")
public class RequestInfoHandler extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
StringBuilder responseBuilder = new StringBuilder();
// 1. Get first line information
responseBuilder.append(req.getMethod());
responseBuilder.append("<br>");
responseBuilder.append(req.getRequestURI());
responseBuilder.append("<br>");
responseBuilder.append(req.getProtocol());
responseBuilder.append("<br>");
// 2. Get request header information
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) {
String key = headerNames.nextElement();
String value = req.getHeader(key);
responseBuilder.append(key + ": " + value + "<br>");
}
resp.getWriter().write(responseBuilder.toString());
}
}
Obtaining Query String from Request
The query string, often containing user information like login credentials, is frequently used in business logic. Its location in the request varies depending on the HTTP method:
- For GET requests: Query string is in the URL
- For POST requests: Query string is in the body
Note: The URL technically includes the query string, but Servlet methods like getRequestURL() return a URL without it.
GET Method
For GET requests, the query string is in the first line of the request. We can use getParameter() to retrieve values.
@WebServlet("/getParams")
public class GetParameterHandler extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Retrieve query string parameters
// Assuming format: username=value&password=value
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("Username: " + username);
System.out.println("Password: " + password);
}
}
When accessing "http://127.0.0.1:8080/yourapp/getParams?username=john&password=12345", the console displays the username and password.
POST Method
For POST requests, the query string is in the body. Different body formats require different parsing approaches:
- Form data format
- JSON format
Form Data Format
When the body is organized as form data with Content-Type: application/x-www-form-urlencoded, we use the same getParameter() method as with GET requests.
JSON Format
For JSON-formatted bodies, native Servlet doesn't provide parsing capabilities. We need the Jackson library, which is Spring's recommended JSON processing library.
First, add the Jackson dependency to your pom.xml:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>
Then, create a class to map JSON data:
class UserRequest {
public String username;
public String password;
}
Now, handle the JSON data in your Servlet:
@WebServlet("/Params")
public class JsonParameterHandler extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Convert JSON string to Java object
UserRequest userRequest = objectMapper.readValue(req.getInputStream(), UserRequest.class);
// Process parameters
String username = userRequest.username;
String password = userRequest.password;
String userInfo = "Username: " + username + "<br>Password: " + password;
System.out.println(userInfo);
// Convert Java object back to JSON for response
String Response = objectMapper.writeValueAsString(userInfo);
resp.getWriter().write(Response);
}
}
Common Methods
setStatus()
Used to set the status code of the response.
@WebServlet("/setStatusCode")
public class StatusCodeHandler extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Set status code directly
// resp.setStatus(404);
// More flexible approach for error messages
resp.sendError(404, "The requested resource was not found");
}
}
setHeader()
Sets headers in the response. For example, to enable auto-refresh:
@WebServlet("/autoRefresh")
public class AutoRefreshHandler extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("refresh", "1"); // Refresh every second
resp.getWriter().write("" + System.currentTimeMillis());
}
}
sendRedirect()
Used for redirection (3xx status codes).
@WebServlet("/redirectPage")
public class RedirectHandler extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Manual approach
// resp.setStatus(302);
// resp.setHeader("Location", "https://example.com");
// Simplified approach
resp.sendRedirect("https://example.com");
}
}
Alternatively, you can implement redirection on the client-side using JavaScript:
<html>
<head>
<title>Redirection Example</title>
<script>
window.onload = function() {
setTimeout(function() {
window.location.href = "https://www.example.com";
}, 3000); // 3 seconds
};
</script>
</head>
<body>
<h1>This page will redirect to example.com in 3 seconds</h1>
</body>
</html>