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

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

一、问题描述

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

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

二、抓包观察

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

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

image.png

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

image.png

三、查找文档

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

image.png

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

image.png

四、思考尝试

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

  • 此时我就想到了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()这个发还响应之前去获取时间,这是最后的机会了!

五、精益求精

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

image.png

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

image.png

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

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

image.png

六、源码解说

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

前端:

<!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 {
    @Override
    protected 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());   //请求的URL
        stringBuilder.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());
相关文章
|
5天前
|
API 数据安全/隐私保护
Haskell中的HTTP请求:代理与响应状态检查
Haskell中的HTTP请求:代理与响应状态检查
|
2月前
|
JSON Java 数据格式
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
107 25
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
|
1月前
|
缓存 应用服务中间件 Apache
HTTP 范围Range请求
HTTP范围请求是一种强大的技术,允许客户端请求资源的部分内容,提高了传输效率和用户体验。通过正确配置服务器和实现范围请求,可以在视频流、断点续传下载等场景中发挥重要作用。希望本文提供的详细介绍和示例代码能帮助您更好地理解和应用这一技术。
89 19
|
2月前
|
JSON JavaScript 前端开发
什么是HTTP POST请求?初学者指南与示范
HTTP POST请求是一种常用的HTTP方法,主要用于向服务器发送数据。通过合理设置请求头和请求主体,可以实现数据的可靠传输。无论是在客户端使用JavaScript,还是在服务器端使用Node.js,理解和掌握POST请求的工作原理和应用场景,对于Web开发至关重要。
357 18
|
2月前
|
JSON 数据格式
.net HTTP请求类封装
`HttpRequestHelper` 是一个用于简化 HTTP 请求的辅助类,支持发送 GET 和 POST 请求。它使用 `HttpClient` 发起请求,并通过 `Newtonsoft.Json` 处理 JSON 数据。示例展示了如何使用该类发送请求并处理响应。注意事项包括:简单的错误处理、需安装 `Newtonsoft.Json` 依赖,以及建议重用 `HttpClient` 实例以优化性能。
89 2
|
3月前
|
开发者
HTTP 协议请求方法的发展历程
【10月更文挑战第21天】
117 45
|
2月前
|
Web App开发 大数据 应用服务中间件
什么是 HTTP Range请求(范围请求)
HTTP Range 请求是一种非常有用的 HTTP 功能,允许客户端请求资源的特定部分,从而提高传输效率和用户体验。通过合理使用 Range 请求,可以实现断点续传、视频流播放和按需加载等功能。了解并掌握 HTTP Range 请求的工作原理和应用场景,对开发高效的网络应用至关重要。
221 15
|
2月前
|
数据采集 JSON 测试技术
Grequests,非常 Nice 的 Python 异步 HTTP 请求神器
在Python开发中,处理HTTP请求至关重要。`grequests`库基于`requests`,支持异步请求,通过`gevent`实现并发,提高性能。本文介绍了`grequests`的安装、基本与高级功能,如GET/POST请求、并发控制等,并探讨其在实际项目中的应用。
79 3
|
3月前
|
缓存 前端开发 API
|
3月前
|
前端开发 UED 开发者
CSS Sprites和图标字体在网页图标加载优化中的应用。CSS Sprites通过合并多图标减少HTTP请求,提升加载速度
本文探讨了CSS Sprites和图标字体在网页图标加载优化中的应用。CSS Sprites通过合并多图标减少HTTP请求,提升加载速度;图标字体则以字体形式呈现图标,便于调整样式。文章分析了两者的优缺点及应用场景,并提供了应用技巧和注意事项,旨在帮助开发者提升页面性能,改善用户体验。
47 5