package com.usky.vpp.config; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.usky.common.core.exception.BusinessException; import com.usky.vpp.domain.VppRegistration; import com.usky.vpp.domain.VppTenantConfig; import com.usky.vpp.mapper.VppRegistrationMapper; import com.usky.vpp.mapper.VppTenantConfigMapper; import com.usky.vpp.util.VppAuditHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * 租户 UN 配置全局内存缓存,key=tenantId,value=VppUnProperties */ @Component public class VppUnPropertiesRegistry { private static final Logger log = LoggerFactory.getLogger(VppUnPropertiesRegistry.class); private final ConcurrentHashMap cache = new ConcurrentHashMap<>(); private final ConcurrentHashMap dnIdToTenantId = new ConcurrentHashMap<>(); @Autowired private VppTenantConfigMapper tenantConfigMapper; @Autowired private VppRegistrationMapper registrationMapper; public void refreshAll() { List configs = tenantConfigMapper.selectList(new LambdaQueryWrapper<>()); if (CollectionUtils.isEmpty(configs)) { cache.clear(); dnIdToTenantId.clear(); log.warn("vpp_tenant_config 无配置记录,UN 对接配置缓存为空"); return; } Map nextCache = new ConcurrentHashMap<>(); Map nextDnIndex = new ConcurrentHashMap<>(); for (VppTenantConfig config : configs) { if (config.getTenantId() == null) { continue; } VppUnProperties properties = toProperties(config); enrichRegistrationId(properties); nextCache.put(config.getTenantId(), properties); if (StringUtils.hasText(config.getDnId())) { nextDnIndex.put(config.getDnId(), config.getTenantId()); } } cache.clear(); cache.putAll(nextCache); dnIdToTenantId.clear(); dnIdToTenantId.putAll(nextDnIndex); log.info("已加载 {} 条租户 UN 配置至内存", cache.size()); } public VppUnProperties get(Integer tenantId) { if (tenantId == null) { return null; } return cache.get(tenantId); } public VppUnProperties require(Integer tenantId) { VppUnProperties properties = get(tenantId); if (properties == null) { throw new BusinessException("租户 " + tenantId + " 未配置运管平台 UN 对接信息"); } return properties; } public VppUnProperties getCurrent() { // 定时任务:runWithTenant 传入的 tenantId;接口调用:SecurityUtils.getTenantId() return require(VppUnTenantContext.resolveTenantId()); } public VppUnProperties getByDnId(String dnId) { if (!StringUtils.hasText(dnId)) { return null; } Integer tenantId = dnIdToTenantId.get(dnId); return tenantId != null ? get(tenantId) : null; } public Collection getAll() { return Collections.unmodifiableCollection(cache.values()); } public boolean hasCryptoEnabledTenant() { return cache.values().stream().anyMatch(this::isCryptoActive); } private boolean isCryptoActive(VppUnProperties properties) { return Boolean.TRUE.equals(properties.getCryptoEnabled()) && StringUtils.hasText(properties.getUnPublicKey()) && StringUtils.hasText(properties.getDnPrivateKey()); } public void updateRegistrationId(Integer tenantId, String registrationId) { VppUnProperties properties = get(tenantId); if (properties != null) { properties.setRegistrationId(registrationId); } } public void updateToken(Integer tenantId, String token) { VppUnProperties properties = get(tenantId); if (properties != null) { properties.setToken(token); } } private VppUnProperties toProperties(VppTenantConfig config) { VppUnProperties properties = new VppUnProperties(); properties.setTenantId(config.getTenantId()); properties.setDnId(config.getDnId()); properties.setDnName(config.getDnName()); properties.setBaseUrl(config.getBaseUrl()); properties.setTransportAddress(config.getTransportAddress()); properties.setUnPublicKey(config.getUnPublicKey()); properties.setDnPublicKey(config.getDnPublicKey()); properties.setDnPrivateKey(config.getDnPrivateKey()); properties.setToken(config.getToken()); properties.setPollIntervalSec(config.getPollIntervalSec() != null ? config.getPollIntervalSec() : 10); properties.setOutboundEnabled(config.getOutboundEnabled()); properties.setPollEnabled(config.getPollEnabled()); properties.setCryptoEnabled(config.getCryptoEnabled()); properties.setPriceDownCoeff(StringUtils.hasText(config.getPriceDownCoeff()) ? config.getPriceDownCoeff() : "0.8"); properties.setAutoAckClearing(config.getAutoAckClearing()); properties.setAutoRegisterOnStartup(config.getAutoRegisterOnStartup()); properties.setTokenTtlMinutes(25); properties.setConnectTimeoutMs(10000); properties.setReadTimeoutMs(30000); return properties; } private void enrichRegistrationId(VppUnProperties properties) { if (!StringUtils.hasText(properties.getDnId())) { return; } LambdaQueryWrapper wrapper = new LambdaQueryWrapper() .eq(VppRegistration::getDnId, properties.getDnId()) .eq(VppRegistration::getDeleteFlag, VppAuditHelper.NOT_DELETED) .orderByDesc(VppRegistration::getRegisteredAt) .last("LIMIT 1"); if (properties.getTenantId() != null) { wrapper.eq(VppRegistration::getTenantId, properties.getTenantId()); } VppRegistration registration = registrationMapper.selectOne(wrapper); if (registration != null && StringUtils.hasText(registration.getRegistrationId())) { properties.setRegistrationId(registration.getRegistrationId()); } } }