【Servlet】(Servlet API HttpServlet 处理请求 HttpServletRequest 打印请求信息 前端给后端传参)
文章目录
- Servlet API
- HttpServlet
- 处理请求
- HttpServletRequest
- 打印请求信息
- 前端给后端传参
Servlet API
Servlet中常用的API
HttpServlet

实际开发的时候主要重写 doXXX 方法, 很少会重写 init / destory / service
destory 服务器终止的时候会调用.
//下面的注解把当前类和一个HTTP请求的路径关联起来
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {@Overridepublic void init() throws ServletException {//重写init 插入自己"初始化"相关的逻辑System.out.println("init");}@Overridepublic void destroy() {System.out.println("destroy");}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//这个只是在服务器的控制台打印System.out.println("hello world");//要想把hello world返回到客户端,需要使用下面的代码//getWriter 会得到一个Writer对象resp.getWriter().write("hello world");}
}

上面的destroy能不能被执行到有待商榷,如果是通过Smart Tomcat 的停止按钮,这个操作本质上是通过Tomcat的8005端口,主动停止,可以触发destroy.如果是直接杀进程,此时可能就来不及执行destroy就没了.因此不太推荐使用destroy.
service每次收到http请求就出触发(路径匹配)
@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.service(req, resp);}
init / destory / service 这三个方法是HttpServlet中最关键的三个方法.
Servlet的声明周期是怎么回事?
- 开始的时候执行init
- 每次收到请求执行service
- 销毁之前执行destroy
处理请求
@WebServlet("/method")
public class MethodServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("doGet");resp.getWriter().write("doGet");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("doPost");resp.getWriter().write("doPost");}@Overrideprotected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("doPut");resp.getWriter().write("doPut");}@Overrideprotected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("doDelete");resp.getWriter().write("doDelete");}
}
我们刷新页面只有doGet请求,想要获得别的请求可以利用postman这个软件来实现:

也可以通过ajax来构造请求:先在webapp目录下创建test.html.

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><!-- 使用这个页面来构造ajax请求 --><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script><script>$.ajax({type: 'get',url: 'method',success: function(body, status){console.log(body);}});</script>
</body>
</html>
然后重启服务器,在网址栏输入:http://127.0.0.1:8080/hello_servlet/test.html然后刷新在控制台就能看到doGet请求了.想要获取别的请求,直接在代码中改就可以了,需要注意的是我们在编写Servlet代码的时候,每次修改代码,要及得重新启动服务器.

此处写的路径是相对路径,相对路径的基准目录是该html所在的路径.此处写method就相当于在http://127.0.0.1:8080/hello_servlet的基础上,再拼上一个method

绝对路径的写法:

HttpServletRequest
这个类表示的是HTTP请求.这个对象是Tomcat自动构造的,Tomcat会实现监听端口,接受连接,解析请求,构造请求对象等一系列工作.
下面的表格就是一些典型的方法:
| 方法 | 描述 |
|---|---|
| String getProtocol() | 返回请求协议的名称和版本 |
| String getMethod() | 返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT |
| String getRequestURI() | 从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的一部分 |
| String getContextPath() | 返回指示请求上下文的请求 URI 部分 |
| String getQueryString() | 返回包含在路径后的请求 URL 中的查询字符串 |
| Enumeration getParameterNames() | 返回一个 String 对象的枚举,包含在该请求中包含的参数的名称 |
| String getParameter(Stringname) | 以字符串形式返回请求参数的值,或者如果参数不存在则返回null |
| String[] getParameterValues(String name) | 返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回 null |
| Enumeration getHeaderNames() | 返回一个枚举,包含在该请求中包含的所有的头名 |
| String getHeader(String name) | 以字符串形式返回指定的请求头的值 |
| String getCharacterEncoding() | 返回请求主体中使用的字符编码的名称 |
| String getContentType() | 返回请求主体的 MIME 类型,如果不知道类型则返回 null |
| int getContentLength() | 以字节为单位返回请求主体的长度,并提供输入流,或者如果长度未知则返回 -1 |
| InputStream getInputStream() | 用于读取请求的 body 内容. 返回一个 InputStream 对象 |
打印请求信息
@WebServlet("/showRequest")
public class ShowRequestServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置响应的 content-type 告诉浏览器 响应的body里的格式是啥样的resp.setContentType("text/html");//搞个 StringBuilder 把这些api的结果拼起来,统一写回到响应中StringBuilder stringBuilder = new StringBuilder();stringBuilder.append(req.getProtocol());stringBuilder.append("<br>");stringBuilder.append(req.getMethod());stringBuilder.append("<br>");stringBuilder.append(req.getRequestURI());stringBuilder.append("<br>");stringBuilder.append(req.getContextPath());stringBuilder.append("<br>");stringBuilder.append(req.getQueryString());stringBuilder.append("<br>");//获取到 header 中所有的键值对Enumeration<String> headerNames = req.getHeaderNames();while (headerNames.hasMoreElements()){String headerName = headerNames.nextElement();stringBuilder.append(headerName + ": " + req.getHeader(headerName));stringBuilder.append("<br>");}resp.getWriter().write(stringBuilder.toString());}
}
在浏览器通过 URL http://127.0.0.1:8080/hello_servlet/showRequest 访问, 可以看到:

前端给后端传参
1.通过GET里的query string
在前端给后端传两个数字,一个是同学的studentId,一个是classId
@WebServlet("/getParameter")
public class GetParameterServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//预期浏览器会发一个形如 /getParameter?studentId=10&classId=20 这样的请求// 借助req 里的 getParameter方法就能拿到 query string 中的键值对内容//getParameter 得到的是 String 类型的结果String studentId = req.getParameter("studentId");String classId = req.getParameter("classId");resp.setContentType("text/html");resp.getWriter().write("studentId = " + studentId + " classId = " + classId);}
}

如果key在query string中不存在,此时就返回值就是null
2.通过POST,借助form表单的方式
对于前端是form表单这样格式的数据(也是键值对,和query string的格式一样,只是这部分内容在body中),后端还是使用getParameter来获取.
前端代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><form action="postParameter" method="post"><input type="text" name="studentId"><input type="text" name="classId"><input type="submit" value="提交"></form>
</body>
</html>

后端代码:
@WebServlet("/postParameter")
public class PostParameterServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String studentId = req.getParameter("studentId");String classId = req.getParameter("classId");resp.setContentType("text/html");resp.getWriter().write("studentId = " + studentId + " classId = " + classId);}
}

使用getParameter 既可以获取到query string 中的键值对,也可以获取到form表单构造的body中的键值对.

3.POST里的json
json是一种非常主流的数据格式,也是键值对结构.

我们可以把body按照这个格式来组织.前端可以通过ajax的方式来构造出这个内容,更简单的方法使用postman直接构造.

后端代码:
@WebServlet("/postParameter2")
public class PostParameter2Servlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//通过这个方法来处理 body 为 json 格式的数据//直接把 req 对象里 body 完整的读取出来//getInputStream// 在流对象中读多少字节取决于Content-Lengthint length = req.getContentLength();byte[] buffer = new byte[length];InputStream inputStream = req.getInputStream();inputStream.read(buffer);//把这个字节数组构造成 String 打印出来String body = new String(buffer,0,length,"utf8");System.out.println("body =" + body);resp.getWriter().write(body);}
}
然后在postman那块点击Send请求,服务器也相对应打印出了从body中读出的数据.

总结:借助postman构造出post请求,body就是json数据,请求到达Tomcat,Tomcat解析成req对象,再通过req.getInputStream读取body内容,把读出的结果构造成响应往回写,最后postman客户端收到了对应的结果.
当前通过json传递数据,但是服务器这边只是把整个body读出来,没有按照键值对的方式来处理,还不能根据key获取value,为了解决这个问题,我们可以使用jackson第三方库.
通过maven引入第三方库:


将所选的内容粘贴到pom.xml当中:

然后上面的后端代码就需要改变:
class Student{public int studentId;public int classId;
}
@WebServlet("/postParameter2")
public class PostParameter2Servlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {Student student = objectMapper.readValue(req.getInputStream(),Student.class);System.out.println(student.studentId + ", " + student.classId);}
}

相关文章:
【Servlet】(Servlet API HttpServlet 处理请求 HttpServletRequest 打印请求信息 前端给后端传参)
文章目录 Servlet APIHttpServlet处理请求 HttpServletRequest打印请求信息前端给后端传参 Servlet API Servlet中常用的API HttpServlet 实际开发的时候主要重写 doXXX 方法, 很少会重写 init / destory / service destory 服务器终止的时候会调用. //下面的注解把当前类和…...
java中右移>>和无符号右移>>>的区别
public static void main(String[] args) {byte[] dest new byte[2];dest[0] 0x15; //0001 0101dest[1] (byte) 0xfb;//1111 1011System.out.println((dest[0] >> 4) & 0xff);//右移 应该是0000 0001 十进制结果显示1 结果也是1,正确System.out.printl…...
牛客周赛 Round 7
目录 A 游游的you矩阵 题目: 题解: AC 代码: B 游游的01串操作 题目: 题解: AC 代码: C 游游的正整数 题目: 题解: AC 代码: D 游游的选数乘积 题目…...
R语言生存分析(机器学习)(1)——GBM(梯度提升机)
GBM是一种集成学习算法,它结合了多个弱学习器(通常是决策树)来构建一个强大的预测模型。GBM使用“Boosting”的技术来训练弱学习器,这种技术是一个迭代的过程,每一轮都会关注之前轮次中预测效果较差的样本,…...
k8s和docker简单介绍
当涉及到容器技术和容器编排时,Docker和Kubernetes是两个重要的概念。我将更详细地介绍它们以及它们之间的关系。 Docker: Docker是一种容器化技术,它允许你将应用程序及其依赖项打包到一个称为"容器"的封闭环境中。每个容器都包…...
Lua学习记录
Lua基础了解 Lua的注释通过 (-- 单行注释,--[[ ]] 多行注释)可以不加; 多个变量赋值,按顺序赋值,没有则为nil; function的简单用法,多个返回值配合多重赋值,以end为结束标志 Lua下标从1开始&…...
三分钟完美解决你的C盘内存过大爆红
一、清理回收站 二、清理桌面 建议一 不要在桌面放太多图标或者文件会占用过多的内存,可以放到其他盘建议二、 将位置移动到别的盘 三、手动删除下载文件与缓存文件 日常使用中会通过Windows下载各种文件资料到电脑中,它默认也是直接下载在C盘中的。如果我们在以…...
C++ - equal(比较两个vector元素)
C标准库的std::equal函数。这个函数用于比较两个范围的元素是否相等。 在使用std::equal函数时,您需要提供两个范围的迭代器,以及一个可选的谓词函数(predicate)。函数会比较第一个范围内的元素和第二个范围内的元素是否相等。如果…...
多线程:线程池
线程池 提前创建多个线程放入线程池中,使用时直接获取,使用完直接放入池中;可以避免频繁创建销毁,实现重复利用,类似生活中的公共交通工具。好处:提高相应速度;降低资源消耗;便于线…...
9.3.2.2网络原理(传输层TCP)
TCP全部细节参考RFC标准文档 一.TCP特点: 有连接,可靠传输,面向字节流,全双工. 二.TCP数据报: 1.端口号是传输层的重要概念. 2.TCP的报头是变长的(UDP是固定的8字节),大小存在4位首部长度中,用4个bit位(0~15)表示长度单位是4字节.(TCP报头最大长度是60字节,前面20字节是固定…...
ssm+mybatis无法给带有下划线属性赋值问题
原因:mybaitis根据配置,将有下划线的字段名改为了驼峰格式。 具体见:ssmmybatis无法给带有下划线属性赋值问题,无法获取数据库带下划线的字段值 - 开发者博客 解决方式: 直接将实体类中的下划线去掉返回值使用resul…...
学习笔记-JVM监控平台搭建
SpringBoot Actuator 1 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> </dependency>2 开启配置 # 暴露所有的监控点【含Prometheus】 management.endpoin…...
使用css实现时间线布局(TimeLine)
前言 在使用uni-app开发微信小程序过程中,遇到了时间轴布局,由于每项的内容高度不一致,使用uniapp自带的扩展组件uni-steps,样式布局无法对齐竖线,于是自己造轮子,完成特殊的布局。显示效果如下࿱…...
深入浅出 栈和队列(附加循环队列、双端队列)
栈和队列 一、栈 概念与特性二、Stack 集合类及模拟实现1、Java集合中的 Stack2、Stack 模拟实现 三、栈、虚拟机栈、栈帧有什么区别?四、队列 概念与特性五、Queue集合类及模拟实现1、Queue的底层结构(1)顺序结构(2)链…...
前端基础(二)
前言:前端开发框架——Vue框架学习。 准备工作:添加Vue devtools扩展工具 具体可查看下面的这篇博客 添加vue devtools扩展工具添加后F12不显示Vue图标_MRJJ_9的博客-CSDN博客 Vue官方学习文档 Vue.js - 渐进式 JavaScript 框架 | Vue.js MVVM M…...
ORB-SLAM2学习笔记7之System主类和多线程
文章目录 0 引言1 整体框架1.1 整体流程 2 System主类2.1 成员函数2.2 成员变量 3 多线程3.1 ORB-SLAM2中的多线程3.2 加锁 0 引言 ORB-SLAM2是一种基于特征的视觉SLAM(Simultaneous Localization and Mapping)系统,它能够从单个、双目或RBG…...
gin的占位符:和通配符*
1、用法 在 Gin 路由中,可以使用一个通配符(*)或一个占位符(:)来捕获 URL 的一部分。 r.GET("/royal/:id", func(c *gin.Context) {id : c.Param("id")//fmt.Println("into :id")c.Str…...
【量化课程】08_2.深度学习量化策略基础实战
文章目录 1. 深度学习简介2. 常用深度学习模型架构2.1 LSTM 介绍2.2 LSTM在股票预测中的应用 3. 模块分类3.1 卷积层3.2 池化层3.3 全连接层3.4 Dropout层 4. 深度学习模型构建5. 策略实现 1. 深度学习简介 深度学习是模拟人脑进行分析学习的神经网络。 2. 常用深度学习模型架…...
12-数据结构-数组、矩阵、广义表
数组、矩阵、广义表 目录 数组、矩阵、广义表 一、数组 二.矩阵 三、广义表 一、数组 这一章节理解基本概念即可。数组要看清其实下标是多少,并且二维数组,存取数据,要先看清楚是按照行存还是按列存,按行则是正常一行一行的去读…...
Idea 反编译jar包
实际项目中,有时候会需要更改jar包源码来达到业务需求,本文章将介绍一下如何通过Idea来进行jar反编译 1、Idea安装decompiler插件 2、找到decompiler插件文件夹 decompiler插件文件夹路径为:idea安装路径/plugins/java-decompiler/lib 3、…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
