XuqmGroup-Server/im-service/src/main/java/com/xuqm/im/service/ImFeatureConfigClient.java
XuqmGroup f6c06db04b feat(deploy): 添加生产环境部署配置和联调环境切换功能
- 新增 .env.production.example 配置文件,包含所有微服务的数据库和Redis配置
- 添加 compose.production.yaml Docker Compose部署文件,定义web和各服务容器
- 实现Android SDK环境切换功能,支持外部服务和本地联调模式切换
- 添加推送注册状态管理和接收开关设置界面
- 集成演示服务的应用密钥客户端和认证服务实现
- 完善文档说明各SDK模块的集成和使用方法
2026-04-30 11:47:01 +08:00

104 行
4.0 KiB
Java

package com.xuqm.im.service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
@Component
public class ImFeatureConfigClient {
private static final Logger log = LoggerFactory.getLogger(ImFeatureConfigClient.class);
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private final RestTemplate restTemplate;
@Value("${im.tenant-service-url:http://127.0.0.1:8081}")
private String tenantServiceUrl;
@Value("${im.internal-token:xuqm-internal-token}")
private String internalToken;
public ImFeatureConfigClient() {
this.restTemplate = new RestTemplate();
}
public boolean allowStrangerMessage(String appId) {
return readConfig(appId).path("allowStrangerMessage").asBoolean(false);
}
public boolean allowFriendRequest(String appId) {
return readConfig(appId).path("allowFriendRequest").asBoolean(true);
}
public String friendRequestMode(String appId) {
JsonNode node = readConfig(appId);
String mode = node.path("friendRequestMode").asText("");
String normalized = mode == null ? "" : mode.trim().toUpperCase();
return switch (normalized) {
case "DIRECT_ACCEPT", "DISALLOW", "REQUIRE_CONFIRM" -> normalized;
default -> node.path("allowFriendRequest").asBoolean(true) ? "REQUIRE_CONFIRM" : "DISALLOW";
};
}
public boolean allowGroupJoinRequest(String appId) {
return readConfig(appId).path("allowGroupJoinRequest").asBoolean(true);
}
public boolean blacklistSendSuccess(String appId) {
return readConfig(appId).path("blacklistSendSuccess").asBoolean(true);
}
public int messageRecallMinutes(String appId) {
return Math.max(readConfig(appId).path("messageRecallMinutes").asInt(2), 0);
}
public int historyRetentionDays(String appId) {
return Math.max(readConfig(appId).path("historyRetentionDays").asInt(7), 1);
}
public int conversationPullLimit(String appId) {
return Math.min(Math.max(readConfig(appId).path("conversationPullLimit").asInt(100), 1), 500);
}
public boolean multiClientConversationDeleteSync(String appId) {
return readConfig(appId).path("multiClientConversationDeleteSync").asBoolean(false);
}
private JsonNode readConfig(String appId) {
String url = UriComponentsBuilder.fromHttpUrl(tenantServiceUrl)
.path("/api/internal/sdk/apps/{appId}/services/{platform}/{serviceType}")
.buildAndExpand(appId, "ANDROID", "IM")
.toUriString();
HttpHeaders headers = new HttpHeaders();
headers.set("X-Internal-Token", internalToken);
try {
ResponseEntity<JsonNode> response = restTemplate.exchange(
url,
HttpMethod.GET,
new HttpEntity<>(headers),
JsonNode.class
);
JsonNode body = response.getBody();
if (response.getStatusCode().is2xxSuccessful() && body != null && body.path("code").asInt() == 200) {
String config = body.path("data").path("config").asText("");
if (!config.isBlank()) {
JsonNode node = OBJECT_MAPPER.readTree(config);
return node == null ? OBJECT_MAPPER.createObjectNode() : node;
}
}
} catch (Exception e) {
log.warn("Failed to read IM feature config for appId={}: {}", appId, e.getMessage());
}
return OBJECT_MAPPER.createObjectNode();
}
}