深入理解 JSP 与 Servlet:原理、交互及实战应用

news/2025/2/23 14:45:31

一、引言

在 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 初始化示例:

java">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 {
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("Servlet 初始化");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        // 服务方法
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
        // 销毁方法
    }
}
2.1.4 服务

当客户端发送请求时,Web 容器会调用 Servlet 的 service() 方法来处理请求并生成响应。service() 方法会根据请求的类型(如 GET、POST)调用相应的 doGet() 或 doPost() 方法。以下是一个处理 GET 请求的示例:

java">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 {
    @Override
    protected 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() 等。以下是一个解析请求参数的示例:

java">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 {
    @Override
    protected 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 对象用于设置响应的内容类型、状态码和输出响应内容。以下是一个设置响应内容的示例:

java">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 {
    @Override
    protected 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 项目结构图

java">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
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
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<>();

    @Override
    protected 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
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<>();

    @Override
    protected 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
java"><%@ 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
java"><%@ 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

http://www.niftyadmin.cn/n/5863491.html

相关文章

Grok-3:人工智能领域的新突破

近日&#xff0c;xAI公司推出的最新AI模型——Grok-3&#xff0c;在Chatbot Arena中一举夺魁&#xff0c;以破纪录的1402分傲视群雄&#xff0c;不仅刷新了大型语言模型&#xff08;LLMs&#xff09;的评分上限&#xff0c;更标志着AI技术的一次重大飞跃。本文将深入探讨Grok-3…

虚拟机从零实现机器人控制

1. 系统安装 因Docker不适合需要图形界面的开发&#xff0c;因此使用虚拟机VMware方便可视化界面方式查看效果&#xff0c;相关软件可以从官网下载&#xff0c;这里有一整套免费安装文件百度网盘地址&#xff1a; 2. ROS安装 Ubuntu 22.04&#xff1a;https://docs.ros.org…

python-leetcode-两两交换链表中的节点

24. 两两交换链表中的节点 - 力扣&#xff08;LeetCode&#xff09; # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val val # self.next next class Solution:def swapPairs(self, head: Opti…

ai-financial-agent - 为金融投资打造的AI代理

探索人工智能在投资研究中的应用。本项目仅用于**教育**目的&#xff0c;不用于真实交易或投资。 作者声明&#xff1a; 本项目仅用于教育和研究目的。 不用于真实交易或投资不提供任何保证或担保过去的表现并不代表未来的结果Creator 对经济损失不承担任何责任咨询财务顾问…

c++中sleep是什么意思(不是Sleep() )

sleep 函数在 C 语言中用于暂停程序执行指定的秒数&#xff0c;语法为 sleep(unsigned int seconds)。当 seconds 为 0 时&#xff0c;函数立即返回&#xff0c;否则函数将使进程暂停指定的秒数&#xff0c;并返回实际暂停的时间。 sleep 函数在 C 中的含义 sleep 函数是 C 标…

WinSCP 连接到 Ubuntu 虚拟机

要使用 WinSCP 连接到 Ubuntu 虚拟机&#xff0c;一般采用 SFTP 或 SCP 协议进行文件传输。以下是详细步骤&#xff1a; 1. 确保虚拟机网络可访问 首先&#xff0c;你的 Ubuntu 虚拟机需要允许外部访问&#xff1a; 如果使用 NAT 网络&#xff1a;需要设置端口转发&#xff0…

<02.22>Leetcode100

滑动窗口要求是我们的窗口大小和对应的窗口序列和需要是单调增的&#xff0c;换个话说就是元素的正负是一致的&#xff0c;我right之后序列和变大&#xff0c;left--之后序列和变小。 import java.io.*; import java.util.*; /* 输入 abcabcbb*/ public class Main {public sta…

[ Vim ] 常用命令 and 配置

Vim 指导 Vim常用命令&配置1 Command1.1 copy & paste1.2 syntax highlight 2 Configuration Vim常用命令&配置 1 Command 1.1 copy & paste copy: yy or yy[n] paste: p 1.2 syntax highlight vim 命令行&#xff1a;:colorscheme [xxx] 2 Configuratio…