在线客服和聊天室是很多业务系统绕不开的功能,自己从零搭建一套 IM 体系成本极高,长连接维护、消息可靠性、离线消息存储每一个都是硬骨头。借助融云这类即时通讯云服务,后端只需要调用服务端接口完成用户管理和房间管理,前端的实时消息收发交给融云 IM SDK 处理,整体开发量能压缩到很小。这篇文章就以 Spring Boot 为基础,完整走一遍融云服务端 SDK 的整合过程,实现一个具备排队转接能力的客服系统和一个支持禁言的聊天室。

一、融云控制台准备与依赖引入
整合的第一步是到融云官方控制台创建一个应用,创建完成后在应用详情里能拿到 App Key 和 App Secret,这两个字段是服务端所有接口调用的凭证,建议放到配置文件中而不是硬编码。融云的服务端 SDK 提供了 Maven 坐标,直接引入即可,不需要自己封装 HTTP 请求和签名逻辑。
<dependency>
<groupId>cn.rongcloud.im</groupId>
<artifactId>server-sdk-java</artifactId>
<version>3.3.1</version>
</dependency>接着在 application.yml 里配置好密钥信息:
rongyun: app-key: 你的AppKey app-secret: 你的AppSecret
然后写一个配置类,把融云的初始化工作交给 Spring 容器管理。融云 SDK 的入口类是 RongCloud,初始化一次全局复用即可,不要每次请求都 new 一个实例,否则会造成不必要的资源浪费。
@Configuration
public class RongCloudConfig {
@Value("${rongyun.app-key}")
private String appKey;
@Value("${rongyun.app-secret}")
private String appSecret;
@Bean
public RongCloud rongCloud() throws Exception {
return RongCloud.getInstance(appKey, appSecret);
}
}这里有个容易踩的坑:App Secret 属于敏感信息,生产环境建议配合配置中心加密存储,一旦泄露别人就能以你的身份调用所有接口,包括给任意用户发消息,风险相当高。
二、用户 Token 的生成与下发
融云的安全模型是每个终端用户必须持有一个 Token 才能连接 IM 服务器,而这个 Token 只能由服务端生成。也就是说,客户端登录你的业务系统后,后端要调融云的接口换取 Token 再返回给前端,前端拿到 Token 后初始化融云 IM SDK 完成连接。这就是典型的服务端主导的鉴权模式。
@Service
public class RongUserService {
@Autowired
private RongCloud rongCloud;
/**
* 为业务用户生成融云 Token
*/
public String getToken(String userId, String nickname, String avatar) throws Exception {
UserModel user = new UserModel()
.setId(userId)
.setName(nickname)
.setPortrait(avatar);
TokenResult result = rongCloud.user.register(user);
if (result.getCode() != 200) {
throw new BusinessException("获取融云Token失败: " + result.getMsg());
}
return result.getToken();
}
}在 Controller 层提供一个登录后获取 Token 的接口,前端每次建立长连接前调用一次。需要注意的是融云对同一用户重复注册会直接返回已有 Token,不会报错,所以不需要自己维护去重逻辑。另外 Token 有效期较长,可以考虑缓存到 Redis 里,减少对融云接口的调用频次,毕竟融云对接口有频率限制,超出会被限流。
用户的昵称和头像变更后,同样要调用 user.update 接口同步到融云,否则聊天窗口里显示的还是旧资料。这个同步动作建议放在用户资料修改的业务事务提交之后执行,用事件监听的方式触发,避免和主业务耦合太深。
三、客服会话的设计与实现
客服系统的核心流程是:客户发起会话、进入排队、分配客服、双向聊天、会话结束。融云提供了客服业务的服务端能力,也可以自己基于一对一聊天实现一套简单的分配逻辑。下面以自研分配为例讲解思路。
首先定义一张会话表,记录会话状态、客户 ID、客服 ID、开始和结束时间。客户点击联系客服时,后端先查当前在线且空闲的客服,有则直接建立会话,没有则把客户塞进 Redis 的排队队列。
@Service
public class CustomerServiceManager {
@Autowired
private StringRedisTemplate redisTemplate;
private static final String WAIT_QUEUE = "cs:wait:queue";
/**
* 客户申请会话,返回分配的客服ID或排队位置
*/
public Map<String, Object> applySession(String customerId) {
String staffId = findIdleStaff();
Map<String, Object> result = new HashMap<>();
if (staffId != null) {
createSession(customerId, staffId);
result.put("status", "connected");
result.put("staffId", staffId);
} else {
redisTemplate.opsForList().rightPush(WAIT_QUEUE, customerId);
Long position = redisTemplate.opsForList().size(WAIT_QUEUE);
result.put("status", "queuing");
result.put("position", position);
}
return result;
}
private String findIdleStaff() {
// 从在线客服集合中找出当前会话数未达上限的一位
// 具体实现依赖客服上线时注册的状态信息
return null;
}
private void createSession(String customerId, String staffId) {
// 写入会话表,并通过融云下发系统消息通知双方
}
}客服关闭一个会话后,触发排队队列的消费:从队列头部取出下一个客户,直接分配给刚释放的客服,并分别给客户和客服推送一条系统通知消息。融云的服务端消息接口支持以系统身份向指定用户下发消息,前端收到后弹窗提醒即可。
会话转接也很常见,比如客户问题比较专业,一线客服需要把会话转给二线专家。实现上就是结束当前会话记录、创建新会话,然后调用融云接口分别通知三方,聊天记录可以通过融云的历史消息云存储功能查询,也可以自己落库一份便于后续质检和统计。
四、聊天室的创建与管理
聊天室和一对一聊天的区别在于消息是广播式的,所有在室内的用户都能收到。融云的聊天室只能由服务端创建,客户端拿到聊天室 ID 后调用加入接口即可收发消息,这个设计天然适合做直播间、活动互动这类场景。
@Service
public class ChatroomService {
@Autowired
private RongCloud rongCloud;
/**
* 创建聊天室
*/
public String createChatroom(String chatroomId, String chatroomName) throws Exception {
ChatroomModel chatroom = new ChatroomModel()
.setId(chatroomId)
.setName(chatroomName);
Result result = rongCloud.chatroom.create(new ChatroomModel[]{chatroom});
if (result.getCode() != 200) {
throw new BusinessException("创建聊天室失败: " + result.getMsg());
}
return chatroomId;
}
/**
* 加入聊天室(销毁型,退出后自动移除成员记录)
*/
public Result joinChatroom(String chatroomId, String userId) throws Exception {
ChatroomMember member = new ChatroomMember()
.setId(chatroomId)
.setMembers(new String[]{userId});
return rongCloud.chatroom.member.join(member, "1");
}
/**
* 全员禁言某个用户
*/
public Result addGagUser(String chatroomId, String userId, long minutes) throws Exception {
return rongCloud.chatroom.gag.add(chatroomId, userId, minutes);
}
}管理层面常用的还有禁言、封禁、销毁聊天室三个能力。禁言适合处理刷屏用户,传一个分钟数即可自动解禁;封禁针对严重违规的用户,可以直接禁止其加入任何聊天室;销毁聊天室则用于活动结束后释放资源,融云对聊天室总量有限制,用完及时清理是良好习惯。
聊天室的消息审核也不可忽视。可以在前端发送消息时由融云侧做内容过滤,也可以在服务端通过消息回调机制拦截:融云支持配置消息发送前的回调地址,Spring Boot 这边提供一个接口接收回调,校验内容合规后返回放行标记,不合规则拒绝发送。这套回调机制同样适用于客服场景里的敏感词过滤。
@RestController
@RequestMapping("/callback/rongyun")
public class MessageCallbackController {
/**
* 融云消息发送前回调,返回 0 表示拒绝发送
*/
@PostMapping("/message/beforeSend")
public Map<String, Object> beforeSendMessage(@RequestBody Map<String, Object> body) {
Map<String, Object> result = new HashMap<>();
String content = String.valueOf(body.getOrDefault("content", ""));
if (containsSensitiveWord(content)) {
result.put("result", 0);
result.put("message", "消息包含敏感内容,已被拦截");
} else {
result.put("result", 1);
}
return result;
}
private boolean containsSensitiveWord(String content) {
// 接入敏感词库进行匹配,这里省略实现
return false;
}
}五、上线前的注意事项
接口频率限制是最容易在生产环境暴露的问题,融云免费版对每秒调用次数有严格上限,Token 获取、消息下发都要做好缓存和合并,比如批量系统通知可以用融云的广播消息接口一次下发,避免循环单发。
其次是断线重连。前端 SDK 自带重连机制,但业务层要处理好重连后的状态恢复,例如聊天室重连后需要重新拉取成员数,客服会话要确认对方是否还在线,这些状态同步逻辑建议全部由后端接口提供,前端只做展示。
最后是监控与日志。融云接口调用的返回码要认真记录,200 之外的都要告警排查。上线前建议把整个链路在测试环境压一遍,特别是排队高峰期的分配逻辑和聊天室万人加入的场景,提前发现性能瓶颈远比线上救火划算。
Spring Boot融云SDK客服系统修改时间:2026-09-15 18:58:47