【Servlet】——Servlet API 详解
个人主页:兜里有颗棉花糖
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创
收录于专栏【Servlet】
本专栏旨在分享学习Servlet的一点学习心得,欢迎大家在评论区交流讨论💌
目录
- 一、HttpServlet
- 二、HttpServletRequest
- 核心方法
- 代码示例1
- 如何获取query string和body(form格式)中的数据
- 获取body(json格式)中的数据
- jackon依赖的导入
- 三、HttpServletResponse
- setStatus
- setHeader
- 构造重定向响应
- 返回一个html界面
API就是一组类和方法,本文中我们学习Servlet API的三个类:HttpServlet、HttpServletRequest、HttpServletResponse。
一、HttpServlet
HttpServlet是我们编写Servlet代码用来的核心类,通过继承这个类并重写其中的方法,然后Tomcat去调用其中的代码逻辑。可以这样理解:我们这里写的代码(重写的方法)并不是我们自己手动调用手动执行的,而是将我们写地代码交给Tomcat,让Tomcat帮助我们执行调用这些代码。
核心方法如下:

Init方法:在webapp被加载的时候会调用此方法,可以使用该方法进行初始化操作。destroy方法:在webapp被销毁(或Tomcat结束)的时候执行destroy方法,可以使用该方法进行收尾工作。注意:该方法不能保证一定会被调用到。
这里分为两种情况。
第一种情况:通过8005端口给Tomcat发起一个特殊的请求,然后Tomcat就关闭了(这种情况可以调用到destroy方法)。
第二种情况:直接杀死Tomcat进程,比如说通过任务资源管理器直接结束Tomcat任务进程,此时就无法执行destroy方法。
实际开发中第二种情况占多数(尤其是在Linux中),这就提醒我们不能依赖destroy方法,因为该方法不一定被调用到。
service方法:每次收到请求会执行service方法,处理每个请求。一般会使用doXXX方法来替代service方法。
对于上述方法,浏览器只能构造Get方法,对于其它的方法浏览器并不方便构造。如果想要构造其它的请求方法,我们可以使用ajax或者postman。

实际开发中用到的最多的是Get和Post。
二、HttpServletRequest
HttpServletRequest是Java Servlet API提供的接口之一,用于表示客户端的HTTP请求。
一个HTTP请求中都有哪些信息都会在HttpServletRequest类中进行体现。当Tomcat接收到Http请求时,它将解析请求并将相关的信息填充到HttpServletRequest对象中,从而使开发人员可以方便地获取和处理这些信息。
核心方法
下图是HttpServletRequest的方法:

URI和URL:URI是唯一资源标识符,URL是唯一资源定位符;URI用来区分不同的资源,而URL就是用来区分不同资源的一种方式。我们可以这样理解,URL是URI的实现方式。实际开发中一般会混着用。
Enumeration getParameterNames()和String getParameter(String name)
我们直到请求中可以通过一些方式把自定义数据传递到服务器中,有两种方式:
第一种方式:query string,query string是键值对结构的数据,Tomcat收到请求后就会把query string解析成Map这样的键值对。然后使用getParameter就可以根据key获取到value;而getParameterNames是拿到所有的key。
第二种方式:body:如果是通过post form表单的形式提交表单的话,此时body中也是键值对的形式(和query string一样)。
getParameterValues方法:即一个key涉及到多个value。
Enumeration getHeaderNames()和String getHeader(String name):获取到请求头中的键值对,Tomcat收到请求后也会把请求头解析成Map。getHeader是通过key拿到指定的value;而getHeaderNames是拿到所有的key。
代码示例1
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.Enumeration;@WebServlet("/request")
public class RequestServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 下行代码就是为了显示告诉浏览器,浏览器拿到的内容是htmlresp.setContentType("text/html");// 调用req的各个方法,把得到的结果汇总到一个字符串中,然后统一返回到桌面上StringBuilder respBody = new StringBuilder();// 由于下面的内容在浏览器是按照html展示的,\n在浏览器上并不是换行,所以使用<br>来表示换行// 获得HTTP请求协议的版本号respBody.append(req.getProtocol());respBody.append("<br");// 获取HTTP请求方法respBody.append(req.getMethod());respBody.append("<br>");// 获取请求的URIrespBody.append(req.getRequestURI());respBody.append("<br>");// 将req.getContextPath()返回的上下文路径添加到respBody中respBody.append(req.getContextPath());respBody.append("<br>");// 返回的查询字符串添加到respBody字符串中的代码respBody.append(req.getQueryString());respBody.append("<br>");// 拼接headerEnumeration<String> headers = req.getHeaderNames();while(headers.hasMoreElements()) {String header = headers.nextElement();respBody.append("<br>");respBody.append(header + ": " + req.getHeader(header));}resp.getWriter().write(respBody.toString());}
}
跑起来之后如下图:

如何获取query string和body(form格式)中的数据
如何获取query string中的数据
代码如下:
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;@WebServlet("/parameter")
public class ParameterServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");System.out.println("username=" + username);System.out.println("password=" + password);resp.getWriter().write("OK");}
}
运行结果如下:


如何获取中body的数据
由于body有很多种格式,所以这里就拿form表单格式(和query string格式一样是键值对的格式)来举例。这里我们让客户端发送一个Post请求,同时使用form格式的数据在body中把数据进行传递。
代码如下:
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;@WebServlet("/parameter2")
public class Parameter2Servlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");System.out.println("username=" + username);System.out.println("password=" + password);resp.getWriter().write("OK");}
}
结果如下:


总结:使用
getParameter()方法可以用于获取query string中的value值以及form表单中的value值。
所以我们完全可以使用一种代码来获取query string中的value值以及form表单中的value值(doPost()方法用于处理POST请求,获取表单中的参数值。doGet()方法用于处理GET请求,获取查询字符串中的参数值)。
注意:上述两份代码的servlet path是不能重复的,否则会出现404报错。
获取body(json格式)中的数据
再来回顾一下json格式:
{username:lisi;password:9521;
}
json格式虽然在开发中也是经常会用到的一种格式,但是Servlet自身不能够对json格式的数据进行解析。解决方式是引入第三方库来进行解析(将键值对还原成Map这种key value的形式)。
解析json格式的第三方库也是有很多的,我们这里使用jackon来对json进行解析。
jackon依赖的导入

然后这里选择一个版本(建议选旧版本)

然后复制粘贴到pom.xml文件中去。

注意是复制粘贴到<dependencies></dependencies>标签中(一个dependencies标签可以包含多个依赖)。

最后刷新一下即可。
jackon依赖引入的是一个类两个方法:类是ObjectMapper,用于将Java对象转换为JSON格式的字符串,也可以将JSON字符串转换回相应的Java对象。
现在我们回归正题:获取body(json格式)中的数据(即客户端中的body按照json格式进行传输)。
readValue方法选择上图中的版本。该方法的作用就是把json格式的字符串解析成Java对象。
第一个参数(InputStream src)可以看到是一个流对象,表示json从哪里来。
第二个参数(JavaType valueType)用于指定一个类型:即json格式的字符串需要解析成什么类型的Java对象(这是一个将json格式的字符串映射成java对象的过程)。
关于第二个参数:我们需要定义一个类,该类的属性名称与 JSON 字符串中的字段匹配(如下图)
完成代码如下:
import com.fasterxml.jackson.databind.ObjectMapper;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;//{
// "username":"lisi",
// "password":"465"
//}class User {public String username;public String password;
}@WebServlet("/json")
public class JsonServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ObjectMapper objectMapper = new ObjectMapper();User user = objectMapper.readValue(req.getInputStream(),User.class);System.out.println("username=" + user.username + ", password=" + user.password);resp.getWriter().write("OK");}
}
运行结果如下:


总结:
readValue方法将req请求中的body(json格式)中的字符串读取并解析,然后构造成了user对象,而user中的属性就是body(json格式)中所体现的内容。
jackon还提供了一个方法可以将java对象转换成json格式的字符串。该方法为writeValueAsString()。
三、HttpServletResponse
HttpServletResponse是用于构造HTTP响应的对象,提供了一系列方法用于操作响应的状态码、头部信息(header)和响应体数据(body)。它和HTTP响应数据相匹配,可以用于向客户端发送响应数据。然后针对状态码、header、body这些属性就可以进行设置。
注意区分下面两个概念:
请求对象:拿到请求对象之后是为了获取对象中的属性(读操作)。
响应对象:拿到响应对象之后是为了设置对象中的属性(写操作)。
而对于
doXXX这样的方法的作用就是根据请求计算响应。
再强调一下:请求对象是Tomcat收到后对Http协议解析得到的对象。
而响应对象是Tomcat创建空的对象,然后在代码中把响应对象的属性设置好。
下面来看HttpServletResponse中的核心方法,如下:

addHeader():可能会出现key相同的两个键值对(一个key可以对应多个value)。另外,Java标准库的Map是不允许key重复的,Tomcat内部也不一定把header解析成Map。setHeader():一个key对应一个value。setCharacterEncoding:告诉浏览器按照什么样的字符集来解析响应的body。sendRedirect:用来设定重定向响应。
setStatus
代码示例1如下:
运行结果如下:
代码示例2如下:
运行结果如下:
在返回状态码的同时,可以给body写入数据,这样就可以得到
比较个性化的错误页面,比如:
上图就是搜狗的404错误页面。
上图就是百度的404错误页面。
上图是哔哩哔哩的404错误页面。
Tomcat同样有一个内置的404报错页面,虽然
setStatus方法并没有页面,但是sendError方法是有页面的。代码如下:
上图是Tomcat的404报错页面。
setHeader
我们通过使用setHeader方法来设置任意的响应报头。举例:通过refresh属性来设置浏览器自动刷新(比如refresh:2,意思就是浏览器每隔两秒就会自动刷新)。
代码如下:
运行结果如下(下图中的时间每隔两秒就会改变):
构造重定向响应
让页面重定向到百度主页。
注意:使用重定向一定要带有Location属性,然后用这个属性来描述你要重定向到哪个地方。
代码如下:

结果如下:



补充:
301:永久重定向
302:临时重定向
刚刚上述代码可以等价替换成下面代码:


即resp.sendRedirect("https://www.baidu.com");等价于resp.setStatus(302);resp.setHeader("Location","https://www.baidu.com");(浏览器看到302和https://www.baidu.com这两个字段就知道要跳转到百度)
返回一个html界面

结果如下:

为什么会出现乱码呢?
我们要知道,如果在IDEA中直接写一个中文字符串的话是按照utf-8进行编码的。但是浏览器默认是使用操作系统的编码方式来解析和显示页面,而windows简体中文版的默认编码方式是gdk,此时浏览器按照gdk的方式来解析utf-8的话就会出现上图中的乱码。
所以我们要设置一下让浏览器按照utf-8的方式进行解析(如下)。


上述代码还存在一个问题,如下(将doGet方法中的两行代码进行互换):
可以看到又出现了乱码。在Servlet中,为resp设置属性的时候,需要注意顺序:要先设置header,然后再设置body;否则如果先设置body的话此时header、status就已经定性而来不及修改了。
好了,以上就是本文的全部内容了。希望各位友友可以一键三连哈!!!

相关文章:
【Servlet】——Servlet API 详解
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【Servlet】 本专栏旨在分享学习Servlet的一点学习心得,欢迎大家在评论区交流讨论💌 目录 一、HttpServlet二、Htt…...
oracle主库增加redo组数
redo log(重做日志): 重做日志:简单来说就是,将oracle数据库的DML、DDL(数据库操作语言,数据库定义i语言)操作记录在日志中,方便恢复及备库使用,以组的方式管…...
lua只读表
参考《programming in lua》13.4.5中,详细介绍了只读表的用法。建立一个函数,传入一个table,传出一个代理table,其__index指向传入的table,__newIndex直接报error即可: --输入一个table,输出一…...
探索深度学习的边界:使用 TensorFlow 实现高效空洞卷积(Atrous Convolution)的全面指南
空洞卷积(Atrous Convolution),在 TensorFlow 中通过 tf.nn.atrous_conv2d 函数实现,是一种强大的工具,用于增强卷积神经网络的功能,特别是在处理图像和视觉识别任务时。这种方法的核心在于它允许网络以更高…...
HarmonyOS案例:摇杆游戏
本案例主要演示如何通过一系列的动画效果以及运算实现摇杆控制组件同步运动的功能,界面简陋无需在意。 欢迎大家的阅读和评价,也欢迎大佬们批评、指正,我将继续努力,奉上更加专业的、高效的代码案例。 import curves from ohos.c…...
Elasticsearch:构建自定义分析器指南
在本博客中,我们将介绍不同的内置字符过滤器、分词器和分词过滤器,以及如何创建适合我们需求的自定义分析器。更多关于分析器的知识,请详细阅读文章: 开始使用 Elasticsearch (3) Elasticsearch: analyzer…...
Git系列---远程操作
📙 作者简介 :RO-BERRY 📗 学习方向:致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持 引用 1.理解分布式版本控制…...
kafka客户端生产者消费者kafka可视化工具(可生产和消费消息)
点击下载《kafka客户端生产者消费者kafka可视化工具(可生产和消费消息)》 1. 前言 因在工作中经常有用到kafka做消息的收发,每次调试过程中,经常需要查看接收的消息内容以及人为发送消息,从网上搜寻了一下࿰…...
【从0上手Cornerstone3D】如何使用CornerstoneTools中的工具之工具介绍
简单介绍一下在Cornerstone中什么是工具,工具是一个未实例化的类,它至少实现了BaseTool接口。 如果我们想要在我们的代码中使用一个工具,则必须实现以下两个步骤: 使用Cornerstone的顶层addTool函数添加未实例化的工具 将工具添…...
02-Java抽象工厂模式 ( Abstract Factory Pattern )
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂 该超级工厂又称为其他工厂的工厂 在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类 每个生成的工厂都能按照工厂模式提供对象 …...
yarn/npm certificate has expired
目录 报错 原因:HTTPS 证书验证失败 方法 a.检查网络安全软件:可能会拦截或修改 HTTPS 流量 b.strict-ssl:false关闭验证【临时方法】 报错 info No lockfile found. [1/4] Resolving packages... error Error: certificate has expired at TLS…...
第十三篇【传奇开心果系列】Python的OpenCV库技术点案例示例:光流估计
传奇开心果短博文系列 系列短博文目录Python的OpenCV库技术点案例示例:光流估计短博文目录前言一、光流估计介绍二、Lucas-Kanade光流介绍和示例代码三、Horn-Schunck光流介绍和示例代码四、cv::calcOpticalFlowPyrLK()函数实现光流估计介绍和示例代码五、光流估计用于运动分析…...
iOS面试题
iOS面试题 1. 什么是iOS中的Autolayout? Autolayout是iOS开发中用于实现自适应界面布局的技术。它基于约束(Constraints)来描述视图之间的关系,以便在不同的设备和屏幕尺寸上正确地布局和调整视图。 Autolayout使用一组规则和优…...
【5G SA流程】5G SA下终端完整注册流程介绍
博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 本人就职于国际知名终端厂商,负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G算力网络技术标准研究。 博客内容主要围绕: 5G/6G协议讲解 …...
101 C++内存高级话题 内存池概念,代码实现和详细分析
零 为什么要用内存池? 从前面的知识我们知道,当new 或者 malloc 的时候,假设您想要malloc 10个字节, char * pchar new char[10]; char *pchar1 malloc(10); 实际上编译器为了 记录和管理这些数据,做了不少事情&…...
算计是一种混合了感性和理性的非纯粹逻辑系统
算计是人类带有动因的感性与理性混合超(计)算,是还未形成逻辑状态的非逻辑系统。算计是指人类在进行决策、推理、思考等活动时,融合了感性和理性的思维过程。它是一种超越纯粹逻辑思维的综合性思维方式。感性是指个体基于感觉、直…...
Python 处理小样本数据的文档分类问题
在处理小样本数据的文档分类问题时,可以尝试使用迁移学习或者基于预训练模型的方法,如BERT、GPT等。然而,直接在这里编写一个完整的深度学习文档分类代码超出了这个平台的限制,但我可以为你提供一个基本的思路和简单示例ÿ…...
centos7安装oracle
1 安装虚拟机 设置4G内存,硬盘40G 2 配置网络环境 2.1配置主机名 # vi /etc/hostname 修改为 oracle2.2 配置IP地址 # vi /etc/sysconfig/network-scripts/ifcfg-ens33 修改 BOOTPROTO"static" ONBOOT"yes" IPADDR192.168.109.110 NETMAS…...
Web html
目录 1 前言2 HTML2.1 元素(Element)2.1.1 块级元素和内联(行级)元素2.1.2 空元素 2.2 html页面的文档结构2.3 常见标签使用2.3.1 注释2.3.2 标题2.3.3 段落2.3.4 列表2.3.5 超链接2.3.6 图片2.3.7 内联(行级)标签2.3.8 换行 2.4 属性2.4.1 布尔属性 2.5 实体引用2.6 空格2.7 D…...
Go语言学习踩坑记
go: go.mod file not found in current directory or any parent directory; see go help mod 解决 资源下载: 序号文件地址1 1、Go IDE liteidex38.3-win64-qt5.15.2.zip Release x38.3 visualfc/liteide GitHub2 2、Go语言的编译环境 go1.21.6.windows-amd64.m…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...



















