一、問題描述
今日遇到了一個問題,要去獲取HTTP報文在請求和響應(yīng)的時間,因為沒有原生的API可以調(diào)用,所以需要一定的技巧~
- 下面主體的框架和代碼,我使用了form表單去構(gòu)造一個POST請求,然后在Servlet中重寫doPost()方法,然后實現(xiàn)獲取請求時間和響應(yīng)時間的代碼邏輯
<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 {
//...
}
}
二、抓包觀察
我們可以先去觀察一下在發(fā)起POST請求后這個HTTP請求報文中是否在這個請求時間,如果有的其實可以把它通過一定手段獲取到
- 但遺憾的是,我并沒有發(fā)現(xiàn)任何與時間相關(guān)的東西??
- 那再到請求報文中去看看的話,就發(fā)現(xiàn)了與時間相關(guān)的內(nèi)容,不過對照現(xiàn)在的時間仔細一看的話,卻查了不少,網(wǎng)上一搜就發(fā)現(xiàn)GMT是格林尼治時間,要比現(xiàn)在的時候早上8個小時,但看到一個時間卻非常激動,想著如何拿到它
三、查找文檔
因為【HttpServletRequest】和【HttpServletResponse】給我們提供了許多原生API,所以我們可以去找找看有哪些API是我們可以用得上的,這里推薦直接進官網(wǎng) ——> 鏈接
- 可以看到,無論是前者還是后者都未我們提供了很多的方法,這也我也會在代碼中使用幾個,不過找了一圈我發(fā)現(xiàn)完全沒有獲取時間的那種API,于是就沒有再查找下去了
四、思考嘗試
再找了很久還是一無所獲,干脆就想著自己去手動獲取一下這個時間
- 此時我就想到了Java里面的Date類,可以獲取當(dāng)前系統(tǒng)的時間,以及隨之對應(yīng)的是格式化解析
SimpleDateFormat()
,于是便立馬寫下了這幾句代碼
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEEE");//格式化日期
Date currentTime = new Date();//獲取當(dāng)前時間
String date = formatter.format(currentTime).toString();
?? 但是要怎么使用這個當(dāng)前時間呢?去獲取哪段時間呢?
-
首先我就提出了上面這個問題,思考了一下從Tomcat解析HTTP請求到將其交給Servlet做處理,那么能夠最早獲取到時間的地方就是一開始進入
doPost()
的時候,我們記錄下當(dāng)前的時間,就可以將其近似于HTTP的請求時間
?? 請求時間有了,那響應(yīng)時間呢?也用這個去求嗎?
-
這個的話不一定,因為剛才我們看了HTTP的響應(yīng)報文,也就是服務(wù)端在處理完數(shù)據(jù)后給瀏覽器返回的一個響應(yīng),里面是存在【Date】這個時間的,你可以選擇使用
getHeaderNames()
先獲取到整個報文的頭部,因為他的返回值是一個Collection集合,所以你可以通過遍歷集合的方式與getHeader()
相配合格式化地輸出里面的內(nèi)容,這里我就不細說了 -
也是一樣,我們可以通過上面這種方式去獲取響應(yīng)時間,何時獲取才是最正確的呢?那就是在
resp.getWriter().write()
這個發(fā)還響應(yīng)之前去獲取時間,這是最后的機會了!
五、精益求精
通過返回我們在后端代碼中獲取到的時間,將其返還給瀏覽器時便看到這個【請求時間】和【響應(yīng)時間】是一樣的,這是為什么呢?
- 仔細觀察我設(shè)置的日期格式化,是精確到秒的,如果你有一點計算機常識的話就可以知道計算機的運行速度是很快的,基本是以納秒為單位,此時我們?nèi)羰侵痪_到秒 的話可能還看不太出來,應(yīng)該再多精確幾位
yyyy-MM-dd HH:mm:ss
- 可以看到,此時我精確到了納秒的級別,此時再去觀察的話就會有所不同
yyyy-MM-dd HH:mm:ss.SSSSSSSSS
- 可以看到雖然精確了很多位數(shù),但是二者之間的差距還是很小,畢竟計算機的處理速度也是非??斓?/li>
但是這么去做的只是鉆了一個牛角尖??,后面我又想到了一個更聰明的辦法
- 那就是讓程序等待一段時間!
try {
Thread.sleep(500); //讓程序暫停0.5s
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
- 學(xué)習(xí)過Java多線程的同學(xué)一定馬上就能反應(yīng)過來了,可以使用Thread類中的
sleep()
方法讓程序睡上幾秒,然后再去獲取時間。此時我們再去觀察【請求時間】和【響應(yīng)時間】的話就會有些差距了。如果你想讓差距更加明顯的話可以讓程序多睡一會
六、源碼解說
這里的話附上我們解決本體所用的源碼
前端:
<!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();//獲取當(dāng)前時間
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()方法快結(jié)束時獲取一下響應(yīng)時間
currentTime = new Date();//獲取當(dāng)前時間
String date2 = formatter.format(currentTime).toString();
stringBuilder.append("響應(yīng)時間 = " + date2);
stringBuilder.append("<br>");
stringBuilder.append("響應(yīng)狀態(tài)碼 = " + resp.getStatus());
stringBuilder.append("<br>");
resp.getWriter().write(stringBuilder.toString());
}
}
?? 稍微來講一下后端的這塊邏輯
- 這邊我主要使用到的就是這個【StringBuilder】類,使用它構(gòu)造出來的對象,我們需要在單線程的環(huán)境下連接多個字符串,此時用它最合適了,通過里面的
append()
方法去進行連接,這里我測試了Reques和Response兩個類中的方法,打印出了HTTP報文的一些內(nèi)容 - 還要注意,有些同學(xué)在看我這句代碼的時候很疑惑,所我怎么把前端的代碼寫到后端來了
stringBuilder.append("<br>");
- 這里主要就是依賴于前面的這句代碼,我將當(dāng)前body中的數(shù)據(jù)格式設(shè)置為了HTML,代表可以識別HTML代碼,所以這個
<br>
就會被當(dāng)做換行了,若是不寫這個的話所有的內(nèi)容都會擠在一起的
resp.setContentType("text/html;charset=utf-8");
- 最后的這句話就是將拼接的StringBuilder類型字符串轉(zhuǎn)換為String類型并發(fā)還給瀏覽器一個響應(yīng),將拼接的內(nèi)容都打印展示出來
resp.getWriter().write(stringBuilder.toString());
2023年5月22日記文章來源:http://www.zghlxwxcb.cn/news/detail-482577.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-482577.html
到了這里,關(guān)于如何獲取HTTP請求時間與響應(yīng)時間【附源碼】的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!