← Назад к вопросам
Как ресурс проверяет новую версию копии данных
2.0 Middle🔥 131 комментариев
#Многопоточность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Проверка версии кэшированных данных в HTTP
Ресурс проверяет новую версию копии данных через механизм валидации кэша, который работает на основе HTTP заголовков ETag и условных запросов.
Основные механизмы валидации
1. ETag (Entity Tag) Это уникальный идентификатор версии ресурса:
// Сервер отправляет:
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
// Клиент сохраняет и отправляет обратно:
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Если версия совпадает — сервер возвращает 304 Not Modified, данные не передаются.
2. Last-Modified / If-Modified-Since Проверка по временной метке:
// Сервер отправляет:
Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT
// Клиент проверяет:
If-Modified-Since: Wed, 21 Oct 2025 07:28:00 GMT
Если данные не изменены — 304 Not Modified.
Практическая реализация на Java
Серверная часть (Spring)
@GetMapping("/api/users/{id}")
public ResponseEntity<User> getUser(@PathVariable String id,
@RequestHeader(value = "If-None-Match", required = false) String ifNoneMatch) {
User user = userService.findById(id);
String etag = "\"" + Integer.toHexString(user.hashCode()) + "\"";
if (ifNoneMatch != null && ifNoneMatch.equals(etag)) {
return ResponseEntity.status(HttpStatus.NOT_MODIFIED).build();
}
return ResponseEntity.ok()
.header("ETag", etag)
.header("Cache-Control", "max-age=3600")
.body(user);
}
Клиентская часть
private Map<String, CacheEntry> cache = new HashMap<>();
public User getUser(String id) throws IOException {
CacheEntry cached = cache.get(id);
HttpRequest.Builder builder = HttpRequest.newBuilder()
.uri(URI.create("http://api.example.com/users/" + id));
if (cached != null) {
builder.header("If-None-Match", cached.etag);
}
HttpRequest request = builder.GET().build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 304) {
return cached.data;
}
User user = new ObjectMapper().readValue(response.body(), User.class);
String etag = response.headers().firstValue("ETag").orElse("");
cache.put(id, new CacheEntry(user, etag));
return user;
}
Как это работает
- Первый запрос: клиент запрашивает ресурс, сервер возвращает
200 OKс данными иETag - Кэширование: клиент сохраняет данные и ETag
- Следующий запрос: клиент отправляет условный запрос с
If-None-Match - Проверка на сервере: если версия совпадает →
304 Not Modified - Обновление: если данные изменились →
200 OKс новыми данными и новым ETag
Преимущества
- Экономия трафика — при 304 тело ответа не передаётся
- Точность — ETag отражает содержимое, не привязана к времени
- Надёжность — работает через кэширующие прокси
- Встроенная конкурентность — используется в REST API
Это стандартная практика в REST API и веб-сервисах.