十、HTTP 缓存——HTTP 缓存与HttpClient客户端缓存

十、HTTP 缓存——HTTP 缓存与HttpClient客户端缓存

1. HTTP 缓存简介

在日常开发中,浏览器缓存是一个非常常见但又容易被忽视的优化手段。许多开发者在面对浏览器缓存相关问题时可能会感到困惑,因此本章内容专门用来解答这些常见问题,并帮助你更好地理解如何在 Java 应用中控制浏览器缓存。

浏览器缓存是指在用户使用浏览器访问网站页面或 HTTP 服务时,根据服务器端返回的缓存控制响应头,将响应内容缓存到本地浏览器。这样,下次访问相同资源时,浏览器可以直接使用缓存内容,或者仅与服务器验证内容是否过期,从而减少网络传输的数据量,提升网站性能。

在这里插入图片描述
1.1 浏览器缓存示例

以 Chrome 浏览器为例,假设我们第一次访问 http://item.jd.com/1856588.html,将得到如下的响应头:

General
Request URL: http://item.jd.com/1856588.html
Request Method: GET
Status Code: 200 OK
Remote Address: 111.206.231.1:80

Response Headers
Age: 3
Cache-Control: max-age=60
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html; charset=gbk
Date: Tue, 16 Aug 2024 12:07:44 GMT
Expires: Tue, 16 Aug 2024 12:08:23 GMT
Last-Modified: Tue, 16 Aug 2024 12:07:25 GMT
Server: jdws
Transfer-Encoding: chunked
Vary: Accept-Encoding
Via: BJ-Y-NX-111(HIT), http/1.1 BJ-UWI-1-3CS-116

这些响应头中,Cache-ControlExpiresLast-Modified 是与缓存机制相关的关键字段。

接下来,如果我们按下 F5 刷新页面,将得到如下响应头:

General
Request URL: http://item.jd.com/1856588.html
Request Method: GET
Status Code: 304 Not Modified
Remote Address: 111.206.231.1:80

Response Headers
Cache-Control: max-age=60
Connection: keep-alive
Date: Tue, 16 Aug 2024 12:07:53 GMT
Expires: Tue, 16 Aug 2024 12:08:23 GMT
Server: jdws
Vary: Accept-Encoding
Via: http/1.1 負I-l-JCS-116

第二次请求返回的状态码是 304 Not Modified,表示服务器端的文档没有被修改,浏览器可以直接使用缓存的内容。

1.2 在 Java 应用中控制浏览器缓存

要在 Java 应用中控制浏览器缓存,可以通过设置响应头来实现。

以下是一个简单的示例,展示了如何使用 Spring Boot 控制浏览器缓存:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.time.Duration;

@RestController
@RequestMapping("/api")
public class CacheController {
   

    @GetMapping("/cache")
    public String getCacheableContent(HttpServletResponse response) {
   
        // 设置 Cache-Control 响应头
        response.setHeader("Cache-Control", "max-age=" + Duration.ofMinutes(5).getSeconds());
        // 设置 Expires 响应头
        response.setHeader("Expires", "Wed, 21 Oct 2024 07:28:00 GMT");
        // 设置 Last-Modified 响应头
        response.setHeader("Last-Modified", "Wed, 21 Oct 2024 07:00:00 GMT");
        return "This content is cacheable for 5 minutes.";
    }
}

在这个示例中,我们设置了 Cache-ControlExpiresLast-Modified 响应头,浏览器将根据这些头信息缓存内容,并在后续请求中使用缓存数据。

在这里插入图片描述

通过合理设置这些响应头,可以有效控制浏览器缓存的行为,提升系统性能并节省带宽。

2. HTTP 缓存响应标头

2.1 Last-Modified

以下是一个Spring MVC的缓存测试代码,用来演示如何使用Last-Modified头进行HTTP缓存控制。

package com.yyl.study.controller;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @author yangjian
 * @date 2024/8/17 09:17:08
 */
@RestController
@RequestMapping("/api")
public class CacheController {
   

    @RequestMapping("/cache")
    public ResponseEntity<String> cache(
            @RequestHeader(value = "If-Modified-Since", required = false) Date ifModifiedSince) throws Exception {
   

        DateFormat gmtDateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);

        // 文档最后修改时间 (去掉毫秒值)
        long lastModifiedMillis = getLastModified() / 1000 * 1000;

        // 当前系统时间 (去掉毫秒值)
        long now = System.currentTimeMillis() / 1000 * 1000;

        // 文档可以在浏览器端/proxy上缓存的时间 (单位:秒)
        long maxAge = 20;

        // 判断内容是否修改了
        if (ifModifiedSince != null && ifModifiedSince.getTime() == lastModifiedMillis) {
   
            MultiValueMap<String, String> headers = new HttpHeaders();
            headers.add("Date", gmtDateFormat.format(new Date(now)));
            headers.add("Expires", gmtDateFormat.format(new Date(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我心向阳iu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值