当前位置: 首页 > news >正文

【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.xdnf.cn/news/1311967.html

相关文章:

  • CUDA 编程笔记:CUDA延迟隐藏
  • [优选算法专题二滑动窗口——最大连续1的个数 III]
  • huggingface TRL中是怎么获取参考模型的输出的
  • Swift 实战:实现一个简化版的 Twitter(LeetCode 355)
  • 新手向:GitCode疑难问题诊疗
  • Java 10 新特性及具体应用
  • 嵌入式硬件篇---电感串并联
  • 2^{-53} 单位舍入误差、机器精度、舍入的最大相对误差界限
  • 实例分割-动手学计算机视觉13
  • docker安装mongodb及java连接实战
  • Effective C++ 条款45:运用成员函数模板接受所有兼容类型
  • Linux怎么查看服务器开放和启用的端口
  • 【原理】C# 字段、属性对比及其底层实现
  • illustrator插件大全 免费插件介绍 Ai设计插件集合 (3)
  • Python语言一键整理xhs评论 基于github的开源项目 MediaCrawler
  • Linux进程概念(四)环境地址变量
  • 同创物流学习记录2·电车
  • 链式二叉树的基本操作——遍历
  • 实时计算 记录
  • 美国服务器环境下Windows容器工作负载基于指标的自动扩缩
  • 从盲区到全域:黎阳之光视频孪生+AI智能算法驱动智慧机场三维感知革命
  • 4.6 Vue 3 中的模板引用 (Template Refs)
  • CSS复习
  • Jenkins安装部署(Win11)和常见配置镜像加速
  • SysTick寄存器(嘀嗒定时器实现延时)
  • 要导入StandardScaler类进行数据标准化,请使用以下语句:
  • VS Code配置MinGW64编译ALGLIB库
  • 《C语言程序设计》笔记p10
  • 【数据分享】上市公司供应链成本分摊数据(2007-2024)
  • 【数据结构】-2- 泛型