如何获取HTTP请求时间与响应时间【附源码】

news/2024/10/22 4:50:25/

在这里插入图片描述

文章目录

  • 一、问题描述
  • 二、抓包观察
  • 三、查找文档
  • 四、思考尝试
  • 五、精益求精
  • 六、源码解说

一、问题描述

今日遇到了一个问题,要去获取HTTP报文在请求响应的时间,因为没有原生的API可以调用,所以需要一定的技巧~

  • 下面主体的框架和代码,我使用了form表单去构造一个POST请求,然后在Servlet中重写doPost()方法,然后实现获取请求时间和响应时间的代码逻辑
<form action="print" method="post"><input type="submit" value="打印信息">
</form>
@WebServlet("/print")
public class printServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//...}
}

二、抓包观察

我们可以先去观察一下在发起POST请求后这个HTTP请求报文中是否在这个请求时间,如果有的其实可以把它通过一定手段获取到

  • 但遗憾的是,我并没有发现任何与时间相关的东西😥

在这里插入图片描述

  • 那再到请求报文中去看看的话,就发现了与时间相关的内容,不过对照现在的时间仔细一看的话,却查了不少,网上一搜就发现GMT是格林尼治时间,要比现在的时候早上8个小时,但看到一个时间却非常激动,想着如何拿到它

在这里插入图片描述

三、查找文档

因为【HttpServletRequest】和【HttpServletResponse】给我们提供了许多原生API,所以我们可以去找找看有哪些API是我们可以用得上的,这里推荐直接进官网 ——> 链接

在这里插入图片描述

  • 可以看到,无论是前者还是后者都未我们提供了很多的方法,这也我也会在代码中使用几个,不过找了一圈我发现完全没有获取时间的那种API,于是就没有再查找下去了

在这里插入图片描述

四、思考尝试

再找了很久还是一无所获,干脆就想着自己去手动获取一下这个时间

  • 此时我就想到了Java里面的Date类,可以获取当前系统的时间,以及随之对应的是格式化解析SimpleDateFormat(),于是便立马写下了这几句代码
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEEE");//格式化日期
Date currentTime = new Date();//获取当前时间
String date = formatter.format(currentTime).toString();

💬 但是要怎么使用这个当前时间呢?去获取哪段时间呢?

  • 首先我就提出了上面这个问题,思考了一下从Tomcat解析HTTP请求到将其交给Servlet做处理,那么能够最早获取到时间的地方就是一开始进入doPost()的时候,我们记录下当前的时间,就可以将其近似于HTTP的请求时间

💬 请求时间有了,那响应时间呢?也用这个去求吗?

  • 这个的话不一定,因为刚才我们看了HTTP的响应报文,也就是服务端在处理完数据后给浏览器返回的一个响应,里面是存在【Date】这个时间的,你可以选择使用getHeaderNames()先获取到整个报文的头部,因为他的返回值是一个Collection集合,所以你可以通过遍历集合的方式与getHeader()相配合格式化地输出里面的内容,这里我就不细说了
  • 也是一样,我们可以通过上面这种方式去获取响应时间,何时获取才是最正确的呢?那就是在resp.getWriter().write()这个发还响应之前去获取时间,这是最后的机会了!

五、精益求精

通过返回我们在后端代码中获取到的时间,将其返还给浏览器时便看到这个【请求时间】和【响应时间】是一样的,这是为什么呢?

在这里插入图片描述

  • 仔细观察我设置的日期格式化,是精确到秒的,如果你有一点计算机常识的话就可以知道计算机的运行速度是很快的,基本是以纳秒为单位,此时我们若是只精确到秒 的话可能还看不太出来,应该再多精确几位
yyyy-MM-dd HH:mm:ss
  • 可以看到,此时我精确到了纳秒的级别,此时再去观察的话就会有所不同
yyyy-MM-dd HH:mm:ss.SSSSSSSSS
  • 可以看到虽然精确了很多位数,但是二者之间的差距还是很小,毕竟计算机的处理速度也是非常快的

在这里插入图片描述

但是这么去做的只是钻了一个牛角尖🐂,后面我又想到了一个更聪明的办法

  • 那就是让程序等待一段时间!
try {Thread.sleep(500);      //让程序暂停0.5s
} catch (InterruptedException e) {throw new RuntimeException(e);
}
  • 学习过Java多线程的同学一定马上就能反应过来了,可以使用Thread类中的sleep()方法让程序睡上几秒,然后再去获取时间。此时我们再去观察【请求时间】和【响应时间】的话就会有些差距了。如果你想让差距更加明显的话可以让程序多睡一会

在这里插入图片描述

六、源码解说

这里的话附上我们解决本体所用的源码

前端:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>表单</title>
</head>
<body><form action="print" method="post"><input type="submit" value="打印信息"></form>
</body>
</html>

后端:

@WebServlet("/print")
public class printServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf-8");// 在doPost()方法开始时获取一下请求时间SimpleDateFormat formatter=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSSSS");//格式化日期Date currentTime=new Date();//获取当前时间String date=formatter.format(currentTime).toString();StringBuilder stringBuilder = new StringBuilder();System.out.println("-------------------------------------------------");stringBuilder.append("请求的URL = " +  req.getRequestURL());   //请求的URLstringBuilder.append("<br>");stringBuilder.append("请求方法 = " + req.getMethod());        //请求方法stringBuilder.append("<br>");stringBuilder.append("请求时间 = " + date);                                  //请求时间stringBuilder.append("<br><br>");try {Thread.sleep(500);      //让程序暂停0.5s} catch (InterruptedException e) {throw new RuntimeException(e);}// 在doPost()方法快结束时获取一下响应时间currentTime = new Date();//获取当前时间String date2 = formatter.format(currentTime).toString();stringBuilder.append("响应时间 = " + date2);stringBuilder.append("<br>");stringBuilder.append("响应状态码 = " + resp.getStatus());stringBuilder.append("<br>");resp.getWriter().write(stringBuilder.toString());}
}

💬 稍微来讲一下后端的这块逻辑

  • 这边我主要使用到的就是这个【StringBuilder】类,使用它构造出来的对象,我们需要在单线程的环境下连接多个字符串,此时用它最合适了,通过里面的append()方法去进行连接,这里我测试了Reques和Response两个类中的方法,打印出了HTTP报文的一些内容
  • 还要注意,有些同学在看我这句代码的时候很疑惑,所我怎么把前端的代码写到后端来了
stringBuilder.append("<br>");
  • 这里主要就是依赖于前面的这句代码,我将当前body中的数据格式设置为了HTML,代表可以识别HTML代码,所以这个<br>就会被当做换行了,若是不写这个的话所有的内容都会挤在一起的
 resp.setContentType("text/html;charset=utf-8");
  • 最后的这句话就是将拼接的StringBuilder类型字符串转换为String类型并发还给浏览器一个响应,将拼接的内容都打印展示出来
resp.getWriter().write(stringBuilder.toString());

2023年5月22日记

在这里插入图片描述


http://www.ppmy.cn/news/93175.html

相关文章

超级独角兽 Databricks 的崛起之路

在数据扩张以及 AI 兴起的时代&#xff0c;数据存储和分析平台拥有巨大价值和能量。 随着互联网数据的爆炸性增长&#xff0c;数据已经成为企业的新型资源&#xff0c;犹如石油般重要。越来越多的企业希望利用各种结构化和非结构化数据来发挥自己的优势。 然而&#xff0c;他…

android 12.0app安装黑名单(限制app安装)

1.概述 在12.0定制化开发中,最近由项目需求要实现对某些app应用安装限制也就是app安装黑名单功能,在黑名单之中的应用会被限制安装,不能安装到系统中 功能分析 在系统中PMS就是负责管理app安装和卸载的,在安装的时候判断是不是在安装黑名单中,然后决定是否安装这个app 2.…

【华为OD机试真题2023B卷 JAVA】代码编辑器

华为OD2023(B卷)机试题库全覆盖,刷题指南点这里 代码编辑器 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 某公司为了更高效的编写代码, 邀请你开发一款代码编辑器程序。 程序的输入为 已有的代码文本和指令序列,程序需输出编辑后的最终文本。指针初始位置位于…

CSDN如何获得铁粉

文章目录 前言一、提供有价值的内容二、坚持写作并保持频率三、积极互动和维护粉丝关系四、针对受众变化调整文章方向总结 前言 最近看到CSDN也是有这个活动&#xff0c;我也想参加一下&#xff0c;现在我就为大家分享一下怎么样获得铁粉吧。 一、提供有价值的内容 提供有价…

Linux 内核启动流程与入口函数分析

从启动引导程序 bootloader&#xff08;uboot&#xff09;跳转到 Linux 内核后&#xff0c;Linux 内核开始启动&#xff0c;今天我们分析一下 Linux 内核启动入口。 跳转过去初始化肯定是在汇编文件中&#xff0c;根据架构可以选择不同的平台&#xff0c;这里看一下链接汇编文…

一些小的问题2

自己实现strcpy、strcat、strlen和strcmp。 注意&#xff0c;这里的 my_strcpy 和 my_strcat 函数的第一个参数是目标字符串&#xff0c;第二个参数是源字符串。另外&#xff0c;my_strcmp 函数的返回值为0表示两个字符串相等&#xff0c;小于0表示前者小于后者&#xff0c;大…

Thonny-适合初学者小白的开箱即用的轻量级 Python IDE

如果你是一位Python初学者小白,那最适合Thonny它了&#xff0c;如果不是初学者&#xff0c;请选择PyDev和Pycharm。 Thonny是一款面向初学者小白的轻量级 IDE&#xff0c;可以让初学者更好更快的入门上手 Python&#xff0c;而不致于在环境上浪费过多的时间。 取之 Python&…

图神经网络GNN GCN AlphaFold2 虚拟药物筛选和新药设计

文章目录 图神经网络1. Geometric Deep LearningRepresentation learning 表征学习机器学习的数据类型&#xff1a;序列、网格、图引出GNN 2. Graph Neural NetworksMachine Learning Lifecyclelearning graph is hardFeature Learning in GraphsWays to Analyze NetworksA Nai…