【Java web】Servlet 详解

一、什么是 Servlet?—— 你不知道的 "网页服务员"

想象你走进一家网红书店(比如 "在线 Java 书店"),想买一本《Java 编程思想》。你告诉前台服务员你的需求,服务员去仓库找书、包装、收款,最后把书递给你 ——这个 "服务员" 的角色,在 Java Web 中就是 Servlet

Servlet 本质:运行在服务器上的 Java 小程序,专门处理客户端(浏览器 / APP)的 HTTP 请求。当你在浏览器输入http://bookstore.com/books时,就是 Servlet 在背后接收请求、查询数据库、生成动态网页内容并返回给你。

为什么需要 Servlet
没有 Servlet 时,服务器只能返回静态 HTML 页面(内容固定)。有了 Servlet,才能实现 "用户登录后显示个性化书单"、"下单后修改库存" 等动态功能 —— 就像书店服务员能根据不同顾客的需求提供定制服务,而不是所有人都拿同一本样书。

二、Servlet 的 "一生"—— 从入职到退休

Servlet 的生命周期由Web 容器(比如 Tomcat,相当于书店的 "管理系统")全程管理,就像服务员的工作流程由书店规定一样,分为三个阶段:

1. 入职培训(初始化:init()

  • 触发时机:第一次有顾客(请求)来时,或书店开门(容器启动)时(需配置<load-on-startup>)。
  • 工作内容:加载 "工作手册"(初始化参数,如数据库连接信息)、准备 "工具"(创建数据库连接池)。
  • 特点一生只执行一次,类似服务员上班第一天的培训,之后直接上岗。
// Servlet初始化示例(类比服务员入职登记)
public class BookServlet extends HttpServlet {private String dbUrl; // 数据库地址(工作工具)@Overridepublic void init(ServletConfig config) throws ServletException {super.init(config);// 获取web.xml中配置的初始化参数(从管理系统拿工作手册)dbUrl = config.getInitParameter("dbUrl"); System.out.println("BookServlet初始化完成,数据库地址:" + dbUrl);}
}

2. 接待顾客(处理请求:service()

  • 触发时机每次有请求来时执行,比如用户查询 "Java 书籍"、"添加购物车"。
  • 工作内容
    • 接收请求数据(顾客说 "我要 Java 书");
    • 调用doGet()/doPost()处理(根据请求类型分工,GET 查数据,POST 提交数据);
    • 返回响应(把书递给顾客)。
  • 特点:多线程并发处理!容器会为每个请求分配一个线程,类似多个服务员同时接待不同顾客。
// 处理GET请求(类比顾客查询书籍)
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 设置响应类型为HTML(告诉顾客"这是书单")response.setContentType("text/html;charset=UTF-8");// 获取输出流(准备说话)PrintWriter out = response.getWriter();// 从数据库查询书籍(服务员去仓库找书)List<String> books = getBooksFromDB(); // 生成HTML响应(口头报书单)out.println("<h1>Java书籍列表</h1>");for (String book : books) {out.println("<p>" + book + "</p>");}
}// 模拟从数据库查询书籍
private List<String> getBooksFromDB() {List<String> books = new ArrayList<>();books.add("《Java编程思想》");books.add("《Effective Java》");return books;
}

3. 下班清理(销毁:destroy()

  • 触发时机:书店打烊(容器关闭)或 Servlet 被移除时。
  • 工作内容:释放资源,比如关闭数据库连接池、保存未完成的工作(如订单数据)。
  • 特点一生只执行一次,类似服务员下班前整理工具、交接工作。
@Override
public void destroy() {// 关闭数据库连接(下班前锁好仓库)closeDBConnection();System.out.println("BookServlet已销毁,资源已释放");
}

三、Servlet 如何 "接到订单"?—— 映射与访问

顾客(客户端)怎么找到对应的 Servlet?需要通过URL 映射,就像顾客根据 "文学区"、"科技区" 的指示牌找到对应的服务员。

1. 注解映射(推荐!简单快捷)

@WebServlet注解直接指定 URL,无需配置文件:

// 当用户访问 http://bookstore.com/books 时,由BookServlet处理
@WebServlet("/books") 
public class BookServlet extends HttpServlet {// ...处理请求的代码...
}

2. web.xml 配置(不推荐!传统方式)

web/WEB-INF/web.xml中配置映射,适合复杂场景(如多个 URL 对应一个 Servlet):

<!-- 声明Servlet(注册服务员) -->
<servlet><servlet-name>BookServlet</servlet-name> <!-- 服务员姓名 --><servlet-class>com.bookstore.BookServlet</servlet-class> <!-- 服务员全类名 --><init-param> <!-- 初始化参数(工作手册) --><param-name>dbUrl</param-name><param-value>jdbc:mysql://localhost:3306/bookstore</param-value></init-param>
</servlet><!-- 映射URL(指定服务区域) -->
<servlet-mapping><servlet-name>BookServlet</servlet-name> <!-- 对应哪个服务员 --><url-pattern>/books</url-pattern> <!-- 访问路径 -->
</servlet-mapping>

四、核心 API:Servlet 的 "工具箱"

Servlet 有两个核心对象,就像服务员的 "记事本" 和 "对讲机",帮助处理请求和响应:

1. HttpServletRequest(请求对象)

  • 作用:获取客户端请求信息,比如 URL 参数、表单数据、Cookie。
  • 常用方法
    • String getParameter(String name):获取表单参数(如request.getParameter("bookId")获取书籍 ID);
    • HttpSession getSession():获取会话对象(记录用户登录状态);
    • RequestDispatcher getRequestDispatcher(String path):请求转发(让另一个 Servlet 协助处理)。
// 获取用户查询的书籍类型(比如用户输入"Java")
String category = request.getParameter("category"); 
if ("Java".equals(category)) {// 查询Java书籍...
}

2. HttpServletResponse(响应对象)

  • 作用:设置响应信息,比如返回 HTML 内容、重定向页面、设置 Cookie。
  • 常用方法
    • PrintWriter getWriter():获取输出流,向客户端写内容;
    • void sendRedirect(String location):重定向(让客户端跳转到新页面);
    • void setContentType(String type):设置响应类型(如text/htmlapplication/json)。
// 重定向到购物车页面(用户添加书籍后跳转到购物车)
response.sendRedirect("/cart"); 

五、Servlet 5.0 新变化:你需要知道的 "新规定"

如果你用 Spring Boot 3.0+,会发现 Servlet 的包名变了!这是因为 Java EE 改名为 Jakarta EE,就像 "中国移动" 改名为 "中国电信",服务没变,但 "公司名" 换了:

旧版本(Java EE)新版本(Jakarta EE 9+)
javax.servlet.*jakarta.servlet.*
javax.servlet.http.*jakarta.servlet.http.*

代码示例

// 旧版本
import javax.servlet.http.HttpServlet;// 新版本(Spring Boot 3.0+)
import jakarta.servlet.http.HttpServlet; 

六、小白避坑指南:Servlet 的 "那些坑"

1. 线程安全问题:别让服务员 "抢笔记"

问题:Servlet 是单实例多线程的,多个请求会同时调用service()方法。如果用实例变量存请求数据,会导致线程安全问题(比如两个用户的数据互相覆盖)。
解决:用局部变量(每个线程独立)或加锁(synchronized,但性能差,不推荐)。

public class BookServlet extends HttpServlet {// 错误:实例变量(所有线程共享,会冲突)private String currentUser; @Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) {// 正确:局部变量(每个线程独立)String currentUser = request.getParameter("username"); }
}

2. 忘记释放资源:服务员 "下班不锁门"

问题init()中创建的数据库连接、IO 流如果不在destroy()中关闭,会导致资源泄漏(数据库连接耗尽)。
解决:在destroy()中显式关闭资源。

3. 混淆请求转发和重定向

请求转发(forward重定向(redirect
服务器内部跳转(服务员内部交接)告诉客户端 "去新地址"(顾客重新排队)
URL 不变(/booksURL 变为新地址(/cart
共享request域数据不共享数据(需用 Session 或 URL 参数)

示例

// 请求转发:让BookDetailServlet处理详情页(内部协作)
request.getRequestDispatcher("/bookDetail").forward(request, response);// 重定向:添加书籍后跳转到购物车(让用户看到新页面)
response.sendRedirect("/cart"); 

七、Servlet 的 "继任者"?—— 为什么现在很少直接写 Servlet?

你可能听说 "现在都用 Spring MVC/ Spring Boot,不用 Servlet 了"—— 其实Spring MVC 的底层就是 Servlet
Spring MVC 的DispatcherServlet是一个 "总服务员",负责把请求分发给不同的 Controller(具体服务员)。直接写 Servlet 就像手动洗碗,用 Spring MVC 就像用洗碗机,效率更高,但原理相通。

学习建议:先掌握 Servlet,再学 Spring MVC,就像先学会手动挡,再开自动挡更轻松~

八、总结:Servlet 的核心价值

Servlet 是 Java Web 的基石,它的作用就像餐厅的服务员、医院的护士 —— 不起眼但关键。理解 Servlet 的生命周期、请求处理流程,能帮你搞懂任何 Java Web 框架的底层逻辑。

下一篇我们将学习JSP——Servlet 的 "模板兄弟",让动态网页开发更简单!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/93360.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/93360.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库Microsoft Access、SQL Server和SQLite三者对比及数据库的选型建议

SQLite本质是代码库&#xff0c;Access是单文件桌面DB&#xff0c;SQL Server是正经的C/S架构数据库。这就像比较自行车、家用轿车和卡车&#xff0c;完全不同的设计目标。 核心区别对比表特性Microsoft AccessSQL ServerSQLite类型桌面DBMS (文件型)客户端/服务器 RDBMS嵌入式…

【C++】默认构造函数,参数化构造函数,拷贝构造函数,拷贝赋值运算符, 移动构造函数 ,移动赋值运算符

1. 默认构造函数 (Default Constructor) 作用&#xff1a; 无参创建对象 签名&#xff1a; ClassName() 特点&#xff1a; ①无参数或所有参数都有默认值 ②若未声明任何构造函数&#xff0c;编译器自动生成&#xff08;空实现&#xff09; ③用于容器默认初始化&#xff08;如…

办公效率提升指南:完成重复任务自动化

手动操作容易出错&#xff0c;尤其是在处理大量数据或复杂文档时。它将PDF转换、Word处理、Excel操作、OCR识别等高频功能融为一体&#xff0c;界面清爽无冗余&#xff0c;零广告打扰&#xff0c;专注提升工作效率。它内置七大核心模块&#xff1a;自动任务、系统工具、文件处理…

数字炼金术:当API工作流遇见AI客服—点石成金的智能革命!

目录 引言 一、蓝耘元生代MaaS平台概述 1.1 蓝耘平台的API服务 1.2 蓝耘平台的优势 二、初识蓝耘元生代MaaS平台—带你深度体验 2.1 从零开始——平台注册与环境搭建 2.2 蓝耘平台的优势在哪里&#xff1f; 三、API工作流调用技巧与实践 3.1 API工作流设计与调用流程 …

HackMyVM-Uvalde

目录信息搜集漏洞利用权限提升信息搜集 主机发现 ┌──(kali㉿kali)-[~] └─$ nmap -sn 192.168.21.0/24 Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-16 01:10 EDT Nmap scan report for dev.medusa.hmv (192.168.21.6) Host is up (0.00015s latency). MAC Addr…

「Java EE开发指南」如何使用MyEclipse中的Web Fragment项目?

开发者可以通过使用Web Fragment项目模块化应用程序部署描述符&#xff0c;本文提供如何使用它们的必要信息。 该特性在MyEclipse中可用。 MyEclipse v2025.1离线版下载 通过使用Web Fragment项目&#xff0c;您的Web应用程序部署描述符可以模块化&#xff0c;就像能够模块化…

redis的key过期删除策略和内存淘汰机制

一、key的过期删除策略 原由&#xff1a;一般情况下&#xff0c;在使用redis作缓存&#xff0c;对k设置过期时间&#xff0c;当过期时间到后&#xff0c;k还是占用内存的&#xff0c;并没有从内存中移除。 1.定时删除 在设置key的过期时间的同时&#xff0c;为该key创建一个定…

NVIDIA Nsight Deep Learning Designer使用

一、关于产品 1.1 产品介绍 NVIDIA Nsight Deep Learning Designer 是一款面向 AI 推理开发者的可视化建模与优化工具。它支持基于 ONNX 格式的神经网络模型编辑、结构可视化、性能分析与 TensorRT 引擎导出&#xff0c;帮助用户更高效地设计、调优和部署高性能推理模型。该工…

Android 常见100道面试题(完整版)

一、基础组件与核心原理Activity 相关Q1&#xff1a;请描述 Activity 的完整生命周期&#xff0c;从创建到销毁经历哪些关键方法&#xff1f;A&#xff1a;Activity 完整生命周期包括&#xff1a;onCreate&#xff08;初始化&#xff09;→ onStart&#xff08;可见&#xff09…

Navicat 为 SQLite 数据库设置密码指南

Navicat 为 SQLite 数据库设置密码指南 在 SQLite 中设置密码实际上是通过加密实现的&#xff0c;Navicat 使用 SQLCipher 扩展来提供数据库加密功能。以下是详细的操作方法和注意事项&#xff1a; 在 Navicat 中设置密码&#xff08;加密数据库&#xff09; 步骤 1&#xff1a…

Spring Framework:Java 开发的基石与 Spring 生态的起点

在 Java 技术领域&#xff0c;Spring Framework 无疑是一座里程碑式的存在。它不仅彻底改变了 Java 企业级应用的开发模式&#xff0c;更以其为核心衍生出了庞大的 Spring 生态系统&#xff0c;成为无数开发者构建应用的首选技术栈。本文将以 Spring Framework 为核心&#xff…

Unity中 terriaria草,在摄像机拉远的时候就看不见了,该怎么解决

在 Unity 中&#xff0c;当摄像机拉远时草就看不见&#xff0c;可能是由于地形细节距离设置、摄像机裁剪平面设置或 LOD&#xff08;Level of Detail&#xff09;设置不当导致的。以下是具体的解决方法&#xff1a;调整地形细节距离&#xff1a;选中场景中的地形对象&#xff0…

驱动开发系列63 - 编译 NVIDIA 的 open-gpu-kernel-modules 开源内核驱动及搭建调试环境

目录 一:通过apt方式安装nvidia 驱动 二:通过 .run 方式安装nvidia驱动 三:编译安装nvidia开源内核驱动 四:验证和调试 五:卸载驱动 1. 以apt方式安装nvidia 驱动的卸载方法 2. 以.run方式安装nvidia驱动的卸载方法 六:安装CUDA环境 一:通过apt方式安装nvidia 驱动…

Rocky Linux 9.2:从 /home 分区释放 10G 空间扩容到 / 根分区

在日常运维中&#xff0c;常见的问题之一就是安装的软件过多&#xff0c;导致根分区&#xff08;/&#xff09;空间不足&#xff0c;而其他分区&#xff08;例如 /home&#xff09;却有大量闲置空间。本文将演示如何在 Rocky Linux 9.2 上&#xff0c;通过 LVM&#xff08;Logi…

iis/iis express无需手动配置handlers,仅将 DLL 放入bin目录即可处理 HTTP 请求的功能

以下是使用VB.NET实现的方案&#xff0c;分别针对传统ASP.NET&#xff08;System.Web&#xff09;和ASP.NET Core 两种环境&#xff0c;实现无需手动配置handlers&#xff0c;仅将 DLL 放入bin目录即可处理 HTTP 请求的功能。 一、传统ASP.NET&#xff08;System.Web&#xff…

【DP】单词的划分

题目描述 有一个很长的由小写字母组成字符串。为了便于对这个字符串进行分析&#xff0c;需要将它划分成若干个部分&#xff0c;每个部分称为一个单词。出于减少分析量的目的&#xff0c;我们希望划分出的单词数越少越好。你就是来完成这一划分工作的。 输入 第一行&#xff0c…

UniApp 中使用 tui-xecharts插件(或类似图表库如 uCharts)

要在 UniApp 中使用 tui-xecharts插件&#xff08;或类似图表库如 uCharts&#xff09;&#xff0c;需遵循以下步骤。以下流程以 ​​uCharts​​&#xff08;官方推荐的高性能跨平台图表库&#xff09;为例&#xff0c;因其在 UniApp 生态中更成熟且文档完善。若需使用 tui-xe…

顺序表 —— OJ题

在上一篇文章中简单介绍了顺序表&#xff0c;这一篇文章讲解下一个比较经典的题&#xff1a;杨辉三角先看一下什么是杨辉三角下面解释&#xff1a;大概就是这个规律。而 ta 其实就是二维数组 即&#xff1a;0 1 1 1 1 2 1 2 1 3 1 3 3 1 4 1 4 6 4 1然后看一下这个题的要求…

基于单片机的防酒驾系统设计

一、引言1.1 研究背景与意义随着社会经济的快速发展&#xff0c;汽车保有量持续攀升&#xff0c;道路交通安全问题愈发凸显。酒后驾驶作为交通事故的主要诱因之一&#xff0c;严重威胁着人们的生命财产安全。据统计&#xff0c;全球每年因酒驾造成的交通事故死亡人数高达数十万…

Redis面试精讲 Day 22:Redis布隆过滤器应用场景

【Redis面试精讲 Day 22】Redis布隆过滤器应用场景 在高并发、大数据量的互联网系统中&#xff0c;如何高效判断一个元素是否存在于集合中&#xff0c;是缓存设计中的关键问题。尤其是在面对缓存穿透——即恶意或无效请求频繁查询不存在的数据&#xff0c;导致数据库压力剧增—…