Initialize project with JsonFetcher implementation, Gradle setup, and IntelliJ configuration.

This commit is contained in:
2026-04-23 05:20:41 +02:00
commit 00b3dbda8c
16 changed files with 579 additions and 0 deletions
@@ -0,0 +1,97 @@
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<String, long[]> cacheTimestamps = new ConcurrentHashMap<>();
private final Map<String, String> 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> T fetch(String path, Class<T> type) throws IOException {
return mapper.readValue(getRaw(path), type);
}
public <T> T fetch(String path, TypeReference<T> 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<String> 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);
}
}
}