javascript
Spring mvc HTTP协议之缓存机制
概述
Spring MVC 支持HTTP協(xié)議的 Last-Modified 緩存機(jī)制。
1. 在客戶端地一次輸入URL時,服務(wù)器端會返回內(nèi)容和狀態(tài)碼200, 表示請求成功,同時會添加一個“Last-Modified”屬性,表示該請求資源的最后修改時間
2. 客戶端第二次請求此URL時,客戶端會向服務(wù)器發(fā)送請求頭 “IF-Modified-Since”,如果服務(wù)端內(nèi)容沒有變化,則自動返回HTTP304狀態(tài)碼(只返回相應(yīng)頭信息,不返回資源文件內(nèi)容,這樣就可以節(jié)省網(wǎng)絡(luò)帶寬,提供響應(yīng)速度和用戶體驗)
Spring MVC 中實現(xiàn)示例
UserCacheController.java
@Controller public class UserCacheController extends AbstractController implements LastModified{private long lastModified = System.currentTimeMillis();protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)throws Exception {List<User> userList = new ArrayList<User>();userList.add(new User("zhangsan", 18));userList.add(new User("wangwu", 16));System.out.println("執(zhí)行一次,我有緩存");return new ModelAndView("userList", "users", userList);}@Overridepublic long getLastModified(HttpServletRequest request) {//時間戳邏輯,返回最后修改時間,例如if (lastModified == 0L) {lastModified = System.currentTimeMillis();}System.out.println("時間戳:"+lastModified);return lastModified;} }Spring MVC 提供的Last-Modified機(jī)制的支持,只需要實現(xiàn)LastModified接口,并實現(xiàn)GetLastModified() 方法,每次修改資源的時候,更新下lastModified的值即可。
userList.jsp
<%@page import="java.util.List"%> <%@page import="cn.com.infcn.bean.User"%> <%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Insert title here</title> </head> <body><%List<User> userList = (List<User>) request.getAttribute("users");for (User user : userList) {%>用戶名:<%=user.getUserName()%><br /> 年齡:<%=user.getAge()%><br /><hr><%}%> </body> </html>訪問效果
只有第一次執(zhí)行了Controller,以后訪問都沒執(zhí)行Controller。
原理分析
DispatcherServlet.doDispatch()
1. 首先獲取 http 請求的method type。
2. 如果method 是 “GET”或“HEAD” 才支持緩存機(jī)制
3. 通過 HandlerAdapter.getLastModified() 方法獲取 UserCacheController 中的lastModified 的值,最后修改時間。
4. 調(diào)用 checkNotModified() 方法驗證 http 請求頭中的“If-Modified-Since”的時間進(jìn)行對比,判斷頁面是否更新過。如果有更新才執(zhí)行具體的Controller, 沒有更新則響應(yīng) 304 狀態(tài)碼信息(HTTP 304: Not Modified )。
getLastModified()
通過handler的適配器類,然后在調(diào)用UserCacheController.getLastModified() 方法獲取最后更新時間。
checkNotModified()
1. 調(diào)用 validateIfModifiedSince() 方法獲取http請求頭中的“If-Modified-Since”值,并驗證是否修改過。
沒有修改過則設(shè)置notModified=true,如果修改過則設(shè)置notModified=false。
2. 如果 notModified=true,則設(shè)置response響應(yīng)狀態(tài)碼304或412
3. 如果是GET 或 HEAD 請求則添加響應(yīng)頭“Last-Modified”
validateIfModifiedSince()
1. 解析http 請求頭中的“If-Modified-Since”值
2. 判斷緩存頁面是否需要更新。
注:(lastModifiedTimestamp / 1000 * 1000):因為http頭中只保存到秒,所以這里把秒后面的置為0。
HTTP 請求響應(yīng)頭分析
通過瀏覽器F12 可以看出:
1. 每次請求都會攜帶“If-Modified-Since”信息到服務(wù)器驗證資源是否需要更新。
2. 服務(wù)器響應(yīng)頭中會包含“Last-Modified”信息,訪問資源最后修改的日期。
緩存限制條件
并不是所有MappingHandler 方式都支持緩存。
比如:DefaultAnnotationHandlerMapping 就不支持緩存機(jī)制。
因為支持注解的Controller中可以有多個請求方法,而每個方法都需要計算文件的最后修改時間,這樣LastModified就不適用了。只適用一個Controller中只支持一個請求的HandlerMapping。
AnnotationMethodHandlerAdapter
從代碼中可以看出,這個方法永遠(yuǎn)返回-1。
想了解更多精彩內(nèi)容請關(guān)注我的公眾號
本人簡書blog地址:http://www.jianshu.com/u/1f0067e24ff8????
點擊這里快速進(jìn)入簡書
GIT地址:http://git.oschina.net/brucekankan/
點擊這里快速進(jìn)入GIT
總結(jié)
以上是生活随笔為你收集整理的Spring mvc HTTP协议之缓存机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring mvc ViewResol
- 下一篇: Spring 多线程下注入bean问题