Servlet 体系结构

news2026/2/20 7:40:15

文章目录

    • Servlet 类图
    • SpringBoot 测试案例
    • HttpServlet 原理
      • 伪代码理解原理
      • 理解差异
      • 为什么 `HttpServlet` 实现 `service()`

Servlet 类图

---
title: Servlet 类图
---

classDiagram
    direction LR
  
    class Servlet {
        <<interface>>
        +init(conf)
        +service(req,res)
        +destroy()
    }

    class GenericServlet {
        +getServletConfig()
        +getServletContext()
    }

    Servlet <|-- GenericServlet

    class HttpServlet {
        +doGet()
        +doPost()
        +doPut()
        +doDelete()
        +doHead()
        +doOptions()
    }

    GenericServlet <|-- HttpServlet

    class LegacyServlet {
        +init()
        +doGet()
        +destroy()
    }
    
    HttpServlet <|-- LegacyServlet
  • Servlet:Servlet 体系根接口
  • GenericServlet:Servlet 抽象实现类
  • HttpServlet:对 HTTP 协议封装的 Servlet 实现类

SpringBoot 测试案例

创建 HttpServlet 测试类

@WebServlet("/demo")
public class ServletDemoSecond extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("get...");
        resp.setContentType("text/plain");
        resp.getWriter().write("GET SUCCESS");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("post...");
    }
}

Servlet 规范不允许同一容器内多个 Servlet 映射到完全相同的 URL 路径,这会导致容器启动时抛出 IllegalArgumentException

因为之前就是将 HttpServlet 测试类和 Servlet 测试类都制定同一个 URL,且 Servlet 测试类还设置了 loadOnStartup 导致了怎么都测试不了 HttpServlet 测试类

可以启动 SpringBoot 项目调用 /demo 接口进行测试,也可以通过 SpringBootTest 进行测试

需要以下依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <version>3.5.0</version>
  <scope>test</scope>
</dependency>

<dependency>
  <groupId>io.rest-assured</groupId>
  <artifactId>rest-assured</artifactId>
  <version>5.4.0</version>
</dependency>

创建测试类进行测试

@SpringBootTest(classes = DemoApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ServletDemoTest {

    @LocalServerPort
    private int port;

    @Test
    public void testDoGet() {
        RestAssured.given().port(port).when().get("/demo").then().statusCode(HttpStatus.OK.value());
    }
}

启动服务输出结果

get...
2025-06-04T21:42:40.711+08:00  INFO 7686 --- [ionShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown        : Commencing graceful shutdown. Waiting for active requests to complete
2025-06-04T21:42:42.717+08:00  INFO 7686 --- [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown        : Graceful shutdown complete
Servlet 销毁

测试类输出结果

get...

HttpServlet 原理

伪代码理解原理

通过伪代码了解 Servlet 和 HttpServlet 的关系,通过创建 MyHttpServlet 类来理解

public class MyHttpServlet implements Servlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        // 根据请求方式不同,调用不同的方法
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        // 获取请求方式
        String method = req.getMethod();

        // 判断请求方式
        if ("GET".equals(method)) {
            // GET 请求方式的处理逻辑
            doGet(servletRequest, servletResponse);
        } else if ("POST".equals(method)) {
            // POST 请求方式的处理逻辑
            doPost(servletRequest, servletResponse);
        }
    }

    protected void doPost(ServletRequest servletRequest, ServletResponse servletResponse) {
        System.out.println("调用 MyHttpServlet 的 doPost 方法");
    }

    protected void doGet(ServletRequest servletRequest, ServletResponse servletResponse) {
        System.out.println("调用 MyHttpServlet 的 doGet 方法");
    }
}

将之前的测试案例改成继承 MyHttpServlet,即 public class ServletDemoSecond extends MyHttpServlet {}

@WebServlet("/demo")
public class ServletDemoSecond extends MyHttpServlet {
    @Override
    protected void doPost(ServletRequest servletRequest, ServletResponse servletResponse) {
        super.doPost(servletRequest, servletResponse);
        System.out.println("post...");
    }

    @Override
    protected void doGet(ServletRequest servletRequest, ServletResponse servletResponse) {
        super.doGet(servletRequest, servletResponse);
        System.out.println("get...");
    }
}

启动 SpringBoot 服务进行测试,控制台输出结果

调用 MyHttpServlet 的 doGet 方法
get...

理解差异

层级是否协议相关service() 谁来实现小结
Servlet 接口实现类 决定只定义生命周期方法 init / service / destroy
GenericServlet 抽象类协议无关仍然抽象→ 子类必须实现把大量通用功能(getServletConfig()、getServletContext()、log() …)封装好
HttpServlet 抽象类与 HTTP 绑定自己实现,再分发到 doGet / doPost 等你只需覆写需要的 “动词方法”

GenericServlet 设计之初就强调 “Generic”——它既可能处理 FTP,也可能处理自定义二进制协议。没有任何通用逻辑可以写进 service(),所以只能交给子类。

模版方法模式 Template Method:抽象类负责实现可复用的公共骨架(初始化,配置,日志),把变化点留给子类,实现开闭原则

为什么 HttpServlet 实现 service()

  • 根据 HttpServlet 是针对于 HTTP 协议的 Servlet,HttpServlet.service() 可以统一读取 request.getMethod(),再路由到对应的 doXXX() 方法
  • 降低重复代码,如果 service() 还是抽象,所有业务 Servlet 都得自己写上述 switch 逻辑 → 代码膨胀且易错
  • 因为已锁定 HTTP 协议,可以把“按方法分派”这一层通用逻辑封装好,再让你通过 doGet、doPost 专注业务。如此既减样板代码,又符合模板方法与责任分离的设计哲学

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

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

相关文章

蒙特卡罗模拟: 高级应用的思路和实例

蒙特卡罗模拟不仅仅是一种理论练习&#xff0c;它还是一种强大的工具&#xff0c;在金融、医疗保健、物流等领域都有实际应用。本篇文章将探讨高级和复杂的现实生活场景&#xff0c;深入探讨它们的细微差别&#xff0c;并通过详细的解释在 Python 中实现它们。 什么是蒙特卡罗…

数据分析Agent构建

数据分析agent构建 代码资料来源于 Streamline-Analyst&#xff0c;旨在通过该仓库上的代码了解如何使用大语言模型构建数据分析工具&#xff1b; 个人仓库&#xff1a;Data-Analysis-Agent-Tutorial 不同的在于 Data-Analysis-Agent-Tutorial 是在 Streamline-Analyst 基础…

vscode配置lua

官网下载lua得到如下 打开vscode的扩展下载如下三个 打开vscode的此处设置 搜索 executorMap&#xff0c;并添加如下内容

【笔记】MSYS2 的 MINGW64 环境 全面工具链

#工作记录 MSYS2 的 MINGW64 环境&#xff08;mingw64.exe&#xff09;&#xff0c;下面是为该环境准备的最全工具链安装命令&#xff08;包括 C/C、Python、pip/wheel、GTK3/GTK4、PyGObject、Cairo、SDL2 等&#xff09;。 这一环境适用于构建原生 64 位 Windows 应用程序。…

国内头部的UWB企业介绍之品铂科技

一、核心优势与技术实力‌ ‌厘米级定位精度‌ 自主研发的ABELL无线实时定位系统&#xff0c;在复杂工业环境中实现静态与动态场景下‌10-30厘米‌高精度定位&#xff0c;尤其擅长金属设备密集的化工、电力等场景&#xff0c;抗干扰能力行业领先。‌多技术融合能力‌ 支持卫星…

Prj10--8088单板机C语言8259中断测试(2)

1.测试结果 2.全部代码 #include "tiny_stdarg.h" // 使用自定义可变参数实现#define ADR_273 0x0200 #define ADR_244 0x0400 #define LED_PORT 0x800 #define PC16550_THR 0x1f0 #define PC16550_LSR 0x1f5 / //基本的IO操作函数 / char str[]"Hel…

35.x64汇编写法(二)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 上一个内容&#xff1a;34.x64汇编写法&#xff08;一&#xff09; 上一个内容写了&#xff0c;汇编调…

安全大模型的思考

马上要准备2025年的护网了&#xff0c;最近就一直很忙&#xff0c;被事情裹挟着前进&#xff0c;忙的晕头转向&#xff0c;近乎感冒&#xff0c;昨天部门搞了一场AI大模型培训&#xff0c;演讲者有着很深的技术底蕴&#xff0c;我听到了一句关于Sass数据验证这块大为感悟&#…

NineData云原生智能数据管理平台新功能发布|2025年5月版

本月发布 6 项更新&#xff0c;其中重点发布 3 项、功能优化 3 项。 重点发布 数据库 DevOps - 多源敏感数据保护 敏感数据扫描能力大幅扩展&#xff0c;新增支持 TiDB、Doris、SelectDB、OceanBase MySQL、GreatSQL、StarRocks、ClickHouse、SingleStore、Lindorm 9 种大数据…

Linux可执行文件ELF文件结构

目标文件格式 编译器编译源代码后生成的文件叫做目标文件&#xff0c;而目标文件经过编译器链接之后得到的就是可执行文件。那么目标文件到底是什么&#xff1f;它和可执行文件又有什么区别&#xff1f;链接到底又做了什么呢&#xff1f;接下来&#xff0c;我们将探索一下目标…

DisplayPort 2.0协议介绍(1)

最近开始学习DisplayPort 2.0协议&#xff0c;相比于DP1.4a&#xff0c;最主要的是速率提升到了10Gbps/lane&#xff0c;还有就是128b/132b编码方式的修改。至于速率13.5Gbps和20Gbps还只是可选项&#xff0c;在DP2.1协议才成为必须支持选项。 那在实现技术细节上有哪些变化呢…

I2C通信讲解

I2C总线发展史 怎么在一条串口线上连接多个设备呢&#xff1f; 由于速度同步线是由主机实时发出的&#xff0c;所以主机可以按需求修改通信速度&#xff0c;这样在一条线上可以挂接不同速度的器件&#xff0c;单片机和性能差的器件通信&#xff0c;就输出较慢的脉冲信号&#x…

基于回归算法的心理健康预测(EDA + 预测)

心理健康涵盖情感、心理与社会福祉&#xff0c;影响认知、情绪和行为模式&#xff0c;决定压力应对、人际交往及健康决策&#xff0c;且在生命各阶段&#xff08;从童年至成年&#xff09;均至关重要。心理健康与身体健康同为整体健康的核心要素&#xff1a;抑郁会增加糖尿病、…

【新品解读】一板多能,AXRF49 定义新一代 RFSoC FPGA 开发平台

“硬件系统庞杂、调试周期长” “高频模拟前端不稳定&#xff0c;影响采样精度” “接收和发射链路难以同步&#xff0c;难以扩展更多通道” “数据流量大&#xff0c;处理与存储跟不上” 这些是大部分客户在构建多通道、高频宽的射频采样链路时&#xff0c;面临的主要问题。…

贪心算法应用:线性规划贪心舍入问题详解

贪心算法应用&#xff1a;线性规划贪心舍入问题详解 贪心算法是一种在每一步选择中都采取当前状态下最优的选择&#xff0c;从而希望导致结果是全局最优的算法策略。在线性规划问题中&#xff0c;贪心算法特别是贪心舍入技术有着广泛的应用。下面我将全面详细地讲解这一主题。…

YOLO在C#中的完整训练、验证与部署方案

YOLO在C#中的完整训练、验证与部署方案 C# 在 YOLO 部署上优势明显&#xff08;高性能、易集成&#xff09;&#xff0c;但训练能力较弱&#xff0c;通常需结合 Python 实现。若项目对开发效率要求高且不依赖 C# 生态&#xff0c;建议全程使用 Python&#xff1b;若需深度集成…

洛谷题目:P2761 软件补丁问题 (本题简单)

个人介绍: 题目传送门: P2761 软件补丁问题 - 洛谷 (luogu.com.cn) 前言: 这道题是一个典型的状态搜索问题,核心目标就是利用给定d额多个补丁程序,将包含若干错误的软件修复成没有错误的状态,并且要使得修复过程当中的总耗时最少。下面是小亦为大家阐述滴思路: 1、状态…

智慧园区数字孪生全链交付方案:降本增效30%,多案例实践驱动全周期交付

在智慧园区建设浪潮中&#xff0c;数字孪生技术正成为破解传统园区管理难题的核心引擎。通过构建与物理园区1:1映射的数字模型&#xff0c;实现数据集成、状态同步与智能决策&#xff0c;智慧园区数字孪生全链交付方案已在多个项目中验证其降本增效价值——某物流园区通过该方案…

【OpenGL学习】(四)统一着色和插值着色

文章目录 【OpenGL学习】&#xff08;四&#xff09;统一着色和插值着色统一着色&#xff08;Flat/Uniform Shading&#xff09;插值着色&#xff08;Interpolated Shading&#xff09; 【OpenGL学习】&#xff08;四&#xff09;统一着色和插值着色 着色器介绍&#xff1a; h…

在 CentOS 上安装 Docker 和 Docker Compose 并配置使用国内镜像源

在 CentOS 上安装 Docker 和 Docker Compose 并配置使用国内镜像源&#xff0c;可以加速镜像下载速度。以下是详细的步骤&#xff1a; 一、安装 Docker 移除旧版本的 Docker&#xff08;如果有&#xff09;&#xff1a; sudo yum remove docker \docker-client \docker-client…