一、引言
在 Java Web 開發領域,JSP(JavaServer Pages)和 Servlet 是兩個至關重要的技術,它們共同構成了動態網頁開發的基礎。Servlet 作為服務器端的 Java 程序,負責處理客戶端請求并生成響應;而 JSP 則是一種簡化的 Servlet 開發方式,允許開發者在 HTML 頁面中嵌入 Java 代碼,使頁面的開發更加直觀和便捷。本文將深入探討 Servlet 的生命周期、請求響應處理機制,以及 JSP 與 Servlet 的交互原理,并通過一個真實的項目實戰來加深理解。
二、Servlet 詳解
2.1 Servlet 生命周期
Servlet 的生命周期包括加載、實例化、初始化、服務和銷毀五個階段,每個階段都對應著特定的方法調用。以下是詳細的生命周期流程圖:
2.1.1 加載
當客戶端首次請求訪問一個 Servlet 時,Web 容器(如 Tomcat)會查找該 Servlet 的類文件,并將其加載到內存中。
2.1.2 實例化
Web 容器使用 new
關鍵字創建 Servlet 類的實例。一個 Servlet 類在整個 Web 應用程序的生命周期中通常只會被實例化一次。
2.1.3 初始化
在實例化之后,Web 容器會調用 Servlet 的 init()
方法進行初始化操作。init()
方法只會被調用一次,通常用于加載配置文件、建立數據庫連接等初始化工作。以下是一個簡單的 Servlet 初始化示例:
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;public class MyServlet implements Servlet {@Overridepublic void init(ServletConfig config) throws ServletException {System.out.println("Servlet 初始化");}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {// 服務方法}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {// 銷毀方法}
}
2.1.4 服務
當客戶端發送請求時,Web 容器會調用 Servlet 的 service()
方法來處理請求并生成響應。service()
方法會根據請求的類型(如 GET、POST)調用相應的 doGet()
或 doPost()
方法。以下是一個處理 GET 請求的示例:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;@WebServlet("/myServlet")
public class MyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {res.setContentType("text/html;charset=UTF-8");PrintWriter out = res.getWriter();out.println("<html>");out.println("<head><title>Hello Servlet</title></head>");out.println("<body>");out.println("<h1>Hello, Servlet!</h1>");out.println("</body>");out.println("</html>");}
}
2.1.5 銷毀
當 Web 應用程序關閉或 Servlet 被卸載時,Web 容器會調用 Servlet 的 destroy()
方法進行資源釋放操作,如關閉數據庫連接、釋放文件句柄等。
2.2 請求響應處理
在 Servlet 中,通過 HttpServletRequest
和 HttpServletResponse
對象來處理客戶端請求和返回響應。
2.2.1 請求參數解析
HttpServletRequest
對象提供了一系列方法來獲取請求參數,如 getParameter()
、getParameterValues()
等。以下是一個解析請求參數的示例:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;@WebServlet("/paramServlet")
public class ParamServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {String name = req.getParameter("name");String age = req.getParameter("age");res.setContentType("text/html;charset=UTF-8");PrintWriter out = res.getWriter();out.println("<html>");out.println("<head><title>Request Parameters</title></head>");out.println("<body>");out.println("<h1>Name: " + name + "</h1>");out.println("<h1>Age: " + age + "</h1>");out.println("</body>");out.println("</html>");}
}
2.2.2 響應內容設置
HttpServletResponse
對象用于設置響應的內容類型、狀態碼和輸出響應內容。以下是一個設置響應內容的示例:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;@WebServlet("/responseServlet")
public class ResponseServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {res.setContentType("text/plain;charset=UTF-8");res.setStatus(HttpServletResponse.SC_OK);PrintWriter out = res.getWriter();out.println("這是一個響應示例");}
}
三、Servlet 與 JSP 的交互
3.1 JSP 本質
JSP 本質上是 Servlet 的一種特殊形式。當 JSP 頁面第一次被請求時,Web 容器會將 JSP 頁面翻譯成一個 Servlet 類,并編譯成字節碼文件。這個過程由 JSP 引擎自動完成,開發者無需手動干預。以下是 JSP 翻譯為 Servlet 的流程圖:
3.2 協同工作原理
Servlet 和 JSP 可以協同工作實現動態網頁開發。通常,Servlet 負責處理業務邏輯和數據處理,而 JSP 負責頁面的展示。以下是一個簡單的項目架構圖,展示了 Servlet 和 JSP 的協同工作方式:
四、真實項目實戰
4.1 項目需求
開發一個簡單的用戶信息管理系統,包括用戶信息的添加、查詢和顯示功能。
4.2 項目結構圖
user-management-system
├── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ ├── controller
│ │ │ ├── AddUserServlet.java
│ │ │ └── ListUsersServlet.java
│ │ └── model
│ │ └── User.java
│ └── webapp
│ ├── WEB-INF
│ │ └── web.xml
│ ├── addUser.jsp
│ └── listUsers.jsp
4.3 源碼實現
4.3.1 User.java
package com.example.model;public class User {private String name;private int age;public User(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}
}
4.3.2 AddUserServlet.java
package com.example.controller;import com.example.model.User;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;@WebServlet("/addUser")
public class AddUserServlet extends HttpServlet {private static List<User> users = new ArrayList<>();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {String name = req.getParameter("name");int age = Integer.parseInt(req.getParameter("age"));User user = new User(name, age);users.add(user);res.sendRedirect("listUsers");}
}
4.3.3 ListUsersServlet.java
package com.example.controller;import com.example.model.User;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;@WebServlet("/listUsers")
public class ListUsersServlet extends HttpServlet {private static List<User> users = new ArrayList<>();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {req.setAttribute("users", users);req.getRequestDispatcher("listUsers.jsp").forward(req, res);}
}
4.3.4 addUser.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head><title>添加用戶</title>
</head>
<body><form action="addUser" method="post"><label for="name">姓名:</label><input type="text" id="name" name="name" required><br><label for="age">年齡:</label><input type="number" id="age" name="age" required><br><input type="submit" value="添加"></form>
</body>
</html>
4.3.5 listUsers.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head><title>用戶列表</title>
</head>
<body><h1>用戶列表</h1><table border="1"><tr><th>姓名</th><th>年齡</th></tr><c:forEach items="${users}" var