package de.catmangames.jsonfetcher; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class JsonFetcher { private final String baseUrl; private final HttpClient client; private final ObjectMapper mapper; private final long cacheTtlMs; private final Map cacheTimestamps = new ConcurrentHashMap<>(); private final Map cacheData = new ConcurrentHashMap<>(); private JsonFetcher(Builder b) { this.baseUrl = b.baseUrl.endsWith("/") ? b.baseUrl : b.baseUrl + "/"; this.client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(b.timeoutSec)) .build(); this.mapper = new ObjectMapper(); this.cacheTtlMs = b.cacheTtlMs; } public T fetch(String path, Class type) throws IOException { return mapper.readValue(getRaw(path), type); } public T fetch(String path, TypeReference type) throws IOException { return mapper.readValue(getRaw(path), type); } private String getRaw(String path) throws IOException { if (cacheTtlMs > 0 && cacheData.containsKey(path)) { long age = System.currentTimeMillis() - cacheTimestamps.get(path)[0]; if (age < cacheTtlMs) return cacheData.get(path); } HttpRequest req = HttpRequest.newBuilder() .uri(java.net.URI.create(baseUrl + path)) .GET() .build(); try { HttpResponse res = client.send(req, HttpResponse.BodyHandlers.ofString()); if (res.statusCode() != 200) throw new IOException("HTTP " + res.statusCode() + " für: " + path); String body = res.body(); if (cacheTtlMs > 0) { cacheData.put(path, body); cacheTimestamps.put(path, new long[]{System.currentTimeMillis()}); } return body; } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IOException("Request unterbrochen", e); } } public static Builder builder(String baseUrl) { return new Builder(baseUrl); } public static class Builder { private final String baseUrl; private long timeoutSec = 5; private long cacheTtlMs = 0; public Builder(String baseUrl) { this.baseUrl = baseUrl; } public Builder timeout(long seconds) { this.timeoutSec = seconds; return this; } /** TTL in Millisekunden, 0 = Cache deaktiviert */ public Builder cache(long ttlMs) { this.cacheTtlMs = ttlMs; return this; } public JsonFetcher build() { return new JsonFetcher(this); } } }