Files
UserBaseService/src/main/java/com/yunhai/userbase/service/impl/EnvConfigService.java
T
chenxing 71adaf6acb
ci-userbase-service / build-and-push (push) Successful in 2m47s
健康检查功能添加
2026-09-01 11:50:49 +08:00

93 lines
3.8 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.yunhai.userbase.service.impl;
import com.alibaba.cloud.nacos.NacosConfigManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 前端运行时配置读取(方案:Projman/前端动态配置方案-env-config接入落地.md)。
* <p>
* projman 配置管理中的 env-config-{前端目标名}.json 会双写到 Nacos
* (dataId = front-{应用名}-{目标名},group = FRONT_GROUP,type = json),
* 本服务按前端目标名读取并原样返回 JSON 串,经 {@code GET /api/env-config?front=xxx} 提供给前端 SPA,
* 替代构建期写死的 VITE_* 环境变量与 config/index.js 静态文件。
* <p>
* 容错口径:读不到(本地未开 Nacos / dataId 不存在 / 超时)一律返回 {@code "{}"},
* 前端拿空对象后走 import.meta.env 构建期兜底,不影响启动。
*/
@Service
public class EnvConfigService {
private static final Logger log = LoggerFactory.getLogger(EnvConfigService.class);
/** 前端目标名白名单:projman 前端目标创建时即限制为简单标识符,此处同口径校验,防 dataId 拼接注入 */
private static final String FRONT_NAME_PATTERN = "^[A-Za-z0-9_-]{1,64}$";
/** Nacos dataId 前缀:front-{应用名}-,与 projman AppConfigFileService 双写规则一致 */
@Value("${yh.env-config.data-id-prefix:front-userbase-}")
private String dataIdPrefix;
/** Nacos group,与 projman 双写侧 FRONT_GROUP 常量一致 */
@Value("${yh.env-config.group:FRONT_GROUP}")
private String group;
/** 结果缓存 TTL:前端 SPA 每次打开页面都会拉一次,缓存削峰避免轮询打穿 Nacos */
private static final long CACHE_TTL_MS = 30_000L;
private final Map<String, CacheEntry> cache = new ConcurrentHashMap<>();
private static class CacheEntry {
final String content;
final long ts;
CacheEntry(String content, long ts) {
this.content = content;
this.ts = ts;
}
}
/** 本地 profile 未启用 Nacos 时为 null(NACOS_CONFIG_ENABLED=false 时不注册该 bean) */
@Autowired(required = false)
private NacosConfigManager nacosConfigManager;
/** 读取前端目标配置 JSON;任何失败返回 "{}"(前端走构建期兜底) */
public String get(String front) {
if (front == null || !front.trim().matches(FRONT_NAME_PATTERN)) {
return "{}";
}
String key = front.trim();
CacheEntry cached = cache.get(key);
long now = System.currentTimeMillis();
if (cached != null && now - cached.ts < CACHE_TTL_MS) {
return cached.content;
}
String content = readFromNacos(key);
cache.put(key, new CacheEntry(content, now));
return content;
}
private String readFromNacos(String front) {
if (nacosConfigManager == null) {
// 本地开发未接 Nacos:无运行时配置,前端走 import.meta.env 兜底
return "{}";
}
try {
String content = nacosConfigManager.getConfigService()
.getConfig(dataIdPrefix + front, group, 3000);
if (content == null || content.trim().isEmpty()) {
return "{}";
}
return content.trim();
} catch (Exception e) {
// Nacos 不可达时 getConfig 自身有本地快照兜底;仍失败则返回空对象,不抛错不影响前端启动
log.warn("[env-config] 读取 Nacos 配置失败 dataId={} group={}: {}", dataIdPrefix + front, group, e.getMessage());
return "{}";
}
}
}