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

javaweb--04

一、Servlet 基础概念

1. 核心定义

  • Servlet 是 Java 提供的一门动态 web 资源开发技术,用于生成动态网页内容。
  • Servlet 是JavaEE 规范之一,本质是一个接口,我们需要自定义类实现 Servlet 接口,由 web 服务器(如 Tomcat)来运行。
  • 官方定义:A servlet is a small Java program that runs within a Web server.(Servlet 是运行在 Web 服务器中的小型 Java 程序)

2. Servlet 快速入门步骤

  1. 创建 web 项目,导入 Servlet 依赖坐标(pom.xml)

    xml

    <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>

    scope=provided表示该依赖由 Tomcat 容器提供,打包时不打入 war 包。

  2. 定义类,实现 Servlet 接口,重写所有方法,在service()中编写业务逻辑

    java

    运行

    @WebServlet("/demo1") public class ServletDemo1 implements Servlet { @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("servlet hello world~"); } // 其他4个方法重写省略 }
  3. 配置访问路径:在类上使用@WebServlet注解,配置 Servlet 的访问路径
  4. 访问测试:启动 Tomcat,浏览器输入 URL 访问:http://localhost:8080/web-demo/demo1

3. Servlet 执行流程

  • Servlet 由谁创建?方法由谁调用?Servlet 由web 服务器(Tomcat)创建,Servlet 方法也由 web 服务器调用。
  • 服务器怎么知道 Servlet 一定有 service 方法?因为自定义 Servlet 必须实现 Servlet 接口,而 Servlet 接口中定义了service()方法,服务器通过接口规范保证方法存在。

二、Servlet 接口 5 大核心方法

表格

方法名作用调用时机调用次数
void init(ServletConfig config)初始化方法Servlet 第一次被访问时(默认),实例化后调用1 次
void service(ServletRequest req, ServletResponse res)提供服务方法每次 Servlet 被访问时多次
void destroy()销毁方法内存释放 / 服务器关闭时,Servlet 对象销毁前1 次
ServletConfig getServletConfig()获取 ServletConfig 对象任意时刻,用于获取 Servlet 配置信息按需调用
String getServletInfo()获取 Servlet 信息任意时刻,用于获取 Servlet 版本、作者等信息按需调用

各方法详细说明

1.init()初始化方法

java

运行

@Override public void init(ServletConfig config) throws ServletException { System.out.println("init..."); }
  • 作用:完成 Servlet 的初始化工作,如加载配置文件、创建数据库连接等
  • 参数ServletConfig:Servlet 配置对象,用于获取 Servlet 初始化参数
2.service()服务方法

java

运行

@Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("servlet hello world~"); }
  • 作用:处理客户端请求,生成响应
  • 参数:
    • ServletRequest req:封装 HTTP 请求信息
    • ServletResponse res:封装 HTTP 响应信息
  • 异常:ServletException(Servlet 异常)、IOException(IO 异常)
3.destroy()销毁方法

java

运行

@Override public void destroy() { // 资源释放逻辑 }
  • 作用:释放 Servlet 占用的资源,如关闭连接、销毁对象等
  • 调用时机:服务器正常关闭、Servlet 被卸载时

三、Servlet 生命周期

Servlet 运行在 Servlet 容器(web 服务器)中,生命周期由容器管理,分为 4 个阶段:

  1. 加载和实例化:默认情况下,当 Servlet第一次被访问时,由容器创建 Servlet 对象
  2. 初始化:实例化后,容器调用init()方法完成初始化,只执行 1 次
  3. 请求处理:每次请求 Servlet 时,容器调用service()方法处理请求,执行多次
  4. 服务终止:服务器关闭 / 内存释放时,容器调用destroy()方法释放资源,之后实例被 JVM 垃圾回收

loadOnStartup 配置(控制实例化时机)

通过@WebServlet注解的loadOnStartup属性,修改 Servlet 实例化时机:

java

运行

@WebServlet(urlPatterns = "/demo", loadOnStartup = 1)
  • 负整数(默认 -1):第一次被访问时创建 Servlet 对象
  • 0 或正整数:服务器启动时创建 Servlet 对象,数字越小,优先级越高

四、Servlet 体系结构

1. 继承体系

plaintext

Servlet(根接口) ↑ 实现 GenericServlet(抽象实现类,实现 Servlet 接口,空实现部分方法) ↑ 继承 HttpServlet(对 HTTP 协议封装的实现类,专门用于处理 HTTP 请求)

2. HttpServlet 使用

开发 B/S 架构的 Web 项目时,我们自定义 Servlet 直接继承 HttpServlet,无需直接实现 Servlet 接口。

使用步骤
  1. 继承 HttpServlet
  2. 重写doGet()doPost()方法,分别处理 GET 和 POST 请求

    java

    运行

    @WebServlet("/demo4") public class ServletDemo4 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 处理 GET 请求逻辑 } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 处理 POST 请求逻辑 // 通常让 doPost 调用 doGet,统一处理逻辑 doGet(req, resp); } }
原理

HttpServletservice()方法会自动获取请求方式,根据不同的请求方式(GET/POST/PUT/DELETE 等),调用对应的doGet()/doPost()/doPut()等方法,简化了开发。


五、关键补充

1. Servlet 与 HTTP 请求方式

  • 直接实现 Servlet 接口时,service()方法需要手动判断请求方式,再做不同处理
  • 继承HttpServlet后,由容器自动分发请求到对应doXxx()方法,开发更高效

2. 常见误区

  • Servlet单实例:一个 Servlet 类在容器中只会创建一个实例,所有请求共享同一个对象,因此要注意线程安全问题
  • init()只执行一次:适合做全局初始化,不要在init()中处理请求
  • service()每次请求都执行:核心业务逻辑写在这里,注意线程安全
http://www.jsqmd.com/news/631761/

相关文章:

  • Radioenge LoRaWAN模块AT指令库技术解析与嵌入式集成
  • 软考高级-系统分析师-案例分析:从单体到微服务的架构演进实战
  • 弹幕格式转换难题?用DanmakuFactory一键解决XML到ASS的专业转换
  • 新手别怕!用嘉立创EDA两层板搞定ESP8266最小系统PCB(附完整工程文件)
  • Eigen嵌入式线性代数库:轻量级矩阵计算与实时系统实践
  • 020、生产环境考量:异步支持、超时、重试与错误处理
  • 【LeetCode Hot 100】滑动窗口最大值——多种解法深度解析
  • 【服务出错问题排查记录】从一个“点击失败”开始:为什么“系统异常”其实是最差的错误设计
  • CodeMagicianT源
  • VSCode跑Python代码总报缺包?一个设置解决Conda环境识别问题
  • 性能核弹X4522首发“翻车”不断?赋缘汇全套调教方案出炉:五大旗舰平台稳如泰山,EFVI一键脚本封神!
  • Noir:一款键盘驱动的现代化数据库管理工具
  • 选型建议:基于职场新人的能力模型,深度分析一级与二级认证的匹配度
  • 021、LangChain Expression Language(LCEL):声明式构建复杂链
  • Consentium Starter Kit嵌入式传感器开发套件全栈解析
  • ERTEC 系列 PROFINET 芯片级硬件过滤器分析桌
  • 抖音下载器终极指南:如何高效批量下载无水印内容
  • Turbo Boost Switcher:掌控Mac性能波动的终极解决方案
  • 人工智能编程流程技能AI Dev Workflow
  • 告别脏数据!用Power Query这3招让你的Power BI报表加载速度翻倍
  • 手机端访问 Web 服务器
  • SE_BME680库:BME680温湿度补偿与IAQ鲁棒算法详解
  • Aria2 Pro Docker部署避坑指南:从RPC密钥到端口映射,一次讲清楚
  • ICMP协议
  • 【为什么你的node包 python包 总是在c盘】彻底解决c盘因为包太多而爆炸的问题
  • 备考策略:针对职场人的时间与精力,提供AI认证考试的高效备考与避坑方案
  • 从ViT到Swin:手把手教你理解那个让Transformer在CV领域“开窍”的Shifted Windows
  • 开源日程管理利器Calendso:从安装到集成的全流程指南
  • 深入解析Xilinx OSERDESE2原语:从基础配置到高速接口实战
  • STM32F746NG BSP详解:QSPI Flash驱动与LCD/SDRAM协同开发