package com.fujica.parkingtool.oss; import java.util.Objects; import java.util.prefs.Preferences; /** * 阿里云 OSS 配置。 * *

4 项核心字段:address / accessKey / secretKey / bucket。 * 全部不为空且 address 是合法主机时被视作"有效配置",否则 {@link #isUsable()} 返回 false, * 用于让上层选择"不传图片"。

* *

address 不需要带协议前缀;不含 bucket 子域名(即只是 OSS endpoint, * 例如 oss-cn-hangzhou.aliyuncs.com)。 * 上传时会自动拼成 https://{bucket}.{address}/{key}

* *

配置持久化在用户 Preferences 节点 /com/fujica/parkingtool/oss 下。

*/ public final class OssSettings { private static final String PREF_ROOT = "/com/fujica/parkingtool/oss"; private static final String KEY_ADDRESS = "address"; private static final String KEY_ACCESS_KEY = "accessKey"; private static final String KEY_SECRET_KEY = "secretKey"; private static final String KEY_BUCKET = "bucket"; private static final String KEY_PATH_PREFIX= "pathPrefix"; /** OSS endpoint,不带 https://,不带 bucket 子域名 */ private String address = ""; private String accessKey = ""; private String secretKey = ""; private String bucket = ""; /** 上传路径前缀,默认 parking-simulator */ private String pathPrefix = "parking-simulator"; public OssSettings() { } public String getAddress() { return address; } public void setAddress(String address) { this.address = address == null ? "" : address.trim(); } public String getAccessKey() { return accessKey; } public void setAccessKey(String accessKey) { this.accessKey = accessKey == null ? "" : accessKey.trim(); } public String getSecretKey() { return secretKey; } public void setSecretKey(String secretKey) { this.secretKey = secretKey == null ? "" : secretKey; } public String getBucket() { return bucket; } public void setBucket(String bucket) { this.bucket = bucket == null ? "" : bucket.trim(); } public String getPathPrefix() { return pathPrefix; } public void setPathPrefix(String pathPrefix) { if (pathPrefix == null) { this.pathPrefix = ""; return; } String p = pathPrefix.trim(); // 去除首尾的多余斜杠 while (p.startsWith("/")) p = p.substring(1); while (p.endsWith("/")) p = p.substring(0, p.length() - 1); this.pathPrefix = p; } /** 4 项核心字段全部非空,且 address 形如 host[:port] 才算有效。 */ public boolean isUsable() { if (isBlank(address) || isBlank(accessKey) || isBlank(secretKey) || isBlank(bucket)) { return false; } String cleaned = cleanAddress(address); // 简单校验:不能是带协议的 URL;必须包含一个点 return !cleaned.contains("://") && cleaned.contains("."); } /** 去除可能错误粘进来的协议前缀和尾部斜杠,返回纯 host[:port] */ public static String cleanAddress(String raw) { if (raw == null) return ""; String s = raw.trim(); if (s.startsWith("https://")) s = s.substring(8); if (s.startsWith("http://")) s = s.substring(7); while (s.endsWith("/")) s = s.substring(0, s.length() - 1); return s; } /** 拼装最终公网 URL(https):{bucket}.{address}/{key} */ public String publicUrl(String key) { String addr = cleanAddress(address); String k = key == null ? "" : (key.startsWith("/") ? key.substring(1) : key); return "https://" + bucket + "." + addr + "/" + k; } private static boolean isBlank(String s) { return s == null || s.trim().isEmpty(); } public static OssSettings load() { OssSettings s = new OssSettings(); Preferences p = node(); s.address = p.get(KEY_ADDRESS, s.address); s.accessKey = p.get(KEY_ACCESS_KEY, s.accessKey); s.secretKey = p.get(KEY_SECRET_KEY, s.secretKey); s.bucket = p.get(KEY_BUCKET, s.bucket); s.pathPrefix = p.get(KEY_PATH_PREFIX,s.pathPrefix); return s; } public void save() { Preferences p = node(); p.put(KEY_ADDRESS, address); p.put(KEY_ACCESS_KEY, accessKey); p.put(KEY_SECRET_KEY, secretKey); p.put(KEY_BUCKET, bucket); p.put(KEY_PATH_PREFIX,pathPrefix); } public OssSettings copy() { OssSettings s = new OssSettings(); s.address = address; s.accessKey = accessKey; s.secretKey = secretKey; s.bucket = bucket; s.pathPrefix = pathPrefix; return s; } private static Preferences node() { return Preferences.userRoot().node(PREF_ROOT); } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof OssSettings that)) return false; return Objects.equals(address, that.address) && Objects.equals(accessKey, that.accessKey) && Objects.equals(secretKey, that.secretKey) && Objects.equals(bucket, that.bucket) && Objects.equals(pathPrefix, that.pathPrefix); } @Override public int hashCode() { return Objects.hash(address, accessKey, secretKey, bucket, pathPrefix); } }