移动app
This commit is contained in:
17
hs-im-app/App.vue
Normal file
17
hs-im-app/App.vue
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
onLaunch: function() {
|
||||||
|
console.log('App Launch')
|
||||||
|
},
|
||||||
|
onShow: function() {
|
||||||
|
console.log('App Show')
|
||||||
|
},
|
||||||
|
onHide: function() {
|
||||||
|
console.log('App Hide')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/*每个页面公共css */
|
||||||
|
</style>
|
||||||
20
hs-im-app/index.html
Normal file
20
hs-im-app/index.html
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<script>
|
||||||
|
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||||
|
CSS.supports('top: constant(a)'))
|
||||||
|
document.write(
|
||||||
|
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||||
|
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||||
|
</script>
|
||||||
|
<title></title>
|
||||||
|
<!--preload-links-->
|
||||||
|
<!--app-context-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"><!--app-html--></div>
|
||||||
|
<script type="module" src="/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
22
hs-im-app/main.js
Normal file
22
hs-im-app/main.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import App from './App'
|
||||||
|
|
||||||
|
// #ifndef VUE3
|
||||||
|
import Vue from 'vue'
|
||||||
|
import './uni.promisify.adaptor'
|
||||||
|
Vue.config.productionTip = false
|
||||||
|
App.mpType = 'app'
|
||||||
|
const app = new Vue({
|
||||||
|
...App
|
||||||
|
})
|
||||||
|
app.$mount()
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef VUE3
|
||||||
|
import { createSSRApp } from 'vue'
|
||||||
|
export function createApp() {
|
||||||
|
const app = createSSRApp(App)
|
||||||
|
return {
|
||||||
|
app
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
72
hs-im-app/manifest.json
Normal file
72
hs-im-app/manifest.json
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"name" : "hs-im-app",
|
||||||
|
"appid" : "__UNI__1D29CD0",
|
||||||
|
"description" : "",
|
||||||
|
"versionName" : "1.0.0",
|
||||||
|
"versionCode" : "100",
|
||||||
|
"transformPx" : false,
|
||||||
|
/* 5+App特有相关 */
|
||||||
|
"app-plus" : {
|
||||||
|
"usingComponents" : true,
|
||||||
|
"nvueStyleCompiler" : "uni-app",
|
||||||
|
"compilerVersion" : 3,
|
||||||
|
"splashscreen" : {
|
||||||
|
"alwaysShowBeforeRender" : true,
|
||||||
|
"waiting" : true,
|
||||||
|
"autoclose" : true,
|
||||||
|
"delay" : 0
|
||||||
|
},
|
||||||
|
/* 模块配置 */
|
||||||
|
"modules" : {},
|
||||||
|
/* 应用发布信息 */
|
||||||
|
"distribute" : {
|
||||||
|
/* android打包配置 */
|
||||||
|
"android" : {
|
||||||
|
"permissions" : [
|
||||||
|
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
/* ios打包配置 */
|
||||||
|
"ios" : {},
|
||||||
|
/* SDK配置 */
|
||||||
|
"sdkConfigs" : {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* 快应用特有相关 */
|
||||||
|
"quickapp" : {},
|
||||||
|
/* 小程序特有相关 */
|
||||||
|
"mp-weixin" : {
|
||||||
|
"appid" : "",
|
||||||
|
"setting" : {
|
||||||
|
"urlCheck" : false
|
||||||
|
},
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"mp-alipay" : {
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"mp-baidu" : {
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"mp-toutiao" : {
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : false
|
||||||
|
},
|
||||||
|
"vueVersion" : "2"
|
||||||
|
}
|
||||||
23
hs-im-app/pages.json
Normal file
23
hs-im-app/pages.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "pages/index/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "uni-app"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"path": "pages/index/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "uni-app"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"globalStyle": {
|
||||||
|
"navigationBarTextStyle": "black",
|
||||||
|
"navigationBarTitleText": "uni-app",
|
||||||
|
"navigationBarBackgroundColor": "#F8F8F8",
|
||||||
|
"backgroundColor": "#F8F8F8"
|
||||||
|
},
|
||||||
|
"uniIdRouter": {}
|
||||||
|
}
|
||||||
52
hs-im-app/pages/index/index.vue
Normal file
52
hs-im-app/pages/index/index.vue
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<template>
|
||||||
|
<view class="content">
|
||||||
|
<image class="logo" src="/static/logo.png"></image>
|
||||||
|
<view class="text-area">
|
||||||
|
<text class="title">{{title}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
title: 'Hello'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
height: 200rpx;
|
||||||
|
width: 200rpx;
|
||||||
|
margin-top: 200rpx;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-bottom: 50rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-area {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #8f8f94;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
22
hs-im-app/pages/login/login.vue
Normal file
22
hs-im-app/pages/login/login.vue
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
BIN
hs-im-app/static/logo.png
Normal file
BIN
hs-im-app/static/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
10
hs-im-app/uni.promisify.adaptor.js
Normal file
10
hs-im-app/uni.promisify.adaptor.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
uni.addInterceptor({
|
||||||
|
returnValue (res) {
|
||||||
|
if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
res.then((res) => res[0] ? reject(res[0]) : resolve(res[1]));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
76
hs-im-app/uni.scss
Normal file
76
hs-im-app/uni.scss
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* 这里是uni-app内置的常用样式变量
|
||||||
|
*
|
||||||
|
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||||
|
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||||
|
*
|
||||||
|
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 颜色变量 */
|
||||||
|
|
||||||
|
/* 行为相关颜色 */
|
||||||
|
$uni-color-primary: #007aff;
|
||||||
|
$uni-color-success: #4cd964;
|
||||||
|
$uni-color-warning: #f0ad4e;
|
||||||
|
$uni-color-error: #dd524d;
|
||||||
|
|
||||||
|
/* 文字基本颜色 */
|
||||||
|
$uni-text-color:#333;//基本色
|
||||||
|
$uni-text-color-inverse:#fff;//反色
|
||||||
|
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
|
||||||
|
$uni-text-color-placeholder: #808080;
|
||||||
|
$uni-text-color-disable:#c0c0c0;
|
||||||
|
|
||||||
|
/* 背景颜色 */
|
||||||
|
$uni-bg-color:#ffffff;
|
||||||
|
$uni-bg-color-grey:#f8f8f8;
|
||||||
|
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
|
||||||
|
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
|
||||||
|
|
||||||
|
/* 边框颜色 */
|
||||||
|
$uni-border-color:#c8c7cc;
|
||||||
|
|
||||||
|
/* 尺寸变量 */
|
||||||
|
|
||||||
|
/* 文字尺寸 */
|
||||||
|
$uni-font-size-sm:12px;
|
||||||
|
$uni-font-size-base:14px;
|
||||||
|
$uni-font-size-lg:16;
|
||||||
|
|
||||||
|
/* 图片尺寸 */
|
||||||
|
$uni-img-size-sm:20px;
|
||||||
|
$uni-img-size-base:26px;
|
||||||
|
$uni-img-size-lg:40px;
|
||||||
|
|
||||||
|
/* Border Radius */
|
||||||
|
$uni-border-radius-sm: 2px;
|
||||||
|
$uni-border-radius-base: 3px;
|
||||||
|
$uni-border-radius-lg: 6px;
|
||||||
|
$uni-border-radius-circle: 50%;
|
||||||
|
|
||||||
|
/* 水平间距 */
|
||||||
|
$uni-spacing-row-sm: 5px;
|
||||||
|
$uni-spacing-row-base: 10px;
|
||||||
|
$uni-spacing-row-lg: 15px;
|
||||||
|
|
||||||
|
/* 垂直间距 */
|
||||||
|
$uni-spacing-col-sm: 4px;
|
||||||
|
$uni-spacing-col-base: 8px;
|
||||||
|
$uni-spacing-col-lg: 12px;
|
||||||
|
|
||||||
|
/* 透明度 */
|
||||||
|
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
|
||||||
|
|
||||||
|
/* 文章场景相关 */
|
||||||
|
$uni-color-title: #2C405A; // 文章标题颜色
|
||||||
|
$uni-font-size-title:20px;
|
||||||
|
$uni-color-subtitle: #555555; // 二级标题颜色
|
||||||
|
$uni-font-size-subtitle:26px;
|
||||||
|
$uni-color-paragraph: #3F536E; // 文章段落颜色
|
||||||
|
$uni-font-size-paragraph:15px;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
rabitMQTT
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
docker run -d -it -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:management
|
||||||
|
|
||||||
|
```
|
||||||
|
在web管理后台新建Exchanges :
|
||||||
|
`messageService2Pipeline`
|
||||||
|
`pipeline2UserService`
|
||||||
|
|
||||||
|
|
||||||
|
zookeeper搭建教程
|
||||||
|
|
||||||
|
https://blog.csdn.net/weixin_43559374/article/details/131588024
|
||||||
|
|||||||
42
hs-im-server/doc/privateSend.py
Normal file
42
hs-im-server/doc/privateSend.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import socket
|
||||||
|
import uuid
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
|
||||||
|
s.connect(("127.0.0.1",9000))
|
||||||
|
|
||||||
|
imei = str(uuid.uuid4())
|
||||||
|
|
||||||
|
print(imei)
|
||||||
|
|
||||||
|
## 基础数据
|
||||||
|
command = 9888
|
||||||
|
version = 1
|
||||||
|
clientType = 4
|
||||||
|
messageType= 0x0
|
||||||
|
appId = 10000
|
||||||
|
name ='rowger'
|
||||||
|
|
||||||
|
## 数据转换为bytes
|
||||||
|
commandByte = command.to_bytes(4, "big")
|
||||||
|
versionByte = version.to_bytes(4,'big')
|
||||||
|
messageTypeByte = messageType.to_bytes(4,'big')
|
||||||
|
clientTypeByte = clientType.to_bytes(4,'big')
|
||||||
|
appIdByte = appId.to_bytes(4,"big")
|
||||||
|
clientTypeByte = clientType.to_bytes(4, 'big')
|
||||||
|
imeiBytes = bytes(imei,"utf-8")
|
||||||
|
imeiLength = len(imeiBytes)
|
||||||
|
imeiLengthByte = imeiLength.to_bytes(4, 'big')
|
||||||
|
|
||||||
|
data = {"name": name, "appId": appId, "clientType": clientType, "imei": imei}
|
||||||
|
|
||||||
|
|
||||||
|
jsonData = json.dumps(data)
|
||||||
|
body = bytes(jsonData, 'utf-8')
|
||||||
|
body_len = len(body)
|
||||||
|
bodyLenBytes = body_len.to_bytes(4,"big")
|
||||||
|
|
||||||
|
s.sendall(commandByte + versionByte + clientTypeByte + messageTypeByte + appIdByte + imeiLengthByte + bodyLenBytes + imeiBytes + body)
|
||||||
|
print("Sending end")
|
||||||
|
|
||||||
46
hs-im-server/im-codec/pom.xml
Normal file
46
hs-im-server/im-codec/pom.xml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.lld</groupId>
|
||||||
|
<artifactId>im-system</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>im-codec</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- netty -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-all</artifactId>
|
||||||
|
<version>4.1.35.Final</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- fastjson -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>1.2.51</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- common -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lld</groupId>
|
||||||
|
<artifactId>common</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.lld.im.codec;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.lld.im.codec.proto.Message;
|
||||||
|
import com.lld.im.codec.proto.MessageHeader;
|
||||||
|
import com.lld.im.codec.utils.ByteBufToMessageUtils;
|
||||||
|
import com.sun.org.apache.bcel.internal.generic.NEW;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 消息解码类
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
public class MessageDecoder extends ByteToMessageDecoder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void decode(ChannelHandlerContext ctx,
|
||||||
|
ByteBuf in, List<Object> out) throws Exception {
|
||||||
|
//请求头(指令
|
||||||
|
// 版本
|
||||||
|
// clientType
|
||||||
|
// 消息解析类型
|
||||||
|
// appId
|
||||||
|
// imei长度
|
||||||
|
// bodylen)+ imei号 + 请求体
|
||||||
|
|
||||||
|
if(in.readableBytes() < 28){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Message message = ByteBufToMessageUtils.transition(in);
|
||||||
|
if(message == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.add(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.lld.im.codec;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.lld.im.codec.proto.MessagePack;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.MessageToByteEncoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 消息编码类,私有协议规则,前4位表示长度,接着command4位,后面是数据
|
||||||
|
**/
|
||||||
|
public class MessageEncoder extends MessageToByteEncoder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
|
||||||
|
if(msg instanceof MessagePack){
|
||||||
|
MessagePack msgBody = (MessagePack) msg;
|
||||||
|
String s = JSONObject.toJSONString(msgBody.getData());
|
||||||
|
byte[] bytes = s.getBytes();
|
||||||
|
out.writeInt(msgBody.getCommand());
|
||||||
|
out.writeInt(bytes.length);
|
||||||
|
out.writeBytes(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.lld.im.codec;
|
||||||
|
|
||||||
|
import com.lld.im.codec.proto.Message;
|
||||||
|
import com.lld.im.codec.utils.ByteBufToMessageUtils;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||||
|
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
public class WebSocketMessageDecoder extends MessageToMessageDecoder<BinaryWebSocketFrame> {
|
||||||
|
@Override
|
||||||
|
protected void decode(ChannelHandlerContext ctx, BinaryWebSocketFrame msg, List<Object> out) throws Exception {
|
||||||
|
System.out.println("ws解码器收到信息");
|
||||||
|
|
||||||
|
ByteBuf content = msg.content();
|
||||||
|
if (content.readableBytes() < 28) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Message message = ByteBufToMessageUtils.transition(content);
|
||||||
|
if(message == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
out.add(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.lld.im.codec;
|
||||||
|
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.lld.im.codec.proto.MessagePack;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||||
|
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description:
|
||||||
|
**/
|
||||||
|
public class WebSocketMessageEncoder extends MessageToMessageEncoder<MessagePack> {
|
||||||
|
|
||||||
|
private static Logger log = LoggerFactory.getLogger(WebSocketMessageEncoder.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void encode(ChannelHandlerContext ctx, MessagePack msg, List<Object> out) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
String s = JSONObject.toJSONString(msg);
|
||||||
|
ByteBuf byteBuf = Unpooled.directBuffer(8+s.length());
|
||||||
|
byte[] bytes = s.getBytes();
|
||||||
|
byteBuf.writeInt(msg.getCommand());
|
||||||
|
byteBuf.writeInt(bytes.length);
|
||||||
|
byteBuf.writeBytes(bytes);
|
||||||
|
out.add(new BinaryWebSocketFrame(byteBuf));
|
||||||
|
}catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
package com.lld.im.codec.config;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description:
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class BootstrapConfig {
|
||||||
|
|
||||||
|
private TcpConfig lim;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class TcpConfig {
|
||||||
|
private Integer tcpPort;// tcp 绑定的端口号
|
||||||
|
|
||||||
|
private Integer webSocketPort; // webSocket 绑定的端口号
|
||||||
|
|
||||||
|
private boolean enableWebSocket; //是否启用webSocket
|
||||||
|
|
||||||
|
private Integer bossThreadSize; // boss线程 默认=1
|
||||||
|
|
||||||
|
private Integer workThreadSize; //work线程
|
||||||
|
|
||||||
|
private Long heartBeatTime; //心跳超时时间 单位毫秒
|
||||||
|
|
||||||
|
private Integer loginModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* redis配置
|
||||||
|
*/
|
||||||
|
private RedisConfig redis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rabbitmq配置
|
||||||
|
*/
|
||||||
|
private Rabbitmq rabbitmq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zk配置
|
||||||
|
*/
|
||||||
|
private ZkConfig zkConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brokerId
|
||||||
|
*/
|
||||||
|
private Integer brokerId;
|
||||||
|
|
||||||
|
private String logicUrl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class ZkConfig {
|
||||||
|
/**
|
||||||
|
* zk连接地址
|
||||||
|
*/
|
||||||
|
private String zkAddr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zk连接超时时间
|
||||||
|
*/
|
||||||
|
private Integer zkConnectTimeOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class RedisConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单机模式:single 哨兵模式:sentinel 集群模式:cluster
|
||||||
|
*/
|
||||||
|
private String mode;
|
||||||
|
/**
|
||||||
|
* 数据库
|
||||||
|
*/
|
||||||
|
private Integer database;
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
/**
|
||||||
|
* 超时时间
|
||||||
|
*/
|
||||||
|
private Integer timeout;
|
||||||
|
/**
|
||||||
|
* 最小空闲数
|
||||||
|
*/
|
||||||
|
private Integer poolMinIdle;
|
||||||
|
/**
|
||||||
|
* 连接超时时间(毫秒)
|
||||||
|
*/
|
||||||
|
private Integer poolConnTimeout;
|
||||||
|
/**
|
||||||
|
* 连接池大小
|
||||||
|
*/
|
||||||
|
private Integer poolSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* redis单机配置
|
||||||
|
*/
|
||||||
|
private RedisSingle single;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* redis单机配置
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class RedisSingle {
|
||||||
|
/**
|
||||||
|
* 地址
|
||||||
|
*/
|
||||||
|
private String address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rabbitmq哨兵模式配置
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class Rabbitmq {
|
||||||
|
private String host;
|
||||||
|
|
||||||
|
private Integer port;
|
||||||
|
|
||||||
|
private String virtualHost;
|
||||||
|
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.lld.im.codec.pack;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class LoginPack {
|
||||||
|
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.lld.im.codec.pack.conversation;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DeleteConversationPack {
|
||||||
|
|
||||||
|
private String conversationId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.lld.im.codec.pack.conversation;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class UpdateConversationPack {
|
||||||
|
|
||||||
|
private String conversationId;
|
||||||
|
|
||||||
|
private Integer isMute;
|
||||||
|
|
||||||
|
private Integer isTop;
|
||||||
|
|
||||||
|
private Integer conversationType;
|
||||||
|
|
||||||
|
private Long sequence;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.lld.im.codec.pack.friendship;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 用户添加黑名单以后tcp通知数据包
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class AddFriendBlackPack {
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
private Long sequence;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.lld.im.codec.pack.friendship;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 好友分组添加成员通知包
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class AddFriendGroupMemberPack {
|
||||||
|
|
||||||
|
public String fromId;
|
||||||
|
|
||||||
|
private String groupName;
|
||||||
|
|
||||||
|
private List<String> toIds;
|
||||||
|
|
||||||
|
/** 序列号*/
|
||||||
|
private Long sequence;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.lld.im.codec.pack.friendship;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 用户创建好友分组通知包
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class AddFriendGroupPack {
|
||||||
|
public String fromId;
|
||||||
|
|
||||||
|
private String groupName;
|
||||||
|
|
||||||
|
/** 序列号*/
|
||||||
|
private Long sequence;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.lld.im.codec.pack.friendship;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 添加好友通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class AddFriendPack {
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
private String toId;
|
||||||
|
/**
|
||||||
|
* 好友来源
|
||||||
|
*/
|
||||||
|
private String addSource;
|
||||||
|
/**
|
||||||
|
* 添加好友时的描述信息(用于打招呼)
|
||||||
|
*/
|
||||||
|
private String addWording;
|
||||||
|
|
||||||
|
private Long sequence;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.lld.im.codec.pack.friendship;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 审批好友申请通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class ApproverFriendRequestPack {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
//1同意 2拒绝
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
private Long sequence;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.lld.im.codec.pack.friendship;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 删除黑名单通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class DeleteAllFriendPack {
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.lld.im.codec.pack.friendship;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 删除黑名单通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class DeleteBlackPack {
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
private Long sequence;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.lld.im.codec.pack.friendship;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 删除好友分组成员通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class DeleteFriendGroupMemberPack {
|
||||||
|
|
||||||
|
public String fromId;
|
||||||
|
|
||||||
|
private String groupName;
|
||||||
|
|
||||||
|
private List<String> toIds;
|
||||||
|
|
||||||
|
/** 序列号*/
|
||||||
|
private Long sequence;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.lld.im.codec.pack.friendship;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 删除好友分组通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class DeleteFriendGroupPack {
|
||||||
|
public String fromId;
|
||||||
|
|
||||||
|
private String groupName;
|
||||||
|
|
||||||
|
/** 序列号*/
|
||||||
|
private Long sequence;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.lld.im.codec.pack.friendship;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 删除好友通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class DeleteFriendPack {
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
private Long sequence;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.lld.im.codec.pack.friendship;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 已读好友申请通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class ReadAllFriendRequestPack {
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private Long sequence;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.lld.im.codec.pack.friendship;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 修改好友通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class UpdateFriendPack {
|
||||||
|
|
||||||
|
public String fromId;
|
||||||
|
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
private Long sequence;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.lld.im.codec.pack.group;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 群内添加群成员通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class AddGroupMemberPack {
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
private List<String> members;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.lld.im.codec.pack.group;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 创建群组通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class CreateGroupPack {
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
private Integer appId;
|
||||||
|
|
||||||
|
//群主id
|
||||||
|
private String ownerId;
|
||||||
|
|
||||||
|
//群类型 1私有群(类似微信) 2公开群(类似qq)
|
||||||
|
private Integer groupType;
|
||||||
|
|
||||||
|
private String groupName;
|
||||||
|
|
||||||
|
private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。
|
||||||
|
|
||||||
|
// 申请加群选项包括如下几种:
|
||||||
|
// 0 表示禁止任何人申请加入
|
||||||
|
// 1 表示需要群主或管理员审批
|
||||||
|
// 2 表示允许无需审批自由加入群组
|
||||||
|
private Integer applyJoinType;
|
||||||
|
|
||||||
|
private Integer privateChat; //是否禁止私聊,0 允许群成员发起私聊;1 不允许群成员发起私聊。
|
||||||
|
|
||||||
|
private String introduction;//群简介
|
||||||
|
|
||||||
|
private String notification;//群公告
|
||||||
|
|
||||||
|
private String photo;//群头像
|
||||||
|
|
||||||
|
private Integer status;//群状态 0正常 1解散
|
||||||
|
|
||||||
|
private Long sequence;
|
||||||
|
|
||||||
|
private Long createTime;
|
||||||
|
|
||||||
|
private String extra;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.lld.im.codec.pack.group;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 解散群通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class DestroyGroupPack {
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
private Long sequence;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.lld.im.codec.pack.group;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 群成员禁言通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class GroupMemberSpeakPack {
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
private String memberId;
|
||||||
|
|
||||||
|
private Long speakDate;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.lld.im.codec.pack.group;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 群聊消息分发报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class GroupMessagePack {
|
||||||
|
|
||||||
|
//客户端传的messageId
|
||||||
|
private String messageId;
|
||||||
|
|
||||||
|
private String messageKey;
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
private int messageRandom;
|
||||||
|
|
||||||
|
private long messageTime;
|
||||||
|
|
||||||
|
private long messageSequence;
|
||||||
|
|
||||||
|
private String messageBody;
|
||||||
|
/**
|
||||||
|
* 这个字段缺省或者为 0 表示需要计数,为 1 表示本条消息不需要计数,即右上角图标数字不增加
|
||||||
|
*/
|
||||||
|
private int badgeMode;
|
||||||
|
|
||||||
|
private Long messageLifeTime;
|
||||||
|
|
||||||
|
private Integer appId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.lld.im.codec.pack.group;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 禁言群tcp通知
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class MuteGroupPack {
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.lld.im.codec.pack.group;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 踢人出群通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class RemoveGroupMemberPack {
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
private String member;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.lld.im.codec.pack.group;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 转让群主通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class TransferGroupPack {
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
private String ownerId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.lld.im.codec.pack.group;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 修改群信息通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class UpdateGroupInfoPack {
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
private String groupName;
|
||||||
|
|
||||||
|
private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。
|
||||||
|
|
||||||
|
private Integer joinType;//加入群权限,0 所有人可以加入;1 群成员可以拉人;2 群管理员或群组可以拉人。
|
||||||
|
|
||||||
|
private String introduction;//群简介
|
||||||
|
|
||||||
|
private String notification;//群公告
|
||||||
|
|
||||||
|
private String photo;//群头像
|
||||||
|
|
||||||
|
private Integer maxMemberCount;//群成员上限
|
||||||
|
|
||||||
|
private Long sequence;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.lld.im.codec.pack.group;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 修改群成员通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class UpdateGroupMemberPack {
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
private String memberId;
|
||||||
|
|
||||||
|
private String alias;
|
||||||
|
|
||||||
|
private String extra;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.lld.im.codec.pack.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ChatMessageAck {
|
||||||
|
|
||||||
|
private String messageId;
|
||||||
|
private Long messageSequence;
|
||||||
|
|
||||||
|
public ChatMessageAck(String messageId) {
|
||||||
|
this.messageId = messageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChatMessageAck(String messageId,Long messageSequence) {
|
||||||
|
this.messageId = messageId;
|
||||||
|
this.messageSequence = messageSequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.lld.im.codec.pack.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MessageReadedPack {
|
||||||
|
|
||||||
|
private long messageSequence;
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
private Integer conversationType;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.lld.im.codec.pack.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MessageReciveServerAckPack {
|
||||||
|
|
||||||
|
private Long messageKey;
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
private Long messageSequence;
|
||||||
|
|
||||||
|
private Boolean serverSend;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.lld.im.codec.pack.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 撤回消息通知报文
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class RecallMessageNotifyPack {
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
private Long messageKey;
|
||||||
|
|
||||||
|
private Long messageSequence;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.lld.im.codec.pack.user;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class LoginAckPack {
|
||||||
|
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.lld.im.codec.pack.user;
|
||||||
|
|
||||||
|
import com.lld.im.common.model.UserSession;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class UserCustomStatusChangeNotifyPack {
|
||||||
|
|
||||||
|
private String customText;
|
||||||
|
|
||||||
|
private Integer customStatus;
|
||||||
|
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.lld.im.codec.pack.user;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class UserModifyPack {
|
||||||
|
// 用户id
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
// 用户名称
|
||||||
|
private String nickName;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
// 头像
|
||||||
|
private String photo;
|
||||||
|
|
||||||
|
// 性别
|
||||||
|
private String userSex;
|
||||||
|
|
||||||
|
// 个性签名
|
||||||
|
private String selfSignature;
|
||||||
|
|
||||||
|
// 加好友验证类型(Friend_AllowType) 1需要验证
|
||||||
|
private Integer friendAllowType;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.lld.im.codec.pack.user;
|
||||||
|
|
||||||
|
import com.lld.im.common.model.UserSession;
|
||||||
|
import lombok.Data;
|
||||||
|
import sun.dc.pr.PRError;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class UserStatusChangeNotifyPack {
|
||||||
|
|
||||||
|
private Integer appId;
|
||||||
|
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
private List<UserSession> client;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.lld.im.codec.proto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Message {
|
||||||
|
|
||||||
|
private MessageHeader messageHeader;
|
||||||
|
|
||||||
|
private Object messagePack;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Message{" +
|
||||||
|
"messageHeader=" + messageHeader +
|
||||||
|
", messagePack=" + messagePack +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.lld.im.codec.proto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MessageHeader {
|
||||||
|
|
||||||
|
//消息操作指令 十六进制 一个消息的开始通常以0x开头
|
||||||
|
//4字节
|
||||||
|
private Integer command;
|
||||||
|
//4字节 版本号
|
||||||
|
private Integer version;
|
||||||
|
//4字节 端类型
|
||||||
|
private Integer clientType;
|
||||||
|
/**
|
||||||
|
* 应用ID
|
||||||
|
*/
|
||||||
|
// 4字节 appId
|
||||||
|
private Integer appId;
|
||||||
|
/**
|
||||||
|
* 数据解析类型 和具体业务无关,后续根据解析类型解析data数据 0x0:Json,0x1:ProtoBuf,0x2:Xml,默认:0x0
|
||||||
|
*/
|
||||||
|
//4字节 解析类型
|
||||||
|
private Integer messageType = 0x0;
|
||||||
|
|
||||||
|
//4字节 imel长度
|
||||||
|
private Integer imeiLength;
|
||||||
|
|
||||||
|
//4字节 包体长度
|
||||||
|
private int length;
|
||||||
|
|
||||||
|
//imei号
|
||||||
|
private String imei;
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.lld.im.codec.proto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 消息服务发送给tcp的包体,tcp再根据改包体解析成Message发给客户端
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class MessagePack<T> implements Serializable {
|
||||||
|
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
private Integer appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收方
|
||||||
|
*/
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端标识
|
||||||
|
*/
|
||||||
|
private int clientType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息ID
|
||||||
|
*/
|
||||||
|
private String messageId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端设备唯一标识
|
||||||
|
*/
|
||||||
|
private String imei;
|
||||||
|
|
||||||
|
private Integer command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务数据对象,如果是聊天消息则不需要解析直接透传
|
||||||
|
*/
|
||||||
|
private T data;
|
||||||
|
|
||||||
|
// /** 用户签名*/
|
||||||
|
// private String userSign;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package com.lld.im.codec.utils;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.lld.im.codec.proto.Message;
|
||||||
|
import com.lld.im.codec.proto.MessageHeader;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: rowger
|
||||||
|
* @description: 将ByteBuf转化为Message实体,根据私有协议转换
|
||||||
|
* 私有协议规则,
|
||||||
|
* 4位表示Command表示消息的开始,
|
||||||
|
* 4位表示version
|
||||||
|
* 4位表示clientType
|
||||||
|
* 4位表示messageType
|
||||||
|
* 4位表示appId
|
||||||
|
* 4位表示imei长度
|
||||||
|
* imei
|
||||||
|
* 4位表示数据长度
|
||||||
|
* data
|
||||||
|
* 后续将解码方式加到数据头根据不同的解码方式解码,如pb,json,现在用json字符串
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
public class ByteBufToMessageUtils {
|
||||||
|
|
||||||
|
public static Message transition(ByteBuf in){
|
||||||
|
|
||||||
|
/** 获取command*/
|
||||||
|
int command = in.readInt();
|
||||||
|
|
||||||
|
/** 获取version*/
|
||||||
|
int version = in.readInt();
|
||||||
|
|
||||||
|
/** 获取clientType*/
|
||||||
|
int clientType = in.readInt();
|
||||||
|
|
||||||
|
/** 获取clientType*/
|
||||||
|
int messageType = in.readInt();
|
||||||
|
|
||||||
|
/** 获取appId*/
|
||||||
|
int appId = in.readInt();
|
||||||
|
|
||||||
|
/** 获取imeiLength*/
|
||||||
|
int imeiLength = in.readInt();
|
||||||
|
|
||||||
|
/** 获取bodyLen*/
|
||||||
|
int bodyLen = in.readInt();
|
||||||
|
|
||||||
|
if(in.readableBytes() < bodyLen + imeiLength){
|
||||||
|
in.resetReaderIndex();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte [] imeiData = new byte[imeiLength];
|
||||||
|
in.readBytes(imeiData);
|
||||||
|
String imei = new String(imeiData);
|
||||||
|
|
||||||
|
byte [] bodyData = new byte[bodyLen];
|
||||||
|
in.readBytes(bodyData);
|
||||||
|
|
||||||
|
|
||||||
|
MessageHeader messageHeader = new MessageHeader();
|
||||||
|
messageHeader.setAppId(appId);
|
||||||
|
messageHeader.setClientType(clientType);
|
||||||
|
messageHeader.setCommand(command);
|
||||||
|
messageHeader.setLength(bodyLen);
|
||||||
|
messageHeader.setVersion(version);
|
||||||
|
messageHeader.setMessageType(messageType);
|
||||||
|
messageHeader.setImei(imei);
|
||||||
|
|
||||||
|
Message message = new Message();
|
||||||
|
message.setMessageHeader(messageHeader);
|
||||||
|
|
||||||
|
if(messageType == 0x0){
|
||||||
|
String body = new String(bodyData);
|
||||||
|
JSONObject parse = (JSONObject) JSONObject.parse(body);
|
||||||
|
message.setMessagePack(parse);
|
||||||
|
}
|
||||||
|
|
||||||
|
in.markReaderIndex();
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.lld.im.common.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description:
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "appconfig")
|
||||||
|
public class AppConfig {
|
||||||
|
|
||||||
|
private String privateKey;
|
||||||
|
|
||||||
|
/** zk连接地址*/
|
||||||
|
private String zkAddr;
|
||||||
|
|
||||||
|
/** zk连接超时时间*/
|
||||||
|
private Integer zkConnectTimeOut;
|
||||||
|
|
||||||
|
/** im管道地址路由策略*/
|
||||||
|
private Integer imRouteWay;
|
||||||
|
|
||||||
|
private boolean sendMessageCheckFriend; //发送消息是否校验关系链
|
||||||
|
|
||||||
|
private boolean sendMessageCheckBlack; //发送消息是否校验黑名单
|
||||||
|
|
||||||
|
/** 如果选用一致性hash的话具体hash算法*/
|
||||||
|
private Integer consistentHashWay;
|
||||||
|
|
||||||
|
private String callbackUrl;
|
||||||
|
|
||||||
|
private boolean modifyUserAfterCallback; //用户资料变更之后回调开关
|
||||||
|
|
||||||
|
private boolean addFriendAfterCallback; //添加好友之后回调开关
|
||||||
|
|
||||||
|
private boolean addFriendBeforeCallback; //添加好友之前回调开关
|
||||||
|
|
||||||
|
private boolean modifyFriendAfterCallback; //修改好友之后回调开关
|
||||||
|
|
||||||
|
private boolean deleteFriendAfterCallback; //删除好友之后回调开关
|
||||||
|
|
||||||
|
private boolean addFriendShipBlackAfterCallback; //添加黑名单之后回调开关
|
||||||
|
|
||||||
|
private boolean deleteFriendShipBlackAfterCallback; //删除黑名单之后回调开关
|
||||||
|
|
||||||
|
private boolean createGroupAfterCallback; //创建群聊之后回调开关
|
||||||
|
|
||||||
|
private boolean modifyGroupAfterCallback; //修改群聊之后回调开关
|
||||||
|
|
||||||
|
private boolean destroyGroupAfterCallback;//解散群聊之后回调开关
|
||||||
|
|
||||||
|
private boolean deleteGroupMemberAfterCallback;//删除群成员之后回调
|
||||||
|
|
||||||
|
private boolean addGroupMemberBeforeCallback;//拉人入群之前回调
|
||||||
|
|
||||||
|
private boolean addGroupMemberAfterCallback;//拉人入群之后回调
|
||||||
|
|
||||||
|
private boolean sendMessageAfterCallback;//发送单聊消息之后
|
||||||
|
|
||||||
|
private boolean sendMessageBeforeCallback;//发送单聊消息之前
|
||||||
|
|
||||||
|
private Integer deleteConversationSyncMode;
|
||||||
|
|
||||||
|
private Integer offlineMessageCount;//离线消息最大条数
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
package com.lld.im.common.config;
|
||||||
|
|
||||||
|
import org.apache.http.client.config.RequestConfig;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "httpclient")
|
||||||
|
public class GlobalHttpClientConfig {
|
||||||
|
private Integer maxTotal; // 最大连接数
|
||||||
|
private Integer defaultMaxPerRoute; // 最大并发链接数
|
||||||
|
private Integer connectTimeout; // 创建链接的最大时间
|
||||||
|
private Integer connectionRequestTimeout; // 链接获取超时时间
|
||||||
|
private Integer socketTimeout; // 数据传输最长时间
|
||||||
|
private boolean staleConnectionCheckEnabled; // 提交时检查链接是否可用
|
||||||
|
|
||||||
|
PoolingHttpClientConnectionManager manager = null;
|
||||||
|
HttpClientBuilder httpClientBuilder = null;
|
||||||
|
|
||||||
|
// 定义httpClient链接池
|
||||||
|
@Bean(name = "httpClientConnectionManager")
|
||||||
|
public PoolingHttpClientConnectionManager getPoolingHttpClientConnectionManager() {
|
||||||
|
return getManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
private PoolingHttpClientConnectionManager getManager() {
|
||||||
|
if (manager != null) {
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
manager = new PoolingHttpClientConnectionManager();
|
||||||
|
manager.setMaxTotal(maxTotal); // 设定最大链接数
|
||||||
|
manager.setDefaultMaxPerRoute(defaultMaxPerRoute); // 设定并发链接数
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实例化连接池,设置连接池管理器。 这里需要以参数形式注入上面实例化的连接池管理器
|
||||||
|
*
|
||||||
|
* @Qualifier 指定bean标签进行注入
|
||||||
|
*/
|
||||||
|
@Bean(name = "httpClientBuilder")
|
||||||
|
public HttpClientBuilder getHttpClientBuilder(
|
||||||
|
@Qualifier("httpClientConnectionManager") PoolingHttpClientConnectionManager httpClientConnectionManager) {
|
||||||
|
|
||||||
|
// HttpClientBuilder中的构造方法被protected修饰,所以这里不能直接使用new来实例化一个HttpClientBuilder,可以使用HttpClientBuilder提供的静态方法create()来获取HttpClientBuilder对象
|
||||||
|
httpClientBuilder = HttpClientBuilder.create();
|
||||||
|
httpClientBuilder.setConnectionManager(httpClientConnectionManager);
|
||||||
|
return httpClientBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入连接池,用于获取httpClient
|
||||||
|
*
|
||||||
|
* @param httpClientBuilder
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public CloseableHttpClient getCloseableHttpClient(
|
||||||
|
@Qualifier("httpClientBuilder") HttpClientBuilder httpClientBuilder) {
|
||||||
|
|
||||||
|
return httpClientBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CloseableHttpClient getCloseableHttpClient() {
|
||||||
|
if (httpClientBuilder != null) {
|
||||||
|
return httpClientBuilder.build();
|
||||||
|
}
|
||||||
|
httpClientBuilder = HttpClientBuilder.create();
|
||||||
|
httpClientBuilder.setConnectionManager(getManager());
|
||||||
|
return httpClientBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder是RequestConfig的一个内部类 通过RequestConfig的custom方法来获取到一个Builder对象
|
||||||
|
* 设置builder的连接信息
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean(name = "builder")
|
||||||
|
public RequestConfig.Builder getBuilder() {
|
||||||
|
RequestConfig.Builder builder = RequestConfig.custom();
|
||||||
|
return builder.setConnectTimeout(connectTimeout).setConnectionRequestTimeout(connectionRequestTimeout)
|
||||||
|
.setSocketTimeout(socketTimeout).setStaleConnectionCheckEnabled(staleConnectionCheckEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用builder构建一个RequestConfig对象
|
||||||
|
*
|
||||||
|
* @param builder
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public RequestConfig getRequestConfig(@Qualifier("builder") RequestConfig.Builder builder) {
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getMaxTotal() {
|
||||||
|
return maxTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxTotal(Integer maxTotal) {
|
||||||
|
this.maxTotal = maxTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDefaultMaxPerRoute() {
|
||||||
|
return defaultMaxPerRoute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultMaxPerRoute(Integer defaultMaxPerRoute) {
|
||||||
|
this.defaultMaxPerRoute = defaultMaxPerRoute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getConnectTimeout() {
|
||||||
|
return connectTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConnectTimeout(Integer connectTimeout) {
|
||||||
|
this.connectTimeout = connectTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getConnectionRequestTimeout() {
|
||||||
|
return connectionRequestTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConnectionRequestTimeout(Integer connectionRequestTimeout) {
|
||||||
|
this.connectionRequestTimeout = connectionRequestTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSocketTimeout() {
|
||||||
|
return socketTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSocketTimeout(Integer socketTimeout) {
|
||||||
|
this.socketTimeout = socketTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStaleConnectionCheckEnabled() {
|
||||||
|
return staleConnectionCheckEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStaleConnectionCheckEnabled(boolean staleConnectionCheckEnabled) {
|
||||||
|
this.staleConnectionCheckEnabled = staleConnectionCheckEnabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
package com.lld.im.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
public class Constants {
|
||||||
|
|
||||||
|
/** channel绑定的userId Key*/
|
||||||
|
public static final String UserId = "userId";
|
||||||
|
|
||||||
|
/** channel绑定的appId */
|
||||||
|
public static final String AppId = "appId";
|
||||||
|
|
||||||
|
public static final String ClientType = "clientType";
|
||||||
|
|
||||||
|
public static final String Imei = "imei";
|
||||||
|
|
||||||
|
/** channel绑定的clientType 和 imel Key*/
|
||||||
|
public static final String ClientImei = "clientImei";
|
||||||
|
|
||||||
|
public static final String ReadTime = "readTime";
|
||||||
|
|
||||||
|
public static final String ImCoreZkRoot = "/im-coreRoot";
|
||||||
|
|
||||||
|
public static final String ImCoreZkRootTcp = "/tcp";
|
||||||
|
|
||||||
|
public static final String ImCoreZkRootWeb = "/web";
|
||||||
|
|
||||||
|
|
||||||
|
public static class RedisConstants{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* userSign,格式:appId:userSign:
|
||||||
|
*/
|
||||||
|
public static final String userSign = "userSign";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户上线通知channel
|
||||||
|
*/
|
||||||
|
public static final String UserLoginChannel
|
||||||
|
= "signal/channel/LOGIN_USER_INNER_QUEUE";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户session,appId + UserSessionConstants + 用户id 例如10000:userSession:lld
|
||||||
|
*/
|
||||||
|
public static final String UserSessionConstants = ":userSession:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存客户端消息防重,格式: appId + :cacheMessage: + messageId
|
||||||
|
*/
|
||||||
|
public static final String cacheMessage = "cacheMessage";
|
||||||
|
|
||||||
|
public static final String OfflineMessage = "offlineMessage";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* seq 前缀
|
||||||
|
*/
|
||||||
|
public static final String SeqPrefix = "seq";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户订阅列表,格式 :appId + :subscribe: + userId。Hash结构,filed为订阅自己的人
|
||||||
|
*/
|
||||||
|
public static final String subscribe = "subscribe";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户自定义在线状态,格式 :appId + :userCustomerStatus: + userId。set,value为用户id
|
||||||
|
*/
|
||||||
|
public static final String userCustomerStatus = "userCustomerStatus";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RabbitConstants{
|
||||||
|
|
||||||
|
public static final String Im2UserService = "pipeline2UserService";
|
||||||
|
|
||||||
|
public static final String Im2MessageService = "pipeline2MessageService";
|
||||||
|
|
||||||
|
public static final String Im2GroupService = "pipeline2GroupService";
|
||||||
|
|
||||||
|
public static final String Im2FriendshipService = "pipeline2FriendshipService";
|
||||||
|
|
||||||
|
public static final String MessageService2Im = "messageService2Pipeline";
|
||||||
|
|
||||||
|
public static final String GroupService2Im = "GroupService2Pipeline";
|
||||||
|
|
||||||
|
public static final String FriendShip2Im = "friendShip2Pipeline";
|
||||||
|
|
||||||
|
public static final String StoreP2PMessage = "storeP2PMessage";
|
||||||
|
|
||||||
|
public static final String StoreGroupMessage = "storeGroupMessage";
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CallbackCommand{
|
||||||
|
public static final String ModifyUserAfter = "user.modify.after";
|
||||||
|
|
||||||
|
public static final String CreateGroupAfter = "group.create.after";
|
||||||
|
|
||||||
|
public static final String UpdateGroupAfter = "group.update.after";
|
||||||
|
|
||||||
|
public static final String DestoryGroupAfter = "group.destory.after";
|
||||||
|
|
||||||
|
public static final String TransferGroupAfter = "group.transfer.after";
|
||||||
|
|
||||||
|
public static final String GroupMemberAddBefore = "group.member.add.before";
|
||||||
|
|
||||||
|
public static final String GroupMemberAddAfter = "group.member.add.after";
|
||||||
|
|
||||||
|
public static final String GroupMemberDeleteAfter = "group.member.delete.after";
|
||||||
|
|
||||||
|
public static final String AddFriendBefore = "friend.add.before";
|
||||||
|
|
||||||
|
public static final String AddFriendAfter = "friend.add.after";
|
||||||
|
|
||||||
|
public static final String UpdateFriendBefore = "friend.update.before";
|
||||||
|
|
||||||
|
public static final String UpdateFriendAfter = "friend.update.after";
|
||||||
|
|
||||||
|
public static final String DeleteFriendAfter = "friend.delete.after";
|
||||||
|
|
||||||
|
public static final String AddBlackAfter = "black.add.after";
|
||||||
|
|
||||||
|
public static final String DeleteBlack = "black.delete";
|
||||||
|
|
||||||
|
public static final String SendMessageAfter = "message.send.after";
|
||||||
|
|
||||||
|
public static final String SendMessageBefore = "message.send.before";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SeqConstants {
|
||||||
|
public static final String Message = "messageSeq";
|
||||||
|
|
||||||
|
public static final String GroupMessage = "groupMessageSeq";
|
||||||
|
|
||||||
|
|
||||||
|
public static final String Friendship = "friendshipSeq";
|
||||||
|
|
||||||
|
// public static final String FriendshipBlack = "friendshipBlackSeq";
|
||||||
|
|
||||||
|
public static final String FriendshipRequest = "friendshipRequestSeq";
|
||||||
|
|
||||||
|
public static final String FriendshipGroup = "friendshipGrouptSeq";
|
||||||
|
|
||||||
|
public static final String Group = "groupSeq";
|
||||||
|
|
||||||
|
public static final String Conversation = "conversationSeq";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.lld.im.common.enums;
|
||||||
|
|
||||||
|
import com.lld.im.common.exception.ApplicationExceptionEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description:
|
||||||
|
**/
|
||||||
|
public enum ConversationErrorCode implements ApplicationExceptionEnum {
|
||||||
|
|
||||||
|
CONVERSATION_UPDATE_PARAM_ERROR(50000,"會話修改參數錯誤"),
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private int code;
|
||||||
|
private String error;
|
||||||
|
|
||||||
|
ConversationErrorCode(int code, String error){
|
||||||
|
this.code = code;
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
public int getCode() {
|
||||||
|
return this.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getError() {
|
||||||
|
return this.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.lld.im.common.enums;
|
||||||
|
|
||||||
|
public enum ConversationTypeEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0 单聊 1群聊 2机器人 3公众号
|
||||||
|
*/
|
||||||
|
P2P(0),
|
||||||
|
|
||||||
|
GROUP(1),
|
||||||
|
|
||||||
|
ROBOT(2),
|
||||||
|
;
|
||||||
|
|
||||||
|
private int code;
|
||||||
|
|
||||||
|
ConversationTypeEnum(int code){
|
||||||
|
this.code=code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package com.lld.im.common.enums;
|
||||||
|
|
||||||
|
public enum DeviceMultiLoginEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单端登录 仅允许 Windows、Web、Android 或 iOS 单端登录。
|
||||||
|
*/
|
||||||
|
ONE(1,"DeviceMultiLoginEnum_ONE"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 双端登录 允许 Windows、Mac、Android 或 iOS 单端登录,同时允许与 Web 端同时在线。
|
||||||
|
*/
|
||||||
|
TWO(2,"DeviceMultiLoginEnum_TWO"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 三端登录 允许 Android 或 iOS 单端登录(互斥),Windows 或者 Mac 单聊登录(互斥),同时允许 Web 端同时在线
|
||||||
|
*/
|
||||||
|
THREE(3,"DeviceMultiLoginEnum_THREE"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多端同时在线 允许 Windows、Mac、Web、Android 或 iOS 多端或全端同时在线登录
|
||||||
|
*/
|
||||||
|
ALL(4,"DeviceMultiLoginEnum_ALL");
|
||||||
|
|
||||||
|
private int loginMode;
|
||||||
|
private String loginDesc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不能用 默认的 enumType b= enumType.values()[i]; 因为本枚举是类形式封装
|
||||||
|
* @param ordinal
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static DeviceMultiLoginEnum getMember(int ordinal) {
|
||||||
|
for (int i = 0; i < DeviceMultiLoginEnum.values().length; i++) {
|
||||||
|
if (DeviceMultiLoginEnum.values()[i].getLoginMode() == ordinal) {
|
||||||
|
return DeviceMultiLoginEnum.values()[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return THREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceMultiLoginEnum(int loginMode, String loginDesc){
|
||||||
|
this.loginMode=loginMode;
|
||||||
|
this.loginDesc=loginDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLoginMode() {
|
||||||
|
return loginMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginMode(int loginMode) {
|
||||||
|
this.loginMode = loginMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLoginDesc() {
|
||||||
|
return loginDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginDesc(String loginDesc) {
|
||||||
|
this.loginDesc = loginDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.lld.im.common.enums;
|
||||||
|
|
||||||
|
import com.lld.im.common.exception.ApplicationExceptionEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description: 6
|
||||||
|
**/
|
||||||
|
public enum GateWayErrorCode implements ApplicationExceptionEnum {
|
||||||
|
|
||||||
|
USERSIGN_NOT_EXIST(60000,"用户签名不存在"),
|
||||||
|
|
||||||
|
APPID_NOT_EXIST(60001,"appId不存在"),
|
||||||
|
|
||||||
|
OPERATER_NOT_EXIST(60002,"操作人不存在"),
|
||||||
|
|
||||||
|
USERSIGN_IS_ERROR(60003,"用户签名不正确"),
|
||||||
|
|
||||||
|
USERSIGN_OPERATE_NOT_MATE(60005,"用户签名与操作人不匹配"),
|
||||||
|
|
||||||
|
USERSIGN_IS_EXPIRED(60004,"用户签名已过期"),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private int code;
|
||||||
|
private String error;
|
||||||
|
|
||||||
|
GateWayErrorCode(int code, String error){
|
||||||
|
this.code = code;
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
public int getCode() {
|
||||||
|
return this.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getError() {
|
||||||
|
return this.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.lld.im.common.enums;
|
||||||
|
|
||||||
|
public enum ImConnectStatusEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管道链接状态,1=在线,2=离线。。
|
||||||
|
*/
|
||||||
|
ONLINE_STATUS(1),
|
||||||
|
|
||||||
|
OFFLINE_STATUS(2),
|
||||||
|
;
|
||||||
|
|
||||||
|
private Integer code;
|
||||||
|
|
||||||
|
ImConnectStatusEnum(Integer code){
|
||||||
|
this.code=code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.lld.im.common.enums;
|
||||||
|
|
||||||
|
public enum ImUrlRouteWayEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机
|
||||||
|
*/
|
||||||
|
RAMDOM(1,"com.lld.im.common.route.algorithm.random.RandomHandle"),
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1.轮训
|
||||||
|
*/
|
||||||
|
LOOP(2,"com.lld.im.common.route.algorithm.loop.LoopHandle"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HASH
|
||||||
|
*/
|
||||||
|
HASH(3,"com.lld.im.common.route.algorithm.consistenthash.ConsistentHashHandle"),
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
private int code;
|
||||||
|
private String clazz;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不能用 默认的 enumType b= enumType.values()[i]; 因为本枚举是类形式封装
|
||||||
|
* @param ordinal
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ImUrlRouteWayEnum getHandler(int ordinal) {
|
||||||
|
for (int i = 0; i < ImUrlRouteWayEnum.values().length; i++) {
|
||||||
|
if (ImUrlRouteWayEnum.values()[i].getCode() == ordinal) {
|
||||||
|
return ImUrlRouteWayEnum.values()[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImUrlRouteWayEnum(int code, String clazz){
|
||||||
|
this.code=code;
|
||||||
|
this.clazz=clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClazz() {
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.lld.im.common.enums;
|
||||||
|
|
||||||
|
public enum ImUserTypeEnum {
|
||||||
|
|
||||||
|
IM_USER(1),
|
||||||
|
|
||||||
|
APP_ADMIN(100),
|
||||||
|
;
|
||||||
|
|
||||||
|
private int code;
|
||||||
|
|
||||||
|
ImUserTypeEnum(int code){
|
||||||
|
this.code=code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.lld.im.common.enums;
|
||||||
|
|
||||||
|
import com.lld.im.common.exception.ApplicationExceptionEnum;
|
||||||
|
|
||||||
|
public enum MessageErrorCode implements ApplicationExceptionEnum {
|
||||||
|
|
||||||
|
|
||||||
|
FROMER_IS_MUTE(50002,"发送方被禁言"),
|
||||||
|
|
||||||
|
FROMER_IS_FORBIBBEN(50003,"发送方被禁用"),
|
||||||
|
|
||||||
|
|
||||||
|
MESSAGEBODY_IS_NOT_EXIST(50003,"消息体不存在"),
|
||||||
|
|
||||||
|
MESSAGE_RECALL_TIME_OUT(50004,"消息已超过可撤回时间"),
|
||||||
|
|
||||||
|
MESSAGE_IS_RECALLED(50005,"消息已被撤回"),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private int code;
|
||||||
|
private String error;
|
||||||
|
|
||||||
|
MessageErrorCode(int code, String error){
|
||||||
|
this.code = code;
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
public int getCode() {
|
||||||
|
return this.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getError() {
|
||||||
|
return this.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.lld.im.common.enums;
|
||||||
|
|
||||||
|
public enum RouteHashMethodEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TreeMap
|
||||||
|
*/
|
||||||
|
TREE(1,"com.lld.im.common.route.algorithm.consistenthash" +
|
||||||
|
".TreeMapConsistentHash"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义map
|
||||||
|
*/
|
||||||
|
CUSTOMER(2,"com.lld.im.common.route.algorithm.consistenthash.xxxx"),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
private int code;
|
||||||
|
private String clazz;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不能用 默认的 enumType b= enumType.values()[i]; 因为本枚举是类形式封装
|
||||||
|
* @param ordinal
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static RouteHashMethodEnum getHandler(int ordinal) {
|
||||||
|
for (int i = 0; i < RouteHashMethodEnum.values().length; i++) {
|
||||||
|
if (RouteHashMethodEnum.values()[i].getCode() == ordinal) {
|
||||||
|
return RouteHashMethodEnum.values()[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
RouteHashMethodEnum(int code, String clazz){
|
||||||
|
this.code=code;
|
||||||
|
this.clazz=clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClazz() {
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.lld.im.common.enums.command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
public interface Command {
|
||||||
|
public int getCommand();
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.lld.im.common.enums.command;
|
||||||
|
|
||||||
|
|
||||||
|
public enum CommandType {
|
||||||
|
|
||||||
|
USER("4"),
|
||||||
|
|
||||||
|
FRIEND("3"),
|
||||||
|
|
||||||
|
GROUP("2"),
|
||||||
|
|
||||||
|
MESSAGE("1"),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private String commandType;
|
||||||
|
|
||||||
|
public String getCommandType() {
|
||||||
|
return commandType;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandType(String commandType) {
|
||||||
|
this.commandType = commandType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CommandType getCommandType(String ordinal) {
|
||||||
|
for (int i = 0; i < CommandType.values().length; i++) {
|
||||||
|
if (CommandType.values()[i].getCommandType().equals(ordinal)) {
|
||||||
|
return CommandType.values()[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.lld.im.common.enums.command;
|
||||||
|
|
||||||
|
public enum ConversationEventCommand implements Command {
|
||||||
|
|
||||||
|
//删除会话
|
||||||
|
CONVERSATION_DELETE(5000),
|
||||||
|
|
||||||
|
//删除会话
|
||||||
|
CONVERSATION_UPDATE(5001),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private int command;
|
||||||
|
|
||||||
|
ConversationEventCommand(int command){
|
||||||
|
this.command=command;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCommand() {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package com.lld.im.common.enums.command;
|
||||||
|
|
||||||
|
public enum FriendshipEventCommand implements Command {
|
||||||
|
|
||||||
|
//添加好友
|
||||||
|
FRIEND_ADD(3000),
|
||||||
|
|
||||||
|
//更新好友
|
||||||
|
FRIEND_UPDATE(3001),
|
||||||
|
|
||||||
|
//删除好友
|
||||||
|
FRIEND_DELETE(3002),
|
||||||
|
|
||||||
|
//好友申请
|
||||||
|
FRIEND_REQUEST(3003),
|
||||||
|
|
||||||
|
//好友申请已读
|
||||||
|
FRIEND_REQUEST_READ(3004),
|
||||||
|
|
||||||
|
//好友申请审批
|
||||||
|
FRIEND_REQUEST_APPROVER(3005),
|
||||||
|
|
||||||
|
//添加黑名单
|
||||||
|
FRIEND_BLACK_ADD(3010),
|
||||||
|
|
||||||
|
//移除黑名单
|
||||||
|
FRIEND_BLACK_DELETE(3011),
|
||||||
|
|
||||||
|
//新建好友分组
|
||||||
|
FRIEND_GROUP_ADD(3012),
|
||||||
|
|
||||||
|
//删除好友分组
|
||||||
|
FRIEND_GROUP_DELETE(3013),
|
||||||
|
|
||||||
|
//好友分组添加成员
|
||||||
|
FRIEND_GROUP_MEMBER_ADD(3014),
|
||||||
|
|
||||||
|
//好友分组移除成员
|
||||||
|
FRIEND_GROUP_MEMBER_DELETE(3015),
|
||||||
|
|
||||||
|
//删除所有好友
|
||||||
|
FRIEND_ALL_DELETE(3016),
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private int command;
|
||||||
|
|
||||||
|
FriendshipEventCommand(int command){
|
||||||
|
this.command=command;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCommand() {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package com.lld.im.common.enums.command;
|
||||||
|
|
||||||
|
//2
|
||||||
|
public enum GroupEventCommand implements Command {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送申请入群通知 2023
|
||||||
|
*/
|
||||||
|
JOIN_GROUP(2000),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送添加群成员 2001,通知给所有管理员和本人
|
||||||
|
*/
|
||||||
|
ADDED_MEMBER(2001),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送创建群组通知 2002,通知给所有人
|
||||||
|
*/
|
||||||
|
CREATED_GROUP(2002),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送更新群组通知 2003,通知给所有人
|
||||||
|
*/
|
||||||
|
UPDATED_GROUP(2003),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送退出群组通知 2004,通知给管理员和操作人
|
||||||
|
*/
|
||||||
|
EXIT_GROUP(2004),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送修改群成员通知 2005,通知给管理员和被操作人
|
||||||
|
*/
|
||||||
|
UPDATED_MEMBER(2005),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送删除群成员通知 2006,通知给所有群成员和被踢人
|
||||||
|
*/
|
||||||
|
DELETED_MEMBER(2006),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送解散群通知 2007,通知所有人
|
||||||
|
*/
|
||||||
|
DESTROY_GROUP(2007),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送转让群主 2008,通知所有人
|
||||||
|
*/
|
||||||
|
TRANSFER_GROUP(2008),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁言群 2009,通知所有人
|
||||||
|
*/
|
||||||
|
MUTE_GROUP(2009),
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁言/解禁 群成员 2010,通知管理员和被操作人
|
||||||
|
*/
|
||||||
|
SPEAK_GOUP_MEMBER(2010),
|
||||||
|
|
||||||
|
//群聊消息收发 2104
|
||||||
|
MSG_GROUP(0x838),
|
||||||
|
|
||||||
|
//发送消息已读 2106
|
||||||
|
MSG_GROUP_READED(0x83a),
|
||||||
|
|
||||||
|
//消息已读通知给同步端 2053
|
||||||
|
MSG_GROUP_READED_NOTIFY(0x805),
|
||||||
|
|
||||||
|
//消息已读回执,给原消息发送方 2054
|
||||||
|
MSG_GROUP_READED_RECEIPT(0x806),
|
||||||
|
|
||||||
|
//群聊消息ack 2047
|
||||||
|
GROUP_MSG_ACK(0x7ff),
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private Integer command;
|
||||||
|
|
||||||
|
GroupEventCommand(int command) {
|
||||||
|
this.command = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getCommand() {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.lld.im.common.enums.command;
|
||||||
|
|
||||||
|
public enum MediaEventCommand implements Command {
|
||||||
|
|
||||||
|
//6000 向对方拨打语音 notify ack
|
||||||
|
CALL_VOICE(6000),
|
||||||
|
|
||||||
|
//6001 向对方拨打视频 notify ack
|
||||||
|
CALL_VIDEO(6001),
|
||||||
|
|
||||||
|
//6002 同意请求 notify ack
|
||||||
|
ACCEPT_CALL(6002),
|
||||||
|
|
||||||
|
//6003 同步ice
|
||||||
|
// TRANSMIT_ICE(6003),
|
||||||
|
|
||||||
|
// //6004 发送offer
|
||||||
|
// TRANSMIT_OFFER(6004),
|
||||||
|
|
||||||
|
// //6005 发送ANSWER
|
||||||
|
// TRANSMIT_ANSWER(6005),
|
||||||
|
|
||||||
|
//6006 hangup 挂断 notify ack
|
||||||
|
HANG_UP(6006),
|
||||||
|
|
||||||
|
//6007 拒绝 notify ack
|
||||||
|
REJECT_CALL(6007),
|
||||||
|
|
||||||
|
//6008 取消呼叫 notify ack
|
||||||
|
CANCEL_CALL(6008),
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private Integer command;
|
||||||
|
|
||||||
|
MediaEventCommand(int command) {
|
||||||
|
this.command = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCommand() {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.lld.im.common.enums.command;
|
||||||
|
|
||||||
|
public enum MessageCommand implements Command {
|
||||||
|
|
||||||
|
//单聊消息 1103
|
||||||
|
MSG_P2P(0x44F),
|
||||||
|
|
||||||
|
//单聊消息ACK 1046
|
||||||
|
MSG_ACK(0x416),
|
||||||
|
|
||||||
|
//消息收到ack 1107
|
||||||
|
MSG_RECIVE_ACK(1107),
|
||||||
|
|
||||||
|
//发送消息已读 1106
|
||||||
|
MSG_READED(0x452),
|
||||||
|
|
||||||
|
//消息已读通知给同步端 1053
|
||||||
|
MSG_READED_NOTIFY(0x41D),
|
||||||
|
|
||||||
|
//消息已读回执,给原消息发送方 1054
|
||||||
|
MSG_READED_RECEIPT(0x41E),
|
||||||
|
|
||||||
|
//消息撤回 1050
|
||||||
|
MSG_RECALL(0x41A),
|
||||||
|
|
||||||
|
//消息撤回通知 1052
|
||||||
|
MSG_RECALL_NOTIFY(0x41C),
|
||||||
|
|
||||||
|
//消息撤回回报 1051
|
||||||
|
MSG_RECALL_ACK(0x41B),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private int command;
|
||||||
|
|
||||||
|
MessageCommand(int command){
|
||||||
|
this.command=command;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCommand() {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.lld.im.common.enums.command;
|
||||||
|
|
||||||
|
public enum SystemCommand implements Command {
|
||||||
|
|
||||||
|
//心跳 9999
|
||||||
|
PING(0x270f),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录 9000
|
||||||
|
*/
|
||||||
|
LOGIN(0x2328),
|
||||||
|
|
||||||
|
//登录ack 9001
|
||||||
|
LOGINACK(0x2329),
|
||||||
|
|
||||||
|
//登出 9003
|
||||||
|
LOGOUT(0x232b),
|
||||||
|
|
||||||
|
//下线通知 用于多端互斥 9002
|
||||||
|
MUTUALLOGIN(0x232a),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private int command;
|
||||||
|
|
||||||
|
SystemCommand(int command){
|
||||||
|
this.command=command;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCommand() {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.lld.im.common.enums.command;
|
||||||
|
|
||||||
|
public enum UserEventCommand implements Command {
|
||||||
|
|
||||||
|
//用户修改command 4000
|
||||||
|
USER_MODIFY(4000),
|
||||||
|
|
||||||
|
//4001
|
||||||
|
USER_ONLINE_STATUS_CHANGE(4001),
|
||||||
|
|
||||||
|
|
||||||
|
//4004 用户在线状态通知报文
|
||||||
|
USER_ONLINE_STATUS_CHANGE_NOTIFY(4004),
|
||||||
|
|
||||||
|
//4005 用户在线状态通知同步报文
|
||||||
|
USER_ONLINE_STATUS_CHANGE_NOTIFY_SYNC(4005),
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private int command;
|
||||||
|
|
||||||
|
UserEventCommand(int command){
|
||||||
|
this.command=command;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCommand() {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.lld.im.common.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description:
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class SyncReq extends RequestBase {
|
||||||
|
|
||||||
|
//客户端最大seq
|
||||||
|
private Long lastSequence;
|
||||||
|
//一次拉取多少
|
||||||
|
private Integer maxLimit;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.lld.im.common.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description:
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class SyncResp<T> {
|
||||||
|
|
||||||
|
private Long maxSequence;
|
||||||
|
|
||||||
|
private boolean isCompleted;
|
||||||
|
|
||||||
|
private List<T> dataList;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.lld.im.common.model.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import sun.dc.pr.PRError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CheckSendMessageReq {
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
private Integer appId;
|
||||||
|
|
||||||
|
private Integer command;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.lld.im.common.model.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DoStoreGroupMessageDto {
|
||||||
|
|
||||||
|
private GroupChatMessageContent groupChatMessageContent;
|
||||||
|
|
||||||
|
private ImMessageBody messageBody;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.lld.im.common.model.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DoStoreP2PMessageDto {
|
||||||
|
|
||||||
|
private MessageContent messageContent;
|
||||||
|
|
||||||
|
private ImMessageBody messageBody;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.lld.im.common.model.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class GroupChatMessageContent extends MessageContent {
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
private List<String> memberId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.lld.im.common.model.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ImMessageBody {
|
||||||
|
private Integer appId;
|
||||||
|
|
||||||
|
/** messageBodyId*/
|
||||||
|
private Long messageKey;
|
||||||
|
|
||||||
|
/** messageBody*/
|
||||||
|
private String messageBody;
|
||||||
|
|
||||||
|
private String securityKey;
|
||||||
|
|
||||||
|
private Long messageTime;
|
||||||
|
|
||||||
|
private Long createTime;
|
||||||
|
|
||||||
|
private String extra;
|
||||||
|
|
||||||
|
private Integer delFlag;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.lld.im.common.model.message;
|
||||||
|
|
||||||
|
import com.lld.im.common.model.ClientInfo;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MessageContent extends ClientInfo {
|
||||||
|
|
||||||
|
private String messageId;
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
private String messageBody;
|
||||||
|
|
||||||
|
private Long messageTime;
|
||||||
|
|
||||||
|
private String extra;
|
||||||
|
|
||||||
|
private Long messageKey;
|
||||||
|
|
||||||
|
private long messageSequence;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.lld.im.common.model.message;
|
||||||
|
|
||||||
|
import com.lld.im.common.model.ClientInfo;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MessageReadedContent extends ClientInfo {
|
||||||
|
|
||||||
|
private long messageSequence;
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
private Integer conversationType;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.lld.im.common.model.message;
|
||||||
|
|
||||||
|
import com.lld.im.common.model.ClientInfo;
|
||||||
|
import lombok.Data;
|
||||||
|
import sun.dc.pr.PRError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MessageReciveAckContent extends ClientInfo {
|
||||||
|
|
||||||
|
private Long messageKey;
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
private Long messageSequence;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.lld.im.common.model.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OfflineMessageContent {
|
||||||
|
|
||||||
|
private Integer appId;
|
||||||
|
|
||||||
|
/** messageBodyId*/
|
||||||
|
private Long messageKey;
|
||||||
|
|
||||||
|
/** messageBody*/
|
||||||
|
private String messageBody;
|
||||||
|
|
||||||
|
private Long messageTime;
|
||||||
|
|
||||||
|
private String extra;
|
||||||
|
|
||||||
|
private Integer delFlag;
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
/** 序列号*/
|
||||||
|
private Long messageSequence;
|
||||||
|
|
||||||
|
private String messageRandom;
|
||||||
|
|
||||||
|
private Integer conversationType;
|
||||||
|
|
||||||
|
private String conversationId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.lld.im.common.model.message;
|
||||||
|
|
||||||
|
import com.lld.im.common.model.ClientInfo;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description:
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class RecallMessageContent extends ClientInfo {
|
||||||
|
|
||||||
|
private Long messageKey;
|
||||||
|
|
||||||
|
private String fromId;
|
||||||
|
|
||||||
|
private String toId;
|
||||||
|
|
||||||
|
private Long messageTime;
|
||||||
|
|
||||||
|
private Long messageSequence;
|
||||||
|
|
||||||
|
private Integer conversationType;
|
||||||
|
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "messageKey":419455774914383872,
|
||||||
|
// "fromId":"lld",
|
||||||
|
// "toId":"lld4",
|
||||||
|
// "messageTime":"1665026849851",
|
||||||
|
// "messageSequence":2,
|
||||||
|
// "appId": 10000,
|
||||||
|
// "clientType": 1,
|
||||||
|
// "imei": "web",
|
||||||
|
// "conversationType":0
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.lld.im.common.route;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
public interface RouteHandle {
|
||||||
|
|
||||||
|
public String routeServer(List<String> values,String key);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.lld.im.common.route;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since JDK 1.8
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public final class RouteInfo {
|
||||||
|
|
||||||
|
private String ip;
|
||||||
|
private Integer port;
|
||||||
|
|
||||||
|
public RouteInfo(String ip, Integer port) {
|
||||||
|
this.ip = ip;
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package com.lld.im.common.route.algorithm.consistenthash;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 一致性hash 抽象类
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
public abstract class AbstractConsistentHash {
|
||||||
|
|
||||||
|
//add
|
||||||
|
protected abstract void add(long key,String value);
|
||||||
|
|
||||||
|
//sort
|
||||||
|
protected void sort(){}
|
||||||
|
|
||||||
|
//获取节点 get
|
||||||
|
protected abstract String getFirstNodeValue(String value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理之前事件
|
||||||
|
*/
|
||||||
|
protected abstract void processBefore();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传入节点列表以及客户端信息获取一个服务节点
|
||||||
|
* @param values
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public synchronized String process(List<String> values, String key){
|
||||||
|
processBefore();
|
||||||
|
for (String value : values) {
|
||||||
|
add(hash(value), value);
|
||||||
|
}
|
||||||
|
sort();
|
||||||
|
return getFirstNodeValue(key) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//hash
|
||||||
|
/**
|
||||||
|
* hash 运算
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Long hash(String value){
|
||||||
|
MessageDigest md5;
|
||||||
|
try {
|
||||||
|
md5 = MessageDigest.getInstance("MD5");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("MD5 not supported", e);
|
||||||
|
}
|
||||||
|
md5.reset();
|
||||||
|
byte[] keyBytes = null;
|
||||||
|
try {
|
||||||
|
keyBytes = value.getBytes("UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException("Unknown string :" + value, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
md5.update(keyBytes);
|
||||||
|
byte[] digest = md5.digest();
|
||||||
|
|
||||||
|
// hash code, Truncate to 32-bits
|
||||||
|
long hashCode = ((long) (digest[3] & 0xFF) << 24)
|
||||||
|
| ((long) (digest[2] & 0xFF) << 16)
|
||||||
|
| ((long) (digest[1] & 0xFF) << 8)
|
||||||
|
| (digest[0] & 0xFF);
|
||||||
|
|
||||||
|
long truncateHashCode = hashCode & 0xffffffffL;
|
||||||
|
return truncateHashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.lld.im.common.route.algorithm.consistenthash;
|
||||||
|
|
||||||
|
import com.lld.im.common.route.RouteHandle;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
public class ConsistentHashHandle implements RouteHandle {
|
||||||
|
|
||||||
|
//TreeMap
|
||||||
|
private AbstractConsistentHash hash;
|
||||||
|
|
||||||
|
public void setHash(AbstractConsistentHash hash) {
|
||||||
|
this.hash = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String routeServer(List<String> values, String key) {
|
||||||
|
return hash.process(values,key);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.lld.im.common.route.algorithm.consistenthash;
|
||||||
|
|
||||||
|
import com.lld.im.common.enums.UserErrorCode;
|
||||||
|
import com.lld.im.common.exception.ApplicationException;
|
||||||
|
|
||||||
|
import java.util.SortedMap;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
public class TreeMapConsistentHash extends AbstractConsistentHash {
|
||||||
|
|
||||||
|
private TreeMap<Long,String> treeMap = new TreeMap<>();
|
||||||
|
|
||||||
|
private static final int NODE_SIZE = 2;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void add(long key, String value) {
|
||||||
|
for (int i = 0; i < NODE_SIZE; i++) {
|
||||||
|
treeMap.put(super.hash("node" + key +i),value);
|
||||||
|
}
|
||||||
|
treeMap.put(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFirstNodeValue(String value) {
|
||||||
|
|
||||||
|
Long hash = super.hash(value);
|
||||||
|
SortedMap<Long, String> last = treeMap.tailMap(hash);
|
||||||
|
if(!last.isEmpty()){
|
||||||
|
return last.get(last.firstKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (treeMap.size() == 0){
|
||||||
|
throw new ApplicationException(UserErrorCode.SERVER_NOT_AVAILABLE) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return treeMap.firstEntry().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processBefore() {
|
||||||
|
treeMap.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.lld.im.common.route.algorithm.loop;
|
||||||
|
|
||||||
|
import com.lld.im.common.enums.UserErrorCode;
|
||||||
|
import com.lld.im.common.exception.ApplicationException;
|
||||||
|
import com.lld.im.common.route.RouteHandle;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
public class LoopHandle implements RouteHandle {
|
||||||
|
|
||||||
|
private AtomicLong index = new AtomicLong();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String routeServer(List<String> values, String key) {
|
||||||
|
int size = values.size();
|
||||||
|
if(size == 0){
|
||||||
|
throw new ApplicationException(UserErrorCode.SERVER_NOT_AVAILABLE);
|
||||||
|
}
|
||||||
|
Long l = index.incrementAndGet() % size;
|
||||||
|
if(l < 0){
|
||||||
|
l = 0L;
|
||||||
|
}
|
||||||
|
return values.get(l.intValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.lld.im.common.route.algorithm.random;
|
||||||
|
|
||||||
|
import com.lld.im.common.enums.UserErrorCode;
|
||||||
|
import com.lld.im.common.exception.ApplicationException;
|
||||||
|
import com.lld.im.common.route.RouteHandle;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
public class RandomHandle implements RouteHandle {
|
||||||
|
@Override
|
||||||
|
public String routeServer(List<String> values, String key) {
|
||||||
|
int size = values.size();
|
||||||
|
if(size == 0){
|
||||||
|
throw new ApplicationException(UserErrorCode.SERVER_NOT_AVAILABLE);
|
||||||
|
}
|
||||||
|
int i = ThreadLocalRandom.current().nextInt(size);
|
||||||
|
return values.get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package com.lld.im.common.utils;
|
||||||
|
import sun.misc.BASE64Decoder;
|
||||||
|
import sun.misc.BASE64Encoder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
public class Base64URL {
|
||||||
|
public static byte[] base64EncodeUrl(byte[] input) {
|
||||||
|
byte[] base64 = new BASE64Encoder().encode(input).getBytes();
|
||||||
|
for (int i = 0; i < base64.length; ++i)
|
||||||
|
switch (base64[i]) {
|
||||||
|
case '+':
|
||||||
|
base64[i] = '*';
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
base64[i] = '-';
|
||||||
|
break;
|
||||||
|
case '=':
|
||||||
|
base64[i] = '_';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return base64;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] base64EncodeUrlNotReplace(byte[] input) {
|
||||||
|
byte[] base64 = new BASE64Encoder().encode(input).getBytes(Charset.forName("UTF-8"));
|
||||||
|
for (int i = 0; i < base64.length; ++i)
|
||||||
|
switch (base64[i]) {
|
||||||
|
case '+':
|
||||||
|
base64[i] = '*';
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
base64[i] = '-';
|
||||||
|
break;
|
||||||
|
case '=':
|
||||||
|
base64[i] = '_';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return base64;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] base64DecodeUrlNotReplace(byte[] input) throws IOException {
|
||||||
|
for (int i = 0; i < input.length; ++i)
|
||||||
|
switch (input[i]) {
|
||||||
|
case '*':
|
||||||
|
input[i] = '+';
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
input[i] = '/';
|
||||||
|
break;
|
||||||
|
case '_':
|
||||||
|
input[i] = '=';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return new BASE64Decoder().decodeBuffer(new String(input,"UTF-8"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] base64DecodeUrl(byte[] input) throws IOException {
|
||||||
|
byte[] base64 = input.clone();
|
||||||
|
for (int i = 0; i < base64.length; ++i)
|
||||||
|
switch (base64[i]) {
|
||||||
|
case '*':
|
||||||
|
base64[i] = '+';
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
base64[i] = '/';
|
||||||
|
break;
|
||||||
|
case '_':
|
||||||
|
base64[i] = '=';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return new BASE64Decoder().decodeBuffer(base64.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,278 @@
|
|||||||
|
package com.lld.im.common.utils;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.lld.im.common.config.GlobalHttpClientConfig;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.http.client.config.RequestConfig;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.client.utils.URIBuilder;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description:
|
||||||
|
**/
|
||||||
|
@Component
|
||||||
|
public class HttpRequestUtils {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CloseableHttpClient httpClient;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RequestConfig requestConfig;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
GlobalHttpClientConfig httpClientConfig;
|
||||||
|
|
||||||
|
public String doGet(String url, Map<String, Object> params, String charset) throws Exception {
|
||||||
|
return doGet(url,params,null,charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过给的url地址,获取服务器数据
|
||||||
|
*
|
||||||
|
* @param url 服务器地址
|
||||||
|
* @param params 封装用户参数
|
||||||
|
* @param charset 设定字符编码
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String doGet(String url, Map<String, Object> params, Map<String, Object> header, String charset) throws Exception {
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(charset)) {
|
||||||
|
charset = "utf-8";
|
||||||
|
}
|
||||||
|
URIBuilder uriBuilder = new URIBuilder(url);
|
||||||
|
// 判断是否有参数
|
||||||
|
if (params != null) {
|
||||||
|
// 遍历map,拼接请求参数
|
||||||
|
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
||||||
|
uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 声明 http get 请求
|
||||||
|
HttpGet httpGet = new HttpGet(uriBuilder.build());
|
||||||
|
httpGet.setConfig(requestConfig);
|
||||||
|
|
||||||
|
if (header != null) {
|
||||||
|
// 遍历map,拼接header参数
|
||||||
|
for (Map.Entry<String, Object> entry : header.entrySet()) {
|
||||||
|
httpGet.addHeader(entry.getKey(),entry.getValue().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = "";
|
||||||
|
try {
|
||||||
|
// 发起请求
|
||||||
|
CloseableHttpResponse response = httpClient.execute(httpGet);
|
||||||
|
// 判断状态码是否为200
|
||||||
|
if (response.getStatusLine().getStatusCode() == 200) {
|
||||||
|
// 返回响应体的内容
|
||||||
|
result = EntityUtils.toString(response.getEntity(), charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET请求, 含URL 参数
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @param params
|
||||||
|
* @return 如果状态码为200,则返回body,如果不为200,则返回null
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public String doGet(String url, Map<String, Object> params) throws Exception {
|
||||||
|
return doGet(url, params, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET 请求,不含URL参数
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public String doGet(String url) throws Exception {
|
||||||
|
return doGet(url, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String doPost(String url, Map<String, Object> params, String jsonBody, String charset) throws Exception {
|
||||||
|
return doPost(url,params,null,jsonBody,charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 带参数的post请求
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public String doPost(String url, Map<String, Object> params, Map<String, Object> header, String jsonBody, String charset) throws Exception {
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(charset)) {
|
||||||
|
charset = "utf-8";
|
||||||
|
}
|
||||||
|
URIBuilder uriBuilder = new URIBuilder(url);
|
||||||
|
// 判断是否有参数
|
||||||
|
if (params != null) {
|
||||||
|
// 遍历map,拼接请求参数
|
||||||
|
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
||||||
|
uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 声明httpPost请求
|
||||||
|
HttpPost httpPost = new HttpPost(uriBuilder.build());
|
||||||
|
// 加入配置信息
|
||||||
|
httpPost.setConfig(requestConfig);
|
||||||
|
|
||||||
|
// 判断map是否为空,不为空则进行遍历,封装from表单对象
|
||||||
|
if (StringUtils.isNotEmpty(jsonBody)) {
|
||||||
|
StringEntity s = new StringEntity(jsonBody, charset);
|
||||||
|
s.setContentEncoding(charset);
|
||||||
|
s.setContentType("application/json");
|
||||||
|
|
||||||
|
// 把json body放到post里
|
||||||
|
httpPost.setEntity(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header != null) {
|
||||||
|
// 遍历map,拼接header参数
|
||||||
|
for (Map.Entry<String, Object> entry : header.entrySet()) {
|
||||||
|
httpPost.addHeader(entry.getKey(),entry.getValue().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = "";
|
||||||
|
// CloseableHttpClient httpClient = HttpClients.createDefault(); // 单个
|
||||||
|
CloseableHttpResponse response = null;
|
||||||
|
try {
|
||||||
|
// 发起请求
|
||||||
|
response = httpClient.execute(httpPost);
|
||||||
|
// 判断状态码是否为200
|
||||||
|
if (response.getStatusLine().getStatusCode() == 200) {
|
||||||
|
// 返回响应体的内容
|
||||||
|
result = EntityUtils.toString(response.getEntity(), charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不带参数post请求
|
||||||
|
* @param url
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public String doPost(String url) throws Exception {
|
||||||
|
return doPost(url, null,null,null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get 方法调用的通用方式
|
||||||
|
* @param url
|
||||||
|
* @param tClass
|
||||||
|
* @param map
|
||||||
|
* @param charSet
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public <T> T doGet(String url, Class<T> tClass, Map<String, Object> map, String charSet) throws Exception {
|
||||||
|
|
||||||
|
String result = doGet(url, map, charSet);
|
||||||
|
if (StringUtils.isNotEmpty(result))
|
||||||
|
return JSON.parseObject(result, tClass);
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get 方法调用的通用方式
|
||||||
|
* @param url
|
||||||
|
* @param tClass
|
||||||
|
* @param map
|
||||||
|
* @param charSet
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public <T> T doGet(String url, Class<T> tClass, Map<String, Object> map, Map<String, Object> header, String charSet) throws Exception {
|
||||||
|
|
||||||
|
String result = doGet(url, map, header, charSet);
|
||||||
|
if (StringUtils.isNotEmpty(result))
|
||||||
|
return JSON.parseObject(result, tClass);
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post 方法调用的通用方式
|
||||||
|
* @param url
|
||||||
|
* @param tClass
|
||||||
|
* @param map
|
||||||
|
* @param jsonBody
|
||||||
|
* @param charSet
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public <T> T doPost(String url, Class<T> tClass, Map<String, Object> map, String jsonBody, String charSet) throws Exception {
|
||||||
|
|
||||||
|
String result = doPost(url, map,jsonBody,charSet);
|
||||||
|
if (StringUtils.isNotEmpty(result))
|
||||||
|
return JSON.parseObject(result, tClass);
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T doPost(String url, Class<T> tClass, Map<String, Object> map, Map<String, Object> header, String jsonBody, String charSet) throws Exception {
|
||||||
|
|
||||||
|
String result = doPost(url, map, header,jsonBody,charSet);
|
||||||
|
if (StringUtils.isNotEmpty(result))
|
||||||
|
return JSON.parseObject(result, tClass);
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post 方法调用的通用方式
|
||||||
|
* @param url
|
||||||
|
* @param map
|
||||||
|
* @param jsonBody
|
||||||
|
* @param charSet
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public String doPostString(String url, Map<String, Object> map, String jsonBody, String charSet) throws Exception {
|
||||||
|
return doPost(url, map,jsonBody,charSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post 方法调用的通用方式
|
||||||
|
* @param url
|
||||||
|
* @param map
|
||||||
|
* @param jsonBody
|
||||||
|
* @param charSet
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public String doPostString(String url, Map<String, Object> map, Map<String, Object> header, String jsonBody, String charSet) throws Exception {
|
||||||
|
return doPost(url, map, header, jsonBody,charSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.lld.im.common.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lld.im.common.BaseErrorCode;
|
||||||
|
import com.lld.im.common.exception.ApplicationException;
|
||||||
|
import com.lld.im.common.route.RouteInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @since JDK 1.8
|
||||||
|
*/
|
||||||
|
public class RouteInfoParseUtil {
|
||||||
|
|
||||||
|
public static RouteInfo parse(String info){
|
||||||
|
try {
|
||||||
|
String[] serverInfo = info.split(":");
|
||||||
|
RouteInfo routeInfo = new RouteInfo(serverInfo[0], Integer.parseInt(serverInfo[1])) ;
|
||||||
|
return routeInfo ;
|
||||||
|
}catch (Exception e){
|
||||||
|
throw new ApplicationException(BaseErrorCode.PARAMETER_ERROR) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
package com.lld.im.common.utils;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.zip.Deflater;
|
||||||
|
import java.util.zip.Inflater;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: app用户 后台管理员
|
||||||
|
*
|
||||||
|
* 10000 xxx 10001 bbbb
|
||||||
|
* @author: lld
|
||||||
|
* @version: 1.0
|
||||||
|
*/
|
||||||
|
public class SigAPI {
|
||||||
|
final private long appId;
|
||||||
|
final private String key;
|
||||||
|
|
||||||
|
public SigAPI(long appId, String key) {
|
||||||
|
this.appId = appId;
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
SigAPI asd = new SigAPI(10000, "123456");
|
||||||
|
String sign = asd.genUserSig("lld", 100000000);
|
||||||
|
// Thread.sleep(2000L);
|
||||||
|
JSONObject jsonObject = decodeUserSig(sign);
|
||||||
|
System.out.println("sign:" + sign);
|
||||||
|
System.out.println("decoder:" + jsonObject.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 解密方法
|
||||||
|
* @param
|
||||||
|
* @return com.alibaba.fastjson.JSONObject
|
||||||
|
* @author lld
|
||||||
|
*/
|
||||||
|
public static JSONObject decodeUserSig(String userSig) {
|
||||||
|
JSONObject sigDoc = new JSONObject(true);
|
||||||
|
try {
|
||||||
|
byte[] decodeUrlByte = Base64URL.base64DecodeUrlNotReplace(userSig.getBytes());
|
||||||
|
byte[] decompressByte = decompress(decodeUrlByte);
|
||||||
|
String decodeText = new String(decompressByte, "UTF-8");
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(decodeText)) {
|
||||||
|
sigDoc = JSONObject.parseObject(decodeText);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return sigDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解压缩
|
||||||
|
*
|
||||||
|
* @param data 待压缩的数据
|
||||||
|
* @return byte[] 解压缩后的数据
|
||||||
|
*/
|
||||||
|
public static byte[] decompress(byte[] data) {
|
||||||
|
byte[] output = new byte[0];
|
||||||
|
|
||||||
|
Inflater decompresser = new Inflater();
|
||||||
|
decompresser.reset();
|
||||||
|
decompresser.setInput(data);
|
||||||
|
|
||||||
|
ByteArrayOutputStream o = new ByteArrayOutputStream(data.length);
|
||||||
|
try {
|
||||||
|
byte[] buf = new byte[1024];
|
||||||
|
while (!decompresser.finished()) {
|
||||||
|
int i = decompresser.inflate(buf);
|
||||||
|
o.write(buf, 0, i);
|
||||||
|
}
|
||||||
|
output = o.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
output = data;
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
o.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decompresser.end();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【功能说明】用于签发 IM 服务中必须要使用的 UserSig 鉴权票据
|
||||||
|
* <p>
|
||||||
|
* 【参数说明】
|
||||||
|
*/
|
||||||
|
public String genUserSig(String userid, long expire) {
|
||||||
|
return genUserSig(userid, expire, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String hmacsha256(String identifier, long currTime, long expire, String base64Userbuf) {
|
||||||
|
String contentToBeSigned = "TLS.identifier:" + identifier + "\n"
|
||||||
|
+ "TLS.appId:" + appId + "\n"
|
||||||
|
+ "TLS.expireTime:" + currTime + "\n"
|
||||||
|
+ "TLS.expire:" + expire + "\n";
|
||||||
|
if (null != base64Userbuf) {
|
||||||
|
contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
byte[] byteKey = key.getBytes(StandardCharsets.UTF_8);
|
||||||
|
Mac hmac = Mac.getInstance("HmacSHA256");
|
||||||
|
SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");
|
||||||
|
hmac.init(keySpec);
|
||||||
|
byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return (Base64.getEncoder().encodeToString(byteSig)).replaceAll("\\s*", "");
|
||||||
|
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String genUserSig(String userid, long expire, byte[] userbuf) {
|
||||||
|
|
||||||
|
long currTime = System.currentTimeMillis() / 1000;
|
||||||
|
|
||||||
|
JSONObject sigDoc = new JSONObject();
|
||||||
|
sigDoc.put("TLS.identifier", userid);
|
||||||
|
sigDoc.put("TLS.appId", appId);
|
||||||
|
sigDoc.put("TLS.expire", expire);
|
||||||
|
sigDoc.put("TLS.expireTime", currTime);
|
||||||
|
|
||||||
|
String base64UserBuf = null;
|
||||||
|
if (null != userbuf) {
|
||||||
|
base64UserBuf = Base64.getEncoder().encodeToString(userbuf).replaceAll("\\s*", "");
|
||||||
|
sigDoc.put("TLS.userbuf", base64UserBuf);
|
||||||
|
}
|
||||||
|
String sig = hmacsha256(userid, currTime, expire, base64UserBuf);
|
||||||
|
if (sig.length() == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
sigDoc.put("TLS.sig", sig);
|
||||||
|
Deflater compressor = new Deflater();
|
||||||
|
compressor.setInput(sigDoc.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
compressor.finish();
|
||||||
|
byte[] compressedBytes = new byte[2048];
|
||||||
|
int compressedBytesLength = compressor.deflate(compressedBytes);
|
||||||
|
compressor.end();
|
||||||
|
return (new String(Base64URL.base64EncodeUrl(Arrays.copyOfRange(compressedBytes,
|
||||||
|
0, compressedBytesLength)))).replaceAll("\\s*", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String genUserSig(String userid, long expire, long time,byte [] userbuf) {
|
||||||
|
|
||||||
|
JSONObject sigDoc = new JSONObject();
|
||||||
|
sigDoc.put("TLS.identifier", userid);
|
||||||
|
sigDoc.put("TLS.appId", appId);
|
||||||
|
sigDoc.put("TLS.expire", expire);
|
||||||
|
sigDoc.put("TLS.expireTime", time);
|
||||||
|
|
||||||
|
String base64UserBuf = null;
|
||||||
|
if (null != userbuf) {
|
||||||
|
base64UserBuf = Base64.getEncoder().encodeToString(userbuf).replaceAll("\\s*", "");
|
||||||
|
sigDoc.put("TLS.userbuf", base64UserBuf);
|
||||||
|
}
|
||||||
|
String sig = hmacsha256(userid, time, expire, base64UserBuf);
|
||||||
|
if (sig.length() == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
sigDoc.put("TLS.sig", sig);
|
||||||
|
Deflater compressor = new Deflater();
|
||||||
|
compressor.setInput(sigDoc.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
compressor.finish();
|
||||||
|
byte[] compressedBytes = new byte[2048];
|
||||||
|
int compressedBytesLength = compressor.deflate(compressedBytes);
|
||||||
|
compressor.end();
|
||||||
|
return (new String(Base64URL.base64EncodeUrl(Arrays.copyOfRange(compressedBytes,
|
||||||
|
0, compressedBytesLength)))).replaceAll("\\s*", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
72
hs-im-server/im-message-store/pom.xml
Normal file
72
hs-im-server/im-message-store/pom.xml
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.lld</groupId>
|
||||||
|
<artifactId>im-system</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>im-message-store</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<!-- rabbitmq -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--MySQL JDBC驱动 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--MySQL -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- mybatis plus -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.jeffreyning</groupId>
|
||||||
|
<artifactId>mybatisplus-plus</artifactId>
|
||||||
|
<version>1.5.1-RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- common -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lld</groupId>
|
||||||
|
<artifactId>common</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user