官方提供的服务器端代码是用nodejs写的(地址https://github.com/sealtalk/sealtalk-server),我需要改成用spring-boot实现。

也是费了好大的功夫。

    源码我分享到https://gitee.com/why_su/erongcloud 了,可以参考下,改了一些东西,例如我觉得userId命名不规范,改成了userAccount。

    最近才发现融云官方提供了java demo,地址是https://github.com/rongcloud/server-sdk-java ,我弄的时候还没有来着。

    融云【单聊】的机制在于,只要知道 两个人的 id,就能互相发送消息,不管是不是好友,所以就需要 我们自己写的后台 来 限制下:不是好友就不能互相聊天。 

注意:如果用户 A  把 B 给删了,但在B 的app上还有对话窗口存在的话,此时按照融云的机制, B 还是可以和 A聊天的,这个时候 就需要使用【融云API】把 B 添加到 A 的【黑名单】里面,这样二者就无法通信了。

这里得废话一句:进入融云后台,右上角找到【我的控制台】点击进去

java 集群应用_群组

,左下角找到【API调用】

java 集群应用_java 集群应用_02

,先再这里面调试程序,能起到事半功倍的效果!!

一、数据库表e_rong_cloud_friendship

-- 创建融云-好友关联关系表
CREATE TABLE `e_rong_cloud_friendship` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
    `user_account` varchar(25) NOT NULL COMMENT '当前用户账号',
    `friend_account` varchar(25) NOT NULL COMMENT '好友账号',
    `display_name` varchar(32) DEFAULT '' COMMENT 'user对friend设置的备注名',
    `message` varchar(64) COMMENT 'user添加friend为好友时的请求信息',
    `status` int(10) unsigned COMMENT '10: 请求, 11: 被请求, 20: 同意, 21: 忽略, 30: 被删除',
    `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP  COMMENT '创建时间',
    `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP  COMMENT '更新时间',
    PRIMARY KEY (`id`),
    UNIQUE KEY `friendship_account` (`user_account`,`friend_account`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

二、status定义

好友之间的关系

status值

字段

说明

10

REQUESTING

请求

11

REQUESTED

被请求

20

AGREED

同意

21

IGNORED

忽略

30

DELETED

被删除

从以下这张截图可以看出:目前数据库一共有维护着4个人的关联关系:

其中 156*** 已接受 187*** 的好友请求, 187***也已接受156***的请求,所以现在156***和187***已经是好友了。

180*** 正在请求 添加184*** 为好友, 184*** 收到了 180*** 发来的添加好友申请,并且看到好友申请消息是【我是xxx】

java 集群应用_java 集群应用_03

三、返回格式定义:

public class Response<T> {
    /***响应码**/
    private Integer code;
    /**消息**/
    private String msg;
    /**消息体**/
    private T result;
     
    /**此处是getter和setter*/
}

引入maven:

<dependency>
    <groupId>cn.rongcloud.im</groupId>
    <artifactId>server-sdk-java</artifactId>
    <version>3.0.1</version>
</dependency>

四、自定义参数,放在了application.yml中

# 自定义参数
erongcloud:
  # 融云appKey
  appKey:
  # 融云appSecret
  appSecret:
  # 文件上传根目录
  fileRoot:
  # 用户默认头像
  defaultImage: 
  # 群组默认头像
  defaultGroupImage:

因为需要使用static,所以使用set的方式注入:

@Component
public class ConfigConstant {
    /**
     * 融云应用AppKey
     */
    public static String appKey;

    @Value("${erongcloud.appSecret}")
    public void setAppSecret(String APP_SECRET) {
        appSecret = APP_SECRET;
    }

    /**
     * 融云应用AppSecret
     */
    public static String appSecret;

    /**
     * 融云申请的key
     */
    @Value("${erongcloud.appKey}")
    public void setAppKey(String APP_KEY) {
        appKey = APP_KEY;
    }

    /**
     * 默认空头像URL(用户)
     */
    public static String defaultImage;

    @Value("${erongcloud.defaultImage}")
    public void setDefaultImage(String DEFAULT_IMAGE) {
        defaultImage = DEFAULT_IMAGE;
    }

    /**
     * 默认空头像URL(群组)
     */
    public static String defaultGroupImage;

    @Value("${erongcloud.defaultGroupImage}")
    public void setDefaultGroupImage(String DEFAULT_GROUP_IMAGE) {
        defaultGroupImage = DEFAULT_GROUP_IMAGE;
    }
}

常量类:

public class RongCloudConstant {

    /**10: 请求*/
    public static final int REQUESTING = 10;
     /**11: 被请求*/
    public static final int REQUESTED = 11;
     /**20: 同意*/
    public static final int AGREED = 20;
     /**21: 忽略*/
    public static final int IGNORED = 21;
     /**30: 被删除*/
    public static final int DELETED = 30;
     /**同意请求*/
    public static final String CONTACT_OPERATION_ACCEPT_RESPONSE = "AcceptResponse";
     /**请求*/
    public static final String CONTACT_OPERATION_REQUEST = "Request";

    /**
     * 响应码
     */
    public static final class Code {
        /**
         * 成功
         */
        public static final int SUCCESS = 200;
    }

    /**
     * 群组相关
     */
    public static final class Groups {
        /**最大成员数*/
        public static final int MAX_MEMBER_COUNT = 500;

        public static final String GROUP_OPERATION_CREATE = "Create";

        public static final String GROUP_OPERATION_ADD = "Add";

        public static final String GROUP_OPERATION_QUIT = "Quit";

        public static final String GROUP_OPERATION_DISMISS = "Dismiss";

        public static final String GROUP_OPERATION_KICKED = "Kicked";

        public static final String GROUP_OPERATION_RENAME = "Rename";

        public static final String GROUP_OPERATION_BULLETIN = "Bulletin";

        public static final String GROUP_OPERATION_TRANSFER = "Transfer";

        /**
         * 角色
         */
        public static final class Role {
            /**
             * 群主
             */
            public static final int OWNER = 0;
            /**
             * 普通成员
             */
            public static final int NORMAL = 1;
        }
    }

}

五、发送融云系统消息,单聊消息(这里主要是小灰条),封装成工具类

public class RongCloudUtil {

    private static RongCloud rongCloud = RongCloud.getInstance(ConfigConstant.appKey, ConfigConstant.appSecret);

    /**
     * 通过融云发送系统信息,详见https://www.rongcloud.cn/docs/message_architecture.html#group_notification_message
     * @param senderId 发送人
     * @param targetIds 接收人(数组)
     * @param baseMessage 消息内容
     * @param pushContent 推送内容
     * @param pushData 推送数据
     */
    public static void sendSystemMessage(String senderId, String[] targetIds, BaseMessage baseMessage, String pushContent, String pushData){
        SystemMessage systemMessage = new SystemMessage()
                .setSenderId(senderId)
                .setTargetId(targetIds)
                .setObjectName(baseMessage.getType())
                .setContent(baseMessage)
                .setPushContent(pushContent)
                .setPushData(pushData)
                .setIsPersisted(0)
                .setIsCounted(0)
                .setContentAvailable(0);
        try {
            rongCloud.message.system.send(systemMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 通过融云发送单聊消息
     */
    public static void sendPrivateMsg(String senderId, String targetId, BaseMessage baseMessage){
        PrivateMessage privateMessage = new PrivateMessage()
                .setSenderId(senderId)
                .setTargetId(new String[]{targetId})
                .setObjectName(baseMessage.getType())
                .setContent(baseMessage)
                .setPushContent("")
                .setPushData("")
                .setCount("")
                .setVerifyBlacklist(0)
                .setIsPersisted(0)
                .setIsCounted(0)
                .setIsIncludeSender(0);
        //发送单聊方法
        try {
            rongCloud.message.msgPrivate.send(privateMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送群组消息
     * @param fromUserId 注意当前用户id不会接收到该消息
     * @param toGroupId 群id
     */
    public static void sendGroupMessage(String fromUserId, String toGroupId, BaseMessage baseMessage, String pushContent, String pushData){
        GroupMessage groupMessage = new GroupMessage()
                .setSenderId(fromUserId)
                .setTargetId(new String[]{toGroupId})
                .setObjectName(baseMessage.getType())
                .setContent(baseMessage)
                .setPushContent(pushContent)
                .setPushData(pushData)
                .setIsPersisted(0)
                .setIsCounted(0)
                .setIsIncludeSender(0)
                .setContentAvailable(0);
        try {
            ResponseResult groupResult = rongCloud.message.group.send(groupMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 移除黑名单
     */
    public static void removeBlackList(String userId,String friendId){
        UserModel user = getUserModel(userId,friendId);
        try {
            rongCloud.user.blackList.remove(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加黑名单
     */
    public static void addBlackList(String userId,String friendId){
        UserModel user = getUserModel(userId,friendId);
        try {
            rongCloud.user.blackList.add(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static UserModel getUserModel(String userId,String friendId){
        UserModel blackUser = new UserModel().setId(userId);
        UserModel[] blacklist = {blackUser};
        UserModel user = new UserModel()
                .setId(friendId)
                .setBlacklist(blacklist);
        return user;
    }
}

五、/invite 发起好友请求:(其实主要就是   判断 status 的值,再更改status的值 )

/**
 * 添加好友
 *
 * @param friendShipInviteDTO 请求参数
 * @return 响应结果
 * @author @2021-03-15 18:35
 */
public Response wholeInvite(FriendShipInviteDTO requestDTO) {
        // 当前用户账号
        String userAccount = requestDTO.getUserAccount();
        // 好友账号
        String friendAccount = requestDTO.getFriendAccount();
        // 添加好友的验证信息
        String message = StringUtils.isBlank(requestDTO.getMessage())
                ? "我是 " + userAccount : requestDTO.getMessage();
        // 推送标题
        String pushContent = requestDTO.getPushContent();
        // 推送内容
        String pushData = requestDTO.getPushData();
        // 获取当前账号的昵称
        RongCloudUserPO rongCloudUserPO = rongCloudUserDao.selectByAccount(userAccount);
        if (rongCloudUserPO == null || StringUtils.isBlank(rongCloudUserPO.getNickname())) {
            throw new BusinessException(CodeConstant.RongCloud.ACCOUNT_NOT_EXIST, "账号\"" + userAccount + "\"未注册!");
        }
        String nickName = rongCloudUserPO.getNickname();
        // 请求者
        RongCloudFriendShipPO requester = rongCloudFriendshipDao.selectByAccount(userAccount, friendAccount);
        // 被请求者
        RongCloudFriendShipPO friend = rongCloudFriendshipDao.selectByAccount(friendAccount, userAccount);
        int requesterStatus, friendStatus;
        String action = "Added";
        String resultMessage = "无需对方确认,已成功添加好友";
        // 通过融云发送好友请求
        String extra = "{sourceUserNickname:" + nickName + ",version:123456}";
        if (requester != null && friend != null) {
            if (requester.getStatus() == RongCloudConstant.AGREED && friend.getStatus() == RongCloudConstant.AGREED) {
                return msg(CodeConstant.RongCloud.ALREADY_FRIEND, "你们已经是好友了", null);
            }
            if (friend.getStatus() == RongCloudConstant.AGREED || friend.getStatus() == RongCloudConstant.REQUESTING) {
                requesterStatus = RongCloudConstant.REQUESTING;
                friendStatus = RongCloudConstant.REQUESTED;
                action = "Sent";
                resultMessage = "请求已发送";
            } else if ((requester.getStatus() == RongCloudConstant.DELETED && friend.getStatus() == RongCloudConstant.DELETED)
                    || (requester.getStatus() == RongCloudConstant.AGREED && friend.getStatus() == RongCloudConstant.DELETED)
                    || (requester.getStatus() == RongCloudConstant.REQUESTING && friend.getStatus() == RongCloudConstant.IGNORED)
                    || (requester.getStatus() == RongCloudConstant.REQUESTING && friend.getStatus() == RongCloudConstant.REQUESTED)) {
                requesterStatus = RongCloudConstant.REQUESTING;
                friendStatus = RongCloudConstant.REQUESTED;
                action = "Sent";
                resultMessage = "请求已发送";
            } else {
                // 什么都不做
                return msg(RongCloudConstant.Code.SUCCESS, "什么都不做.", "None");
            }
            //更新状态
            requester.setStatus(requesterStatus);
            friend.setStatus(friendStatus);
            requester.setMessage("");
            friend.setMessage(message);
            requester.setUpdateTime(new Date());
            friend.setUpdateTime(new Date());
            rongCloudFriendshipDao.update(requester);
            rongCloudFriendshipDao.update(friend);
            // 通过融云发送好友请求
            if (friend.getStatus() == RongCloudConstant.REQUESTED) {
                sendContactMessage(RongCloudConstant.CONTACT_OPERATION_REQUEST, userAccount, friendAccount, message, pushContent, pushData, extra);
            }
        } else {
            // 之前没有加过好友
            if (userAccount.equals(friendAccount)) {
                // 自己加自己无条件通过
                saveFriendShip(userAccount, friendAccount, message, RongCloudConstant.AGREED);
            } else {
                // 请求者的 status为 requesting
                saveFriendShip(userAccount, friendAccount, "", RongCloudConstant.REQUESTING);
                // 被请求者的 status 为 requested
                saveFriendShip(friendAccount, userAccount, message, RongCloudConstant.REQUESTED);
                // 通过融云发送好友请求
                sendContactMessage(RongCloudConstant.CONTACT_OPERATION_REQUEST, userAccount, friendAccount, message, pushContent, pushData, extra);
            }
        }
        return msg(CodeConstant.Http.SUCCESS, resultMessage, action);
    }

六、/agree 同意好友请求

主要在于小灰条,可查看 融云控制台里面的 API调用

java 集群应用_推送_04

public Response wholeAgree(@RequestBody @Validated FriendShipAccountDTO requestDTO) {
        // 当前用户id (被请求者)
        String userAccount = requestDTO.getUserAccount();
        // 请求者
        String requestAccount = requestDTO.getFriendAccount();
        // 查询账号是否存在
        RongCloudUserPO userPO = rongCloudUserDao.selectByAccount(userAccount);
        if (userPO == null) {
            throw new BusinessException(CodeConstant.RongCloud.ACCOUNT_NOT_EXIST, "账号不存在!");
        }
        RongCloudUserPO friendUserPO = rongCloudUserDao.selectByAccount(requestAccount);
        if (friendUserPO == null) {
            throw new BusinessException(CodeConstant.RongCloud.ACCOUNT_NOT_EXIST, "好友账号不存在!");
        }
        // 更新双方的 status为AGREE
        RongCloudFriendShipPO fd = rongCloudFriendshipDao.selectByAccount(userAccount, requestAccount);
        RongCloudFriendShipPO fg = rongCloudFriendshipDao.selectByAccount(requestAccount, userAccount);
        if (fg != null && fg.getStatus() != RongCloudConstant.REQUESTING 
                && fg.getStatus() != RongCloudConstant.AGREED 
                && fg.getStatus() != RongCloudConstant.REQUESTED) {
            return ResponseUtil.getResponse(CodeConstant.RongCloud.UNKNOW_FRIEND, "无效的好友请求,或者未知好友", null);
        }
        // 将双方的状态都置为同意
        rongCloudFriendshipDao.updateStatus(userAccount, requestAccount, RongCloudConstant.AGREED, new Date(), "");
        rongCloudFriendshipDao.updateStatus(requestAccount, userAccount, RongCloudConstant.AGREED, new Date(), "");
        // 给请求者 发一条消息说,我同意你的请求了
        String extra = "{sourceUserNickname:" + userPO.getNickname() + ",version:123456}";
        sendContactMessage(RongCloudConstant.CONTACT_OPERATION_ACCEPT_RESPONSE, userAccount, requestAccount,
                "我是" + userAccount + ",我已经同意你的好友请求了", "", "", extra);
        // 小灰条通知
        RongCloudUtil.sendPrivateMsg(userAccount, requestAccount,
                new InformationNtfMessage("你已添加了" + friendUserPO.getNickname() + ",现在可以开始聊天了。", ""));
        // 文本消息
        RongCloudUtil.sendPrivateMsg(userAccount, requestAccount,
                new TxtMessage("我通过了你的朋友验证请求,现在我们可以开始聊天了", ""));
        RongCloudUtil.sendPrivateMsg(requestAccount, userAccount,
                new TxtMessage(fd.getMessage(), ""));
        // 移除黑名单
        RongCloudUtil.removeBlackList(userAccount, requestAccount);
        RongCloudUtil.removeBlackList(requestAccount, userAccount);
        return ResponseUtil.getSuccessResponse();
    }

例如:  【十月】请求添加【实话实说】为好友,发送的验证请求内容是“我是十月,通过下”。

【实话实说】同意请求。 此时,【十月】会给【实话实说】发一条  TxtMsg文本消息 (发送的内容就是 它请求的验证消息)

java 集群应用_推送_05

【实话实说】也会发一条消息给【十月】来通知对方我同意了请求(这里有小灰条)

java 集群应用_群组_06

七、/delete   删除好友

注意 只需要 将一方的 status 改为  30 就可以了,并且需要加入融云提供的黑名单,两人才不能通信(不然只要聊天界面还在,两人还是可以聊天的)!

java 集群应用_融云java好友关系_07

/**
 * 逻辑删除好友(将status置为 {@link RongCloudConstant#DELETED})
 *
 * @param friendShipAccountDTO 请求参数
 */
public void delete(FriendShipAccountDTO requestDTO) {
        RongCloudFriendShipPO fg = rongCloudFriendshipDao.selectByAccount(requestDTO.getUserAccount(), requestDTO.getFriendAccount());
        if (fg == null || fg.getStatus() != RongCloudConstant.AGREED) {
            throw new BusinessException(CodeConstant.RongCloud.REJECT_OPERATION, "你们不是好友关系,不能执行相关操作");
        }
        fg.setDisplayName("");
        fg.setMessage("");
        fg.setStatus(RongCloudConstant.DELETED);
        fg.setUpdateTime(new Date());
        rongCloudFriendshipDao.update(fg);

        //添加到黑名单
        RongCloudUtil.addBlackList(requestDTO.getUserAccount(), requestDTO.getFriendAccount());
        RongCloudUtil.addBlackList(requestDTO.getFriendAccount(), requestDTO.getUserAccount());

    }

其它方法不贴了,主要的难点在于,发送融云提供的系统消息,通知对方我要加你为好友了,以及小灰条~

具体代码我已经分享到https://gitee.com/why_su/erongcloud了,可以参考下。

java 集群应用_java 集群应用_08