├── .deepsource.toml ├── .gitignore ├── LICENSE ├── LICENSE_CN ├── MyGenerate POJOs.groovy ├── README.md ├── him-api ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── lmxdawn │ │ │ └── him │ │ │ └── api │ │ │ ├── HimApiApplication.java │ │ │ ├── annotation │ │ │ └── CheckLoginAnnotation.java │ │ │ ├── config │ │ │ ├── CorsConfig.java │ │ │ ├── DruidStatFilter.java │ │ │ ├── DruidStatViewServlet.java │ │ │ ├── OkHttpConfig.java │ │ │ └── PublicFileUrlConfig.java │ │ │ ├── constant │ │ │ ├── WSMsgTypeConstant.java │ │ │ ├── WSReqTypeConstant.java │ │ │ └── WSResTypeConstant.java │ │ │ ├── controller │ │ │ ├── HelloController.java │ │ │ ├── group │ │ │ │ ├── GroupIndexController.java │ │ │ │ ├── GroupMsgController.java │ │ │ │ └── GroupUserController.java │ │ │ └── user │ │ │ │ ├── UserFriendAskController.java │ │ │ │ ├── UserFriendController.java │ │ │ │ ├── UserFriendMsgController.java │ │ │ │ ├── UserIndexController.java │ │ │ │ └── UserLoginController.java │ │ │ ├── dao │ │ │ ├── group │ │ │ │ ├── GroupDao.java │ │ │ │ ├── GroupMsgDao.java │ │ │ │ └── GroupUserDao.java │ │ │ └── user │ │ │ │ ├── UserDao.java │ │ │ │ ├── UserFriendAskDao.java │ │ │ │ ├── UserFriendDao.java │ │ │ │ ├── UserFriendMsgDao.java │ │ │ │ ├── UserProfileDao.java │ │ │ │ └── UserQqDao.java │ │ │ ├── dto │ │ │ └── UserLoginDTO.java │ │ │ ├── exception │ │ │ └── JsonException.java │ │ │ ├── filter │ │ │ └── CorsFilter.java │ │ │ ├── handler │ │ │ └── GlobalExceptionHandler.java │ │ │ ├── service │ │ │ ├── group │ │ │ │ ├── GroupMsgService.java │ │ │ │ ├── GroupService.java │ │ │ │ ├── GroupUserService.java │ │ │ │ └── impl │ │ │ │ │ ├── GroupMsgServiceImpl.java │ │ │ │ │ ├── GroupServiceImpl.java │ │ │ │ │ └── GroupUserServiceImpl.java │ │ │ ├── other │ │ │ │ ├── QqWebAuthService.java │ │ │ │ └── impl │ │ │ │ │ └── QqWebAuthServiceImpl.java │ │ │ └── user │ │ │ │ ├── UserFriendAskService.java │ │ │ │ ├── UserFriendMsgService.java │ │ │ │ ├── UserFriendService.java │ │ │ │ ├── UserProfileService.java │ │ │ │ ├── UserQqService.java │ │ │ │ ├── UserService.java │ │ │ │ └── impl │ │ │ │ ├── UserFriendAskServiceImpl.java │ │ │ │ ├── UserFriendMsgServiceImpl.java │ │ │ │ ├── UserFriendServiceImpl.java │ │ │ │ ├── UserProfileServiceImpl.java │ │ │ │ ├── UserQqServiceImpl.java │ │ │ │ └── UserServiceImpl.java │ │ │ ├── utils │ │ │ ├── CacheUtils.java │ │ │ ├── GroupUserUtils.java │ │ │ ├── JwtUtils.java │ │ │ ├── OkHttpUtil.java │ │ │ ├── PageUtils.java │ │ │ ├── PasswordUtils.java │ │ │ ├── PublicFileUtils.java │ │ │ ├── SpringBeanFactoryUtils.java │ │ │ ├── UserFriendUtils.java │ │ │ ├── UserLoginUtils.java │ │ │ └── WSBaseReqUtils.java │ │ │ ├── vo │ │ │ ├── req │ │ │ │ ├── GroupMsgCreateReqVO.java │ │ │ │ ├── GroupSaveReqVO.java │ │ │ │ ├── GroupUserListReqVO.java │ │ │ │ ├── GroupUserSaveReqVO.java │ │ │ │ ├── UserFriendAskAckReqVO.java │ │ │ │ ├── UserFriendDeleteReqVO.java │ │ │ │ ├── UserFriendMsgClearMsgCountReqVO.java │ │ │ │ ├── UserFriendMsgSaveReqVO.java │ │ │ │ ├── UserGroupListReqVO.java │ │ │ │ ├── UserLoginPwdReqVO.java │ │ │ │ ├── WSBaseReqVO.java │ │ │ │ ├── WSMessageReqVO.java │ │ │ │ └── WSUserReqVO.java │ │ │ └── res │ │ │ │ ├── GroupIndexListResVO.java │ │ │ │ ├── GroupMsgListResVO.java │ │ │ │ ├── GroupUserListResVO.java │ │ │ │ ├── QqOpenIdResVO.java │ │ │ │ ├── QqUserInfoResVO.java │ │ │ │ ├── UserFriendAskListResVO.java │ │ │ │ ├── UserFriendListInfoResVO.java │ │ │ │ ├── UserInfoListResVO.java │ │ │ │ ├── UserInfoResVO.java │ │ │ │ ├── UserLoginResVO.java │ │ │ │ ├── UserProfileInfoResVO.java │ │ │ │ └── UserReadResVO.java │ │ │ └── ws │ │ │ ├── WSServer.java │ │ │ ├── WSServerHandler.java │ │ │ ├── WSServerInitializer.java │ │ │ └── WSSocketHolder.java │ └── resources │ │ ├── application-dev.properties │ │ ├── application-pro.properties │ │ ├── application-test.properties │ │ ├── application.properties │ │ ├── mybatis │ │ ├── mapper │ │ │ ├── group │ │ │ │ ├── GroupDao.xml │ │ │ │ ├── GroupMsgDao.xml │ │ │ │ └── GroupUserDao.xml │ │ │ └── user │ │ │ │ ├── UserDao.xml │ │ │ │ ├── UserFriendAskDao.xml │ │ │ │ ├── UserFriendDao.xml │ │ │ │ ├── UserFriendMsgDao.xml │ │ │ │ ├── UserProfileDao.xml │ │ │ │ └── UserQqDao.xml │ │ └── mybatis-config.xml │ │ ├── static │ │ └── favicon.ico │ │ └── templates │ │ └── .gitignore │ └── test │ └── java │ └── com │ └── lmxdawn │ └── him │ └── api │ ├── BaseApplicationTest.java │ └── service │ ├── group │ └── impl │ │ └── GroupServiceImplTest.java │ └── user │ └── impl │ ├── UserFriendMsgServiceImplTest.java │ └── UserFriendServiceImplTest.java ├── him-common ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── lmxdawn │ │ │ └── him │ │ │ └── common │ │ │ ├── constant │ │ │ ├── CookieConstant.java │ │ │ └── RedisConstant.java │ │ │ ├── converter │ │ │ └── OrderForm2OrderDTOConverter.java │ │ │ ├── entity │ │ │ ├── group │ │ │ │ ├── Group.java │ │ │ │ ├── GroupMsg.java │ │ │ │ └── GroupUser.java │ │ │ └── user │ │ │ │ ├── User.java │ │ │ │ ├── UserFriend.java │ │ │ │ ├── UserFriendAsk.java │ │ │ │ ├── UserFriendMsg.java │ │ │ │ ├── UserProfile.java │ │ │ │ └── UserQq.java │ │ │ ├── enums │ │ │ └── ResultEnum.java │ │ │ ├── protobuf │ │ │ ├── WSBaseReqProtoOuterClass.java │ │ │ ├── WSBaseResProtoOuterClass.java │ │ │ ├── WSMessageResProtoOuterClass.java │ │ │ └── WSUserResProtoOuterClass.java │ │ │ ├── utils │ │ │ └── ResultVOUtils.java │ │ │ └── vo │ │ │ ├── req │ │ │ ├── BaseLimitReqVO.java │ │ │ └── BaseReqVO.java │ │ │ └── res │ │ │ └── BaseResVO.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── lmxdawn │ └── him │ └── common │ └── .gitignore ├── pom.xml ├── protocol ├── README.md ├── WSBaseReqProto.proto ├── WSBaseResProto.proto ├── WSMessageResProto.proto ├── WSUserResProto.proto ├── proto.bat ├── proto.sh └── 说明文档.txt └── scripts └── him.sql /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[analyzers]] 4 | name = "shell" 5 | enabled = true 6 | 7 | [[analyzers]] 8 | name = "java" 9 | enabled = true 10 | 11 | [analyzers.meta] 12 | runtime_version = "8" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2 | 3 | "Anti 996" License Version 1.0 (Draft) 4 | 5 | Permission is hereby granted to any individual or legal entity 6 | obtaining a copy of this licensed work (including the source code, 7 | documentation and/or related items, hereinafter collectively referred 8 | to as the "licensed work"), free of charge, to deal with the licensed 9 | work for any purpose, including without limitation, the rights to use, 10 | reproduce, modify, prepare derivative works of, distribute, publish 11 | and sublicense the licensed work, subject to the following conditions: 12 | 13 | 1. The individual or the legal entity must conspicuously display, 14 | without modification, this License and the notice on each redistributed 15 | or derivative copy of the Licensed Work. 16 | 17 | 2. The individual or the legal entity must strictly comply with all 18 | applicable laws, regulations, rules and standards of the jurisdiction 19 | relating to labor and employment where the individual is physically 20 | located or where the individual was born or naturalized; or where the 21 | legal entity is registered or is operating (whichever is stricter). In 22 | case that the jurisdiction has no such laws, regulations, rules and 23 | standards or its laws, regulations, rules and standards are 24 | unenforceable, the individual or the legal entity are required to 25 | comply with Core International Labor Standards. 26 | 27 | 3. The individual or the legal entity shall not induce, suggest or force 28 | its employee(s), whether full-time or part-time, or its independent 29 | contractor(s), in any methods, to agree in oral or written form, to 30 | directly or indirectly restrict, weaken or relinquish his or her 31 | rights or remedies under such laws, regulations, rules and standards 32 | relating to labor and employment as mentioned above, no matter whether 33 | such written or oral agreements are enforceable under the laws of the 34 | said jurisdiction, nor shall such individual or the legal entity 35 | limit, in any methods, the rights of its employee(s) or independent 36 | contractor(s) from reporting or complaining to the copyright holder or 37 | relevant authorities monitoring the compliance of the license about 38 | its violation(s) of the said license. 39 | 40 | THE LICENSED WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 41 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 42 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 43 | IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, 44 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 45 | OTHERWISE, ARISING FROM, OUT OF OR IN ANY WAY CONNECTION WITH THE 46 | LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK. 47 | -------------------------------------------------------------------------------- /LICENSE_CN: -------------------------------------------------------------------------------- 1 | 版权所有(c)<年份><版权持有人> 2 | 3 | 反996许可证版本1.0 4 | 5 | 在符合下列条件的情况下,特此免费向任何得到本授权作品的副本(包括源代码、文件和/或相关内容,以 6 | 下统称为“授权作品”)的个人和法人实体授权:被授权个人或法人实体有权以任何目的处置授权作品,包括 7 | 但不限于使用、复制,修改,衍生利用、散布,发布和再许可: 8 | 9 | 1. 个人或法人实体必须在许可作品的每个再散布或衍生副本上包含以上版权声明和本许可证,不得自行修 10 | 改。 11 | 2. 个人或法人实体必须严格遵守与个人实际所在地或个人出生地或归化地、或法人实体注册地或经营地( 12 | 以较严格者为准)的司法管辖区所有适用的与劳动和就业相关法律、法规、规则和标准。如果该司法管辖区 13 | 没有此类法律、法规、规章和标准或其法律、法规、规章和标准不可执行,则个人或法人实体必须遵守国际 14 | 劳工标准的核心公约。 15 | 3. 个人或法人不得以任何方式诱导、暗示或强迫其全职或兼职员工或其独立承包人以口头或书面形式同意 16 | 直接或间接限制、削弱或放弃其所拥有的,受相关与劳动和就业有关的法律、法规、规则和标准保护的权利 17 | 或补救措施,无论该等书面或口头协议是否被该司法管辖区的法律所承认,该等个人或法人实体也不得以任 18 | 何方法限制其雇员或独立承包人向版权持有人或监督许可证合规情况的有关当局报告或投诉上述违反许可证 19 | 的行为的权利。 20 | 21 | 该授权作品是"按原样"提供,不做任何明示或暗示的保证,包括但不限于对适销性、特定用途适用性和非侵 22 | 权性的保证。在任何情况下,无论是在合同诉讼、侵权诉讼或其他诉讼中,版权持有人均不承担因本软件或 23 | 本软件的使用或其他交易而产生、引起或与之相关的任何索赔、损害或其他责任。 24 | -------------------------------------------------------------------------------- /MyGenerate POJOs.groovy: -------------------------------------------------------------------------------- 1 | import com.intellij.database.model.DasTable 2 | import com.intellij.database.util.Case 3 | import com.intellij.database.util.DasUtil 4 | 5 | /* 6 | * Available context bindings: 7 | * SELECTION Iterable 8 | * PROJECT project 9 | * FILES files helper 10 | */ 11 | 12 | packageName = "" 13 | typeMapping = [ 14 | (~/(?i)bigint/) : "Long", 15 | (~/(?i)int|tinyint/) : "Integer", 16 | (~/(?i)float|double|decimal|real/) : "Double", 17 | (~/(?i)datetime|timestamp|date|time/) : "Date", 18 | (~/(?i)/) : "String" 19 | ] 20 | 21 | FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir -> 22 | SELECTION.filter { it instanceof DasTable }.each { generate(it, dir) } 23 | } 24 | 25 | def generate(table, dir) { 26 | def className = javaName(table.getName(), true) 27 | def fields = calcFields(table) 28 | packageName = getPackageName(dir) 29 | PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(new File(dir, className + ".java")), "UTF-8")) 30 | printWriter.withPrintWriter {out -> generate(out, className, fields,table)} 31 | } 32 | 33 | // 获取包所在文件夹路径 34 | def getPackageName(dir) { 35 | return dir.toString().replaceAll("\\\\", ".").replaceAll("/", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "") + ";" 36 | } 37 | 38 | def generate(out, className, fields, table) { 39 | out.println "package $packageName" 40 | out.println "" 41 | out.println "import lombok.Data;" 42 | Set types = new HashSet() 43 | 44 | fields.each() { 45 | types.add(it.type) 46 | } 47 | 48 | if (types.contains("Date")) { 49 | out.println "" 50 | out.println "import java.util.Date;" 51 | } 52 | 53 | out.println "" 54 | out.println "/**\n" + 55 | " * ${table} \n" + 56 | " */" 57 | out.println "@Data" 58 | out.println "public class $className {" 59 | out.println "" 60 | fields.each() {// 输出注释 61 | if (isNotEmpty(it.commoent)) { 62 | out.println "\t/**" 63 | out.println " \t* ${it.commoent.toString()}" 64 | out.println " \t*/" 65 | } 66 | if (it.annos != "") out.println " ${it.annos}" 67 | out.println "\tprivate ${it.type} ${it.name};" 68 | } 69 | out.println "" 70 | // fields.each() { 71 | // out.println "" 72 | // out.println " public ${it.type} get${it.name.capitalize()}() {" 73 | // out.println " return ${it.name};" 74 | // out.println " }" 75 | // out.println "" 76 | // out.println " public void set${it.name.capitalize()}(${it.type} ${it.name}) {" 77 | // out.println " this.${it.name} = ${it.name};" 78 | // out.println " }" 79 | // out.println "" 80 | // } 81 | out.println "}" 82 | } 83 | 84 | def calcFields(table) { 85 | DasUtil.getColumns(table).reduce([]) { fields, col -> 86 | def spec = Case.LOWER.apply(col.getDataType().getSpecification()) 87 | 88 | def typeStr = typeMapping.find { p, t -> p.matcher(spec).find() }.value 89 | fields += [[ 90 | name : javaName(col.getName(), false), 91 | type : typeStr, 92 | commoent: col.getComment(), 93 | annos: ""]] 94 | } 95 | } 96 | 97 | def isNotEmpty(content) { 98 | return content != null && content.toString().trim().length() > 0 99 | } 100 | 101 | def javaName(str, capitalize) { 102 | def s = com.intellij.psi.codeStyle.NameUtil.splitNameIntoWords(str) 103 | .collect { Case.LOWER.apply(it).capitalize() } 104 | .join("") 105 | .replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_") 106 | capitalize || s.length() == 1? s : Case.LOWER.apply(s[0]) + s[1..-1] 107 | } 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |
3 |

4 | 5 | [![him-vue](https://github.com/lmxdawn/him-vue/raw/master/pic/him.jpg)](http://him-netty.await.fun/h5) 6 | 7 | 8 |

9 |

10 | 11 | [![him-vue](https://img.shields.io/badge/him-him--vue-1.svg)](https://github.com/lmxdawn/him-vue) 12 | [![him-netty](https://img.shields.io/badge/him-him--netty-1.svg)](https://github.com/lmxdawn/him-netty) 13 | [![QQ群](https://img.shields.io/badge/QQ%E7%BE%A4-210277856-orange.svg)](https://shang.qq.com/wpa/qunwpa?idkey=d4965fc7101936dcdea5eb1d05e2eaeb3128f20796028ee937ab516652083c6c) 14 | [![](https://badge.juejin.im/entry/5cd6be3ae51d456e5b66ae3d/likes.svg?style=flat-square)](https://juejin.im/post/5cd6be3ae51d456e5b66ae3d) 15 | 16 |

17 | 18 |

19 | 20 | [![vue](https://img.shields.io/badge/vue-2.x-1.svg)](https://github.com/vuejs/vue) 21 | [![netty](https://img.shields.io/badge/netty-4.1.25.Final-1.svg)](https://github.com/netty/netty) 22 | [![spring-boot](https://img.shields.io/badge/spring--boot-2.1.2.RELEASE-1.svg)](https://github.com/spring-projects/spring-boot) 23 | 24 |

25 |
26 | 27 | # him-netty 28 | 29 | > 使用前先阅读**开源协议**: [中文版](https://github.com/lmxdawn/him-netty/LICENSE_CN) , [English version](https://github.com/lmxdawn/him-netty/LICENSE) , 协议出处 [Anti-996-License-1.0](https://github.com/kattgu7/Anti-996-License) 30 | 31 | > 前端:vue [前往](https://github.com/lmxdawn/him-vue) ,服务端 netty [前往](https://github.com/lmxdawn/him-netty) 32 | 33 | # 踩坑指南 34 | 35 | > * 1. iOS版本手机QQ中清空不了 Cookie 的bug (Android 版本的QQ没试), 其它浏览器均正常 36 | 37 | > * 2. 手机微信中打开后点击输入文字后, 不管点不点击发送按钮都会出现短暂的不能点击的现象(任何按钮都不能点击), 后来发现是因为在微信里面, 输入法把 输入框顶上去了, 然后输入法隐藏后输入框还在上面!!!! [点击查看详情](https://developers.weixin.qq.com/community/develop/doc/00040a43cd4290dedbc7e7f1851400) 38 | 。找到一个解决输入框的方法: @blur="chatTextBlur" 监听失去焦点的事件(vue 写法), 然后在事件里面执行 `window.scroll(0, 0);` 39 | 40 | > * 3. 因为设置了定位,`overflow: scroll` 原生滚动,iOS下会不流畅,解决办法:换成 `-webkit-overflow-scrolling: touch;` 41 | 42 | # 功能列表 43 | * [x] 单聊 44 | * [x] 群聊 45 | * [x] protobuf 编解码 46 | * [x] 客户端心跳 47 | * [x] 客户端断开重连 48 | * [x] 异地登录, 通知下线 49 | * [x] 移动端/PC端适配 50 | * [x] 离线消息 (消息通过 ack 机制, 实现可达性) 51 | * [x] 第三方QQ登录 52 | * [x] 自带 emoji 表情 53 | * [x] 文本消息 54 | * [ ] 声音提示 55 | * [ ] 图片消息 56 | * [ ] 音频消息 57 | * [ ] 视屏消息 58 | * [ ] 分布式部署 59 | * [ ] PHP 版本的 (Workerman 版本) 60 | 61 | 62 | # 环境要求 63 | 64 | ## git 65 | > 这个版本管理肯定需要安装的 66 | 67 | ## jdk 68 | > JDK 8 69 | 70 | ## maven 71 | > 3.6.1 72 | 73 | ## spring boot 74 | > 2.1.2 75 | 76 | ## 下载 77 | 78 | > git clone https://github.com/lmxdawn/him-netty.git 79 | 80 | > cd him-netty 81 | 82 | ## SQL的导入 83 | 84 | > 创建数据库,名称: him, 把 根目录下 scripts 里面的 him.sql 导入进去 85 | 86 | ## 打包 87 | 88 | > mvn -Dmaven.test.skip=true clean package 89 | 90 | > java -jar him-api/target/him-api-0.0.1-SNAPSHOT.jar 91 | 92 | > 如果要加环境配置 --spring.profiles.active=pro 即可, 默认是 dev 环境。 93 | **特别要注意:配置文件里面有跨域配置,这个一定要注意** 94 | 95 | him-vue [前往](https://github.com/lmxdawn/him-vue) 和 him-netty [前往](https://github.com/lmxdawn/him-netty) 都启动后访问 http://localhost:8080 96 | 97 | 注意默认使用 QQ登录, 这个需要去申请QQ互联, 如果不想去申请, 则可以直接设置 Cookie, 两个值 UID 和 SID, 这两个值可以通过接口 /api/user/login/byPwd 获取, 具体请看java 代码 98 | 99 | # 加好友演示 100 | 101 | [![him-vue](https://github.com/lmxdawn/him-vue/raw/master/pic/user-show-how.gif)](http://him-netty.await.fun/h5) 102 | 103 | # 加群演示 104 | 105 | [![him-vue](https://github.com/lmxdawn/him-vue/raw/master/pic/group-show-how.gif)](http://him-netty.await.fun/h5) 106 | 107 | 108 | # QQ 互联相关配置 109 | 110 | ### java 代码 111 | > him-api/src/main/resources/ 这里的配置文件里面, `qq.auth.appid` 和 `qq.auth.appkey` 配置上即可 112 | 113 | ### vue 代码 114 | > 详细配置 根目录下的 115 | `.env.development` 116 | `.env.production` 117 | `.env.stage` 这三个文件是配置, 分别代表 本地测试,生产环境,线上测试环境 118 | 119 | |名称|描述| 120 | | --- | --- | 121 | | VUE_APP_API_BASE | API接口地址 | 122 | | VUE_APP_WEBSOCKET_URL | websocket地址 | 123 | | VUE_APP_USER_QR_CODE_URL | 生成用户的二维码地址(用来加好友的) | 124 | | VUE_APP_GROUP_QR_CODE_URL | 生成群二维码的地址(用来加群的) | 125 | | VUE_APP_ROUTER_BASE | 如果用了 NGINX 做代理, 并且有二级路径, 则需要配置此项 | 126 | 127 | # 跨域问题 128 | 129 | > NGINX 做了端口的代理后, header 头 设置了跨域, 但是还是获取不了, 不知道为啥, 欢迎大神来指导 130 | 131 | > 最后我的解决办法, 全部用一个域名, 然后 NGINX 做路径的转换,下面贴一下我的配置 132 | 133 | ``` 134 | # 前端路径, 注意这里配置了二级目录后, 需要 vue 的路由里面也需要配置 135 | # 我是写在配置文件里面的 VUE_APP_ROUTER_BASE 这个配置项来控制的 136 | location /h5 { 137 | try_files $uri $uri/ /h5/index.html; 138 | } 139 | # API 路径 140 | location /api 141 | { 142 | proxy_pass http://127.0.0.1:9000/api; 143 | proxy_http_version 1.1; 144 | proxy_set_header Upgrade $http_upgrade; 145 | proxy_set_header Connection "Upgrade"; 146 | proxy_set_header X-Real-IP $remote_addr; 147 | } 148 | # ws 路径 149 | location /ws 150 | { 151 | proxy_pass http://127.0.0.1:9001; 152 | proxy_http_version 1.1; 153 | proxy_set_header Upgrade $http_upgrade; 154 | proxy_set_header Connection "Upgrade"; 155 | proxy_set_header X-Real-IP $remote_addr; 156 | } 157 | ``` 158 | 159 | # protobuf 杂谈 160 | 161 | > 说明: 目前所有文件都生成好了,不需要在生成,下面简单说明下 162 | ## java 中使用 163 | 164 | 下载好 him-netty 后在 protocol 目录下 165 | 166 | > 生成 java 类需要安装 安装 protoc 下载地址:https://github.com/protocolbuffers/protobuf/releases, 167 | 168 | > 目前下载的 v3.7.1,解压到任意目录 ,然后把这个目录添加到环境变量 Path 中 169 | 170 | > 然后 windows 版本执行 `proto.bat` 即可,Linux/Max 运行 `sh proto.sh` 171 | 172 | -------------------------------------------------------------------------------- /him-api/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ -------------------------------------------------------------------------------- /him-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | him 7 | com.lmxdawn 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | him-api 13 | 14 | 15 | 16 | 17 | 18 | com.lmxdawn 19 | him-common 20 | 21 | 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-devtools 26 | true 27 | 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-web 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-test 38 | test 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-aop 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-data-redis 49 | 50 | 51 | 52 | 53 | com.alibaba 54 | fastjson 55 | 56 | 57 | 58 | 59 | 60 | com.alibaba 61 | druid 62 | 1.1.12 63 | 64 | 65 | 66 | mysql 67 | mysql-connector-java 68 | runtime 69 | 70 | 71 | 72 | org.mybatis.spring.boot 73 | mybatis-spring-boot-starter 74 | 1.3.2 75 | 76 | 77 | 78 | 79 | org.projectlombok 80 | lombok 81 | true 82 | 83 | 84 | 85 | 86 | io.jsonwebtoken 87 | jjwt 88 | 0.9.1 89 | 90 | 91 | 92 | 93 | com.google.protobuf 94 | protobuf-java 95 | 96 | 97 | 98 | 99 | io.netty 100 | netty-all 101 | 102 | 103 | 104 | 105 | 106 | com.squareup.okhttp3 107 | okhttp 108 | 109 | 110 | 111 | 112 | org.apache.commons 113 | commons-lang3 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | org.springframework.boot 123 | spring-boot-maven-plugin 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/HimApiApplication.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.web.servlet.ServletComponentScan; 6 | 7 | @SpringBootApplication 8 | @ServletComponentScan 9 | public class HimApiApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(HimApiApplication.class, args); 13 | } 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/annotation/CheckLoginAnnotation.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * 登录验证的注解 10 | */ 11 | //此注解只能修饰方法 12 | @Target(ElementType.METHOD) 13 | //当前注解如何去保持 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface CheckLoginAnnotation { 16 | String value() default ""; 17 | } 18 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/config/CorsConfig.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | /** 8 | * 跨域配置 9 | */ 10 | @Data 11 | @Configuration 12 | @ConfigurationProperties(prefix = "cors") 13 | public class CorsConfig { 14 | 15 | // 允许的域 16 | private String allowedOrigins; 17 | // 允许的方法 18 | private String allowedMethods; 19 | // 允许的头信息 20 | private String allowedHeaders; 21 | // 是否允许Cookie 22 | private String allowedCredentials; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/config/DruidStatFilter.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.config; 2 | 3 | import com.alibaba.druid.support.http.WebStatFilter; 4 | 5 | import javax.servlet.annotation.WebFilter; 6 | import javax.servlet.annotation.WebInitParam; 7 | 8 | /** 9 | * 配置监控拦截器 (过滤不需要监控的后缀) 10 | * druid监控拦截器 11 | */ 12 | @WebFilter(filterName = "druidWebStatFilter", urlPatterns = "/*", 13 | initParams = { 14 | @WebInitParam(name = "exclusions", value = "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")//忽略资源 15 | } 16 | ) 17 | public class DruidStatFilter extends WebStatFilter { 18 | } 19 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/config/DruidStatViewServlet.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.config; 2 | 3 | import com.alibaba.druid.support.http.StatViewServlet; 4 | 5 | import javax.servlet.annotation.WebInitParam; 6 | import javax.servlet.annotation.WebServlet; 7 | 8 | /** 9 | * druid监控视图配置 (监控视图配置) 10 | */ 11 | @WebServlet(urlPatterns = "/druid/*", initParams={ 12 | @WebInitParam(name="allow",value="127.0.0.1"),// IP白名单 (没有配置或者为空,则允许所有访问) 13 | @WebInitParam(name="deny",value="192.168.16.111"),// IP黑名单 (存在共同时,deny优先于allow) 14 | @WebInitParam(name="loginUsername",value="api"),// 用户名 15 | @WebInitParam(name="loginPassword",value="api"),// 密码 16 | @WebInitParam(name="resetEnable",value="true")// 禁用HTML页面上的“Reset All”功能 17 | }) 18 | public class DruidStatViewServlet extends StatViewServlet { 19 | private static final long serialVersionUID = 2359758657306626394L; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/config/OkHttpConfig.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.config; 2 | 3 | import okhttp3.OkHttpClient; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import java.util.concurrent.TimeUnit; 8 | 9 | @Configuration 10 | public class OkHttpConfig { 11 | 12 | /** 13 | * http client 14 | * @return okHttp 15 | */ 16 | @Bean 17 | public OkHttpClient okHttpClient() { 18 | OkHttpClient.Builder builder = new OkHttpClient.Builder(); 19 | builder.connectTimeout(30, TimeUnit.SECONDS) 20 | .readTimeout(10, TimeUnit.SECONDS) 21 | .writeTimeout(10,TimeUnit.SECONDS) 22 | .retryOnConnectionFailure(true); 23 | return builder.build(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/config/PublicFileUrlConfig.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | /** 7 | * 公共文件的配置 8 | */ 9 | 10 | @Configuration 11 | @ConfigurationProperties(prefix = "public-file") 12 | public class PublicFileUrlConfig { 13 | 14 | /** 15 | * 上传的地址 16 | */ 17 | private static String uploadUrl; 18 | 19 | public void setUploadUrl(String uploadUrl) { 20 | PublicFileUrlConfig.uploadUrl = uploadUrl; 21 | } 22 | 23 | public static String getUploadUrl() { 24 | return uploadUrl; 25 | } 26 | 27 | /** 28 | * 资源的域名 29 | */ 30 | private static String domain; 31 | 32 | public void setDomain(String domain) { 33 | PublicFileUrlConfig.domain = domain; 34 | } 35 | 36 | public static String getDomain() { 37 | return domain; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/constant/WSMsgTypeConstant.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.constant; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * 消息类型(0:普通文字消息,1:图片消息,2:文件消息,3:语音消息,4:视频消息) 7 | */ 8 | @Getter 9 | public class WSMsgTypeConstant { 10 | 11 | public static final int TEXT = 0; 12 | public static final int IMAGE = 1; 13 | public static final int FILE = 2; 14 | public static final int VOICE = 3; 15 | public static final int VIDEO = 4; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/constant/WSReqTypeConstant.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.constant; 2 | 3 | /** 4 | * 请求类型常量(0: 心跳, 1: 登录) 5 | */ 6 | public class WSReqTypeConstant { 7 | 8 | // 心跳 9 | public static final int PING = 0; 10 | // 登录 11 | public static final int LOGIN = 1; 12 | 13 | } -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/constant/WSResTypeConstant.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.constant; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * 返回类型的常量(-2: 登录异常, -1: 异地登录, 0: 心跳,1: 好友消息,2: 群消息,3: 好友请求消息,4: 好友同意消息,5: 加入群消息) 7 | */ 8 | @Getter 9 | public class WSResTypeConstant { 10 | 11 | public static final int LOGIN_OUT = -2; 12 | public static final int WS_OUT = -1; 13 | public static final int PING = 0; 14 | public static final int FRIEND = 1; 15 | public static final int GROUP = 2; 16 | public static final int FRIEND_ASK = 3; 17 | public static final int FRIEND_ACK = 4; 18 | public static final int JOIN_GROUP = 5; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.controller; 2 | 3 | import com.lmxdawn.him.api.ws.WSServer; 4 | import com.lmxdawn.him.api.utils.WSBaseReqUtils; 5 | import com.lmxdawn.him.api.vo.req.WSBaseReqVO; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | @RestController 12 | public class HelloController { 13 | 14 | @Autowired 15 | private WSServer wsServer; 16 | 17 | @GetMapping("/hello") 18 | public String hello(@RequestParam("uid") Long uid) { 19 | 20 | Integer type = 1; 21 | Long id = uid; 22 | Integer msgType = 0; 23 | String msgContent = "嘿嘿测试"; 24 | Long sUid = 1L; 25 | String name = "测试"; 26 | String avatar = "头像"; 27 | String remark = "说明"; 28 | 29 | WSBaseReqVO wsBaseReqVO = WSBaseReqUtils.create(type, id, msgType, msgContent, sUid, name, avatar, remark); 30 | 31 | Boolean aBoolean = wsServer.sendMsg(uid, wsBaseReqVO); 32 | 33 | return aBoolean ? "success" : "客户端不在线"; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/controller/group/GroupIndexController.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.controller.group; 2 | 3 | import com.lmxdawn.him.api.dto.UserLoginDTO; 4 | import com.lmxdawn.him.api.service.group.GroupService; 5 | import com.lmxdawn.him.api.service.group.GroupUserService; 6 | import com.lmxdawn.him.api.service.user.UserService; 7 | import com.lmxdawn.him.api.utils.UserLoginUtils; 8 | import com.lmxdawn.him.api.vo.res.GroupIndexListResVO; 9 | import com.lmxdawn.him.api.vo.req.GroupSaveReqVO; 10 | import com.lmxdawn.him.api.vo.res.UserInfoListResVO; 11 | import com.lmxdawn.him.common.entity.group.Group; 12 | import com.lmxdawn.him.common.entity.group.GroupUser; 13 | import com.lmxdawn.him.common.enums.ResultEnum; 14 | import com.lmxdawn.him.common.utils.ResultVOUtils; 15 | import com.lmxdawn.him.common.vo.res.BaseResVO; 16 | import org.springframework.beans.BeanUtils; 17 | import org.springframework.validation.BindingResult; 18 | import org.springframework.web.bind.annotation.*; 19 | 20 | import javax.annotation.Resource; 21 | import javax.servlet.http.HttpServletRequest; 22 | import javax.validation.Valid; 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | import java.util.Map; 26 | import java.util.stream.Collectors; 27 | 28 | /** 29 | * 群相关 30 | */ 31 | @RequestMapping("/group") 32 | @RestController 33 | public class GroupIndexController { 34 | 35 | @Resource 36 | private GroupService groupService; 37 | 38 | @Resource 39 | private GroupUserService groupUserService; 40 | 41 | 42 | @Resource 43 | private UserService userService; 44 | 45 | /** 46 | * 群用户列表 47 | * 48 | * @return 49 | */ 50 | @GetMapping("/lists") 51 | public BaseResVO lists(@RequestParam("groupId") Long groupId, 52 | @RequestParam(value = "page", required = false, defaultValue = "1") Integer page, 53 | @RequestParam(value = "limit", required = false, defaultValue = "20") Integer limit, 54 | HttpServletRequest request) { 55 | // 验证登录 56 | UserLoginDTO userLoginDTO = UserLoginUtils.check(request); 57 | if (userLoginDTO == null) { 58 | return ResultVOUtils.error(ResultEnum.LOGIN_VERIFY_FALL); 59 | } 60 | 61 | Long uid = userLoginDTO.getUid(); 62 | // 判断是不是在群里边 63 | GroupUser groupUser = groupUserService.findByGroupIdAndUid(groupId, uid); 64 | if (groupUser == null) { 65 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, "请先加入群~"); 66 | } 67 | limit = limit > 500 ? 500 : limit; 68 | List groupUsers = groupUserService.listByGroupId(groupId, page, limit); 69 | 70 | List uids = groupUsers.stream().map(GroupUser::getUid).collect(Collectors.toList()); 71 | Map userInfoListResVOMap = userService.listByUidIn(uids); 72 | 73 | List groupIndexListResVOS = new ArrayList<>(); 74 | groupUsers.forEach(v -> { 75 | GroupIndexListResVO groupIndexListResVO = new GroupIndexListResVO(); 76 | BeanUtils.copyProperties(v, groupIndexListResVO); 77 | groupIndexListResVO.setUser(userInfoListResVOMap.get(v.getUid())); 78 | groupIndexListResVOS.add(groupIndexListResVO); 79 | }); 80 | 81 | return ResultVOUtils.success(groupIndexListResVOS); 82 | } 83 | 84 | /** 85 | * 添加 86 | * 87 | * @return 88 | */ 89 | @PostMapping("/create") 90 | public BaseResVO create(@Valid @RequestBody GroupSaveReqVO groupSaveReqVO, 91 | BindingResult bindingResult, 92 | HttpServletRequest request) { 93 | if (bindingResult.hasErrors()) { 94 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, bindingResult.getFieldError().getDefaultMessage()); 95 | } 96 | 97 | // 验证登录 98 | UserLoginDTO userLoginDTO = UserLoginUtils.check(request); 99 | if (userLoginDTO == null) { 100 | return ResultVOUtils.error(ResultEnum.LOGIN_VERIFY_FALL); 101 | } 102 | 103 | Long uid = userLoginDTO.getUid(); 104 | 105 | String avatar = groupSaveReqVO.getAvatar(); 106 | 107 | avatar = avatar == null || "".equals(avatar) ? "http://prbsvykmy.bkt.clouddn.com/static/image/group-default.png" : avatar; 108 | 109 | Group group = new Group(); 110 | group.setUid(uid); 111 | group.setName(groupSaveReqVO.getName()); 112 | group.setAvatar(avatar); 113 | group.setMemberNum(1); 114 | 115 | String remark = groupSaveReqVO.getRemark(); 116 | remark = remark == null || "".equals(remark) ? "你今生有没有坚定不移地相信过一件事或一个人?是那种至死不渝的相信?" : remark; 117 | group.setRemark(remark); 118 | boolean b = groupService.insertGroup(group); 119 | 120 | if (!b) { 121 | return ResultVOUtils.error(ResultEnum.NOT_NETWORK); 122 | } 123 | 124 | // 加入群列表 125 | GroupUser groupUser = new GroupUser(); 126 | groupUser.setGroupId(group.getGroupId()); 127 | groupUser.setUid(uid); 128 | groupUser.setRank(2); // 群主 129 | boolean b1 = groupUserService.insertGroupUser(groupUser); 130 | 131 | return ResultVOUtils.success(group); 132 | } 133 | 134 | /** 135 | * 更新 136 | * 137 | * @return 138 | */ 139 | @PostMapping("/update") 140 | public BaseResVO update(@Valid @RequestBody GroupSaveReqVO groupSaveReqVO, 141 | BindingResult bindingResult, 142 | HttpServletRequest request) { 143 | if (bindingResult.hasErrors()) { 144 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, bindingResult.getFieldError().getDefaultMessage()); 145 | } 146 | 147 | if (groupSaveReqVO.getGroupId() == null 148 | || groupSaveReqVO.getGroupId() <= 0) { 149 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, "参数错误~"); 150 | } 151 | 152 | // 验证登录 153 | UserLoginDTO userLoginDTO = UserLoginUtils.check(request); 154 | if (userLoginDTO == null) { 155 | return ResultVOUtils.error(ResultEnum.LOGIN_VERIFY_FALL); 156 | } 157 | 158 | Long uid = userLoginDTO.getUid(); 159 | 160 | Group group1 = groupService.findByGroupId(groupSaveReqVO.getGroupId()); 161 | // 判断是否是群主 162 | if (group1 == null || !uid.equals(group1.getUid())) { 163 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, "没有该群信息~"); 164 | } 165 | 166 | Group group = new Group(); 167 | group.setGroupId(groupSaveReqVO.getGroupId()); 168 | boolean isUp = false; 169 | if (null != groupSaveReqVO.getName() && !groupSaveReqVO.getName().equals(group1.getName())) { 170 | group.setName(groupSaveReqVO.getName()); 171 | isUp = true; 172 | } 173 | if (null != groupSaveReqVO.getAvatar() && !groupSaveReqVO.getAvatar().equals(group1.getAvatar())) { 174 | group.setAvatar(groupSaveReqVO.getAvatar()); 175 | isUp = true; 176 | } 177 | if (null != groupSaveReqVO.getRemark() && !groupSaveReqVO.getRemark().equals(group1.getRemark())) { 178 | group.setRemark(groupSaveReqVO.getRemark()); 179 | isUp = true; 180 | } 181 | boolean b = true; 182 | if (isUp) { 183 | b = groupService.updateGroup(group); 184 | } 185 | if (!b) { 186 | return ResultVOUtils.error(ResultEnum.NOT_NETWORK); 187 | } 188 | 189 | return ResultVOUtils.success(); 190 | } 191 | 192 | /** 193 | * 删除 (解散群) 194 | * 195 | * @return 196 | */ 197 | @PostMapping("/delete") 198 | public BaseResVO delete(@RequestParam(value = "groupId") Long groupId, 199 | HttpServletRequest request) { 200 | 201 | if (groupId == null 202 | || groupId <= 0) { 203 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, "参数错误~"); 204 | } 205 | 206 | // 验证登录 207 | UserLoginDTO userLoginDTO = UserLoginUtils.check(request); 208 | if (userLoginDTO == null) { 209 | return ResultVOUtils.error(ResultEnum.LOGIN_VERIFY_FALL); 210 | } 211 | 212 | Long uid = userLoginDTO.getUid(); 213 | 214 | Group group1 = groupService.findByGroupId(groupId); 215 | // 判断是否是群主 216 | if (group1 == null || !uid.equals(group1.getUid())) { 217 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, "没有该群信息~"); 218 | } 219 | 220 | // 删除群成员信息 221 | boolean b = groupUserService.deleteByGroupId(groupId); 222 | if (!b) { 223 | return ResultVOUtils.error(ResultEnum.NOT_NETWORK); 224 | } 225 | 226 | return ResultVOUtils.success(); 227 | } 228 | 229 | } 230 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/controller/group/GroupMsgController.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.controller.group; 2 | 3 | import com.lmxdawn.him.api.dto.UserLoginDTO; 4 | import com.lmxdawn.him.api.constant.WSResTypeConstant; 5 | import com.lmxdawn.him.api.service.group.GroupMsgService; 6 | import com.lmxdawn.him.api.service.group.GroupUserService; 7 | import com.lmxdawn.him.api.service.user.UserService; 8 | import com.lmxdawn.him.api.ws.WSServer; 9 | import com.lmxdawn.him.api.utils.UserLoginUtils; 10 | import com.lmxdawn.him.api.utils.WSBaseReqUtils; 11 | import com.lmxdawn.him.api.vo.req.GroupMsgCreateReqVO; 12 | import com.lmxdawn.him.api.vo.req.WSBaseReqVO; 13 | import com.lmxdawn.him.api.vo.res.GroupMsgListResVO; 14 | import com.lmxdawn.him.api.vo.res.UserInfoListResVO; 15 | import com.lmxdawn.him.common.entity.group.GroupMsg; 16 | import com.lmxdawn.him.common.entity.group.GroupUser; 17 | import com.lmxdawn.him.common.entity.user.User; 18 | import com.lmxdawn.him.common.enums.ResultEnum; 19 | import com.lmxdawn.him.common.utils.ResultVOUtils; 20 | import com.lmxdawn.him.common.vo.res.BaseResVO; 21 | import org.springframework.beans.BeanUtils; 22 | import org.springframework.validation.BindingResult; 23 | import org.springframework.web.bind.annotation.*; 24 | 25 | import javax.annotation.Resource; 26 | import javax.servlet.http.HttpServletRequest; 27 | import javax.validation.Valid; 28 | import java.util.ArrayList; 29 | import java.util.List; 30 | import java.util.Map; 31 | import java.util.stream.Collectors; 32 | 33 | /** 34 | * 群消息相关 35 | */ 36 | @RequestMapping("/group/msg") 37 | @RestController 38 | public class GroupMsgController { 39 | 40 | @Resource 41 | private GroupUserService groupUserService; 42 | 43 | @Resource 44 | private GroupMsgService groupMsgService; 45 | 46 | @Resource 47 | private UserService userService; 48 | 49 | @Resource 50 | private WSServer wsServer; 51 | 52 | /** 53 | * 列表 54 | * 55 | * @return 56 | */ 57 | @GetMapping("/lists") 58 | public BaseResVO lists(@RequestParam("groupId") Long groupId, 59 | @RequestParam(value = "page", required = false, defaultValue = "1") Integer page, 60 | @RequestParam(value = "limit", required = false, defaultValue = "20") Integer limit, 61 | HttpServletRequest request) { 62 | 63 | limit = limit > 25 ? 25 : limit; 64 | // 验证登录 65 | UserLoginDTO userLoginDTO = UserLoginUtils.check(request); 66 | if (userLoginDTO == null) { 67 | return ResultVOUtils.error(ResultEnum.LOGIN_VERIFY_FALL); 68 | } 69 | 70 | Long uid = userLoginDTO.getUid(); 71 | 72 | // 判断是不是群里的人 73 | GroupUser groupUser = groupUserService.findByGroupIdAndUid(groupId, uid); 74 | if (groupUser == null) { 75 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, "不是该群成员~"); 76 | } 77 | 78 | List groupMsgs = groupMsgService.listByGroupIdAndCreateTime(groupId, groupUser.getCreateTime(), page, limit); 79 | 80 | List groupMsgListResVOS = new ArrayList<>(); 81 | if (groupMsgs.size() == 0) { 82 | return ResultVOUtils.success(groupMsgListResVOS); 83 | } 84 | 85 | List uids = groupMsgs.stream().map(GroupMsg::getSenderUid).collect(Collectors.toList()); 86 | Map userInfoListResVOMap = userService.listByUidIn(uids); 87 | 88 | groupMsgs.forEach(v -> { 89 | GroupMsgListResVO groupMsgListResVO = new GroupMsgListResVO(); 90 | BeanUtils.copyProperties(v, groupMsgListResVO); 91 | groupMsgListResVO.setUser(userInfoListResVOMap.get(v.getSenderUid())); 92 | groupMsgListResVOS.add(groupMsgListResVO); 93 | }); 94 | 95 | return ResultVOUtils.success(groupMsgListResVOS); 96 | } 97 | 98 | /** 99 | * 添加 100 | * 101 | * @return 102 | */ 103 | @PostMapping("/create") 104 | public BaseResVO create(@Valid @RequestBody GroupMsgCreateReqVO groupMsgCreateReqVO, 105 | BindingResult bindingResult, 106 | HttpServletRequest request) { 107 | if (bindingResult.hasErrors()) { 108 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, bindingResult.getFieldError().getDefaultMessage()); 109 | } 110 | 111 | // 验证登录 112 | UserLoginDTO userLoginDTO = UserLoginUtils.check(request); 113 | if (userLoginDTO == null) { 114 | return ResultVOUtils.error(ResultEnum.LOGIN_VERIFY_FALL); 115 | } 116 | 117 | Long uid = userLoginDTO.getUid(); 118 | 119 | Long groupId = groupMsgCreateReqVO.getGroupId(); 120 | // 判断是否在群里面 121 | GroupUser groupUser1 = groupUserService.findByGroupIdAndUid(groupId, uid); 122 | if (groupUser1 == null) { 123 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, "不是该群成员~"); 124 | } 125 | 126 | Integer msgType = groupMsgCreateReqVO.getMsgType(); 127 | String msgContent = groupMsgCreateReqVO.getMsgContent(); 128 | boolean b = groupMsgService.sendGroupMsg(uid, groupId, WSResTypeConstant.GROUP, msgType, msgContent); 129 | if (!b) { 130 | return ResultVOUtils.error(ResultEnum.NOT_NETWORK); 131 | } 132 | 133 | 134 | return ResultVOUtils.success(); 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/controller/user/UserFriendController.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.controller.user; 2 | 3 | import com.lmxdawn.him.api.dto.UserLoginDTO; 4 | import com.lmxdawn.him.api.service.user.UserFriendService; 5 | import com.lmxdawn.him.api.service.user.UserService; 6 | import com.lmxdawn.him.api.utils.UserLoginUtils; 7 | import com.lmxdawn.him.api.vo.req.UserFriendDeleteReqVO; 8 | import com.lmxdawn.him.api.vo.res.UserFriendListInfoResVO; 9 | import com.lmxdawn.him.api.vo.res.UserInfoListResVO; 10 | import com.lmxdawn.him.common.entity.user.UserFriend; 11 | import com.lmxdawn.him.common.enums.ResultEnum; 12 | import com.lmxdawn.him.common.utils.ResultVOUtils; 13 | import com.lmxdawn.him.common.vo.res.BaseResVO; 14 | import org.springframework.beans.BeanUtils; 15 | import org.springframework.validation.BindingResult; 16 | import org.springframework.web.bind.annotation.*; 17 | 18 | import javax.annotation.Resource; 19 | import javax.servlet.http.HttpServletRequest; 20 | import javax.validation.Valid; 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | import java.util.Map; 24 | import java.util.stream.Collectors; 25 | 26 | /** 27 | * 朋友相关 28 | */ 29 | @RequestMapping("/user/friend") 30 | @RestController 31 | public class UserFriendController { 32 | 33 | @Resource 34 | private UserFriendService userFriendService; 35 | 36 | @Resource 37 | private UserService userService; 38 | 39 | /** 40 | * 获取朋友列表 41 | * 42 | * @return 43 | */ 44 | @GetMapping("/lists") 45 | public BaseResVO lists(@RequestParam(value = "page", required = false, defaultValue = "1") Integer page, 46 | @RequestParam(value = "limit", required = false, defaultValue = "20") Integer limit, 47 | HttpServletRequest request) { 48 | 49 | // 验证登录 50 | UserLoginDTO userLoginDTO = UserLoginUtils.check(request); 51 | if (userLoginDTO == null) { 52 | return ResultVOUtils.error(ResultEnum.LOGIN_VERIFY_FALL); 53 | } 54 | 55 | limit = limit > 50 ? 50 : limit; 56 | 57 | Long uid = userLoginDTO.getUid(); 58 | 59 | 60 | List userFriends = userFriendService.listByUid(uid, page, limit); 61 | 62 | List uids = userFriends.stream().map(UserFriend::getFriendUid).collect(Collectors.toList()); 63 | 64 | Map userInfoListResVOMap = userService.listByUidIn(uids); 65 | 66 | List userFriendListInfoResVOS = new ArrayList<>(); 67 | userFriends.forEach(v -> { 68 | UserFriendListInfoResVO userFriendListInfoResVO = new UserFriendListInfoResVO(); 69 | BeanUtils.copyProperties(v, userFriendListInfoResVO); 70 | userFriendListInfoResVO.setUser(userInfoListResVOMap.get(v.getFriendUid())); 71 | userFriendListInfoResVOS.add(userFriendListInfoResVO); 72 | }); 73 | 74 | return ResultVOUtils.success(userFriendListInfoResVOS); 75 | 76 | } 77 | 78 | 79 | /** 80 | * 删除好友 81 | * 82 | * @return 83 | */ 84 | @PostMapping("/delete") 85 | public BaseResVO delete(@Valid @RequestBody UserFriendDeleteReqVO userFriendDeleteReqVO, 86 | BindingResult bindingResult, 87 | HttpServletRequest request) { 88 | if (bindingResult.hasErrors()) { 89 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, bindingResult.getFieldError().getDefaultMessage()); 90 | } 91 | 92 | // 验证登录 93 | UserLoginDTO userLoginDTO = UserLoginUtils.check(request); 94 | if (userLoginDTO == null) { 95 | return ResultVOUtils.error(ResultEnum.LOGIN_VERIFY_FALL); 96 | } 97 | 98 | Long uid = userLoginDTO.getUid(); 99 | Long friendUid = userFriendDeleteReqVO.getFriendUid(); 100 | 101 | boolean b = userFriendService.deleteByUidAndFriendUid(uid, friendUid); 102 | boolean b1 = userFriendService.deleteByUidAndFriendUid(friendUid, uid); 103 | if (!b) { 104 | return ResultVOUtils.error(ResultEnum.NOT_NETWORK); 105 | } 106 | 107 | return ResultVOUtils.success(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/controller/user/UserIndexController.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.controller.user; 2 | 3 | import com.lmxdawn.him.api.dto.UserLoginDTO; 4 | import com.lmxdawn.him.api.service.user.UserProfileService; 5 | import com.lmxdawn.him.api.service.user.UserService; 6 | import com.lmxdawn.him.api.utils.UserFriendUtils; 7 | import com.lmxdawn.him.api.utils.UserLoginUtils; 8 | import com.lmxdawn.him.api.vo.res.UserInfoResVO; 9 | import com.lmxdawn.him.api.vo.res.UserProfileInfoResVO; 10 | import com.lmxdawn.him.api.vo.res.UserReadResVO; 11 | import com.lmxdawn.him.common.entity.user.User; 12 | import com.lmxdawn.him.common.entity.user.UserProfile; 13 | import com.lmxdawn.him.common.enums.ResultEnum; 14 | import com.lmxdawn.him.common.utils.ResultVOUtils; 15 | import com.lmxdawn.him.common.vo.res.BaseResVO; 16 | import org.springframework.beans.BeanUtils; 17 | import org.springframework.web.bind.annotation.GetMapping; 18 | import org.springframework.web.bind.annotation.RequestMapping; 19 | import org.springframework.web.bind.annotation.RequestParam; 20 | import org.springframework.web.bind.annotation.RestController; 21 | 22 | import javax.annotation.Resource; 23 | import javax.servlet.http.HttpServletRequest; 24 | 25 | @RequestMapping("/user") 26 | @RestController 27 | public class UserIndexController { 28 | 29 | @Resource 30 | private UserService userService; 31 | 32 | @Resource 33 | private UserProfileService userProfileService; 34 | 35 | /** 36 | * 登录用户信息 37 | * @return 38 | */ 39 | @GetMapping("/loginInfo") 40 | public BaseResVO loginInfo(HttpServletRequest request) { 41 | 42 | // 验证登录 43 | UserLoginDTO userLoginDTO = UserLoginUtils.check(request); 44 | if (userLoginDTO == null) { 45 | return ResultVOUtils.error(ResultEnum.LOGIN_VERIFY_FALL); 46 | } 47 | 48 | Long uid = userLoginDTO.getUid(); 49 | 50 | User user = userService.findByUid(uid); 51 | if (user == null) { 52 | return ResultVOUtils.error(ResultEnum.LOGIN_VERIFY_FALL); 53 | } 54 | 55 | UserProfile userProfile = userProfileService.findByUid(uid); 56 | 57 | UserProfileInfoResVO userProfileInfoResVO = new UserProfileInfoResVO(); 58 | if (userProfile != null) { 59 | BeanUtils.copyProperties(userProfile, userProfileInfoResVO); 60 | } 61 | 62 | UserInfoResVO userInfoResVO = new UserInfoResVO(); 63 | BeanUtils.copyProperties(user, userInfoResVO); 64 | userInfoResVO.setProfile(userProfileInfoResVO); 65 | 66 | return ResultVOUtils.success(userInfoResVO); 67 | 68 | } 69 | 70 | /** 71 | * 用户信息 72 | * @return 73 | */ 74 | @GetMapping("/read") 75 | public BaseResVO read(@RequestParam(value = "uid") Long uid, 76 | HttpServletRequest request) { 77 | 78 | // 验证登录 79 | UserLoginDTO userLoginDTO = UserLoginUtils.check(request); 80 | if (userLoginDTO == null) { 81 | return ResultVOUtils.error(ResultEnum.LOGIN_VERIFY_FALL); 82 | } 83 | 84 | User user = userService.findByUid(uid); 85 | 86 | UserReadResVO userReadResVO = new UserReadResVO(); 87 | BeanUtils.copyProperties(user, userReadResVO); 88 | 89 | return ResultVOUtils.success(userReadResVO); 90 | 91 | } 92 | 93 | 94 | 95 | /** 96 | * 获取二维码 97 | * 98 | * @param request 99 | * @return 100 | */ 101 | @GetMapping("/getQRCheckCode") 102 | public BaseResVO getQRCheckCode(HttpServletRequest request) { 103 | // 验证登录 104 | UserLoginDTO userLoginDTO = UserLoginUtils.check(request); 105 | if (userLoginDTO == null) { 106 | return ResultVOUtils.error(ResultEnum.LOGIN_VERIFY_FALL); 107 | } 108 | 109 | Long uid = userLoginDTO.getUid(); 110 | 111 | String checkCode = UserFriendUtils.createCheckCode(uid); 112 | 113 | return ResultVOUtils.success(checkCode); 114 | 115 | } 116 | 117 | 118 | } 119 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/controller/user/UserLoginController.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.controller.user; 2 | 3 | 4 | import com.lmxdawn.him.api.service.other.QqWebAuthService; 5 | import com.lmxdawn.him.api.service.user.UserQqService; 6 | import com.lmxdawn.him.api.utils.UserLoginUtils; 7 | import com.lmxdawn.him.api.vo.req.UserLoginPwdReqVO; 8 | import com.lmxdawn.him.api.vo.res.QqOpenIdResVO; 9 | import com.lmxdawn.him.api.vo.res.QqUserInfoResVO; 10 | import com.lmxdawn.him.api.vo.res.UserLoginResVO; 11 | import com.lmxdawn.him.api.service.user.UserService; 12 | import com.lmxdawn.him.api.utils.PasswordUtils; 13 | import com.lmxdawn.him.common.entity.user.User; 14 | import com.lmxdawn.him.common.entity.user.UserQq; 15 | import com.lmxdawn.him.common.enums.ResultEnum; 16 | import com.lmxdawn.him.common.vo.res.BaseResVO; 17 | import com.lmxdawn.him.common.utils.ResultVOUtils; 18 | import okhttp3.Request; 19 | import okhttp3.Response; 20 | import org.apache.commons.lang3.RandomStringUtils; 21 | import org.springframework.validation.BindingResult; 22 | import org.springframework.web.bind.annotation.*; 23 | 24 | import javax.annotation.Resource; 25 | import javax.servlet.http.HttpServletResponse; 26 | import javax.validation.Valid; 27 | 28 | /** 29 | * 登录控制器 30 | */ 31 | @RequestMapping("/user/login") 32 | @RestController 33 | public class UserLoginController { 34 | 35 | @Resource 36 | private UserService userService; 37 | 38 | @Resource 39 | private QqWebAuthService qqWebAuthService; 40 | 41 | @Resource 42 | private UserQqService userQqService; 43 | 44 | /** 45 | * 用户密码登录 46 | * 47 | * @param userLoginPwdReqVO 48 | * @param bindingResult 49 | * @return 50 | */ 51 | @PostMapping("/byPwd") 52 | public BaseResVO byPwd(@Valid @RequestBody UserLoginPwdReqVO userLoginPwdReqVO, 53 | BindingResult bindingResult) { 54 | if (bindingResult.hasErrors()) { 55 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, bindingResult.getFieldError().getDefaultMessage()); 56 | } 57 | 58 | Long uid = userLoginPwdReqVO.getUid(); 59 | User user = userService.findPwdByUid(uid); 60 | String md5Pwd = PasswordUtils.md52md5(userLoginPwdReqVO.getPwd()); 61 | if (user == null || !md5Pwd.equals(user.getPwd())) { 62 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, "密码或用户名错误~"); 63 | } 64 | String token = UserLoginUtils.createSid(uid); 65 | 66 | UserLoginResVO userLoginResVO = new UserLoginResVO(); 67 | userLoginResVO.setUid(uid); 68 | userLoginResVO.setSid(token); 69 | return ResultVOUtils.success(userLoginResVO); 70 | } 71 | 72 | /** 73 | * 用户密码登录 74 | * 75 | * @return 76 | */ 77 | @PostMapping("/byTourist") 78 | public BaseResVO byTourist(@RequestParam(value = "sex") Integer type) { 79 | 80 | if (type != 1 && type != 2) { 81 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, "请选择游客性别~"); 82 | } 83 | char[] chr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 84 | 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 85 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; 86 | String name = "火星人" + RandomStringUtils.random(7, chr); 87 | String avatar = String.format("http://prbsvykmy.bkt.clouddn.com/static/image/user-%d-default.png", type); 88 | String remark = "你今生有没有坚定不移地相信过一件事或一个人?是那种至死不渝的相信?"; 89 | // 创建用户 90 | User user = new User(); 91 | user.setName(name); 92 | user.setAvatar(avatar); 93 | user.setRemark(remark); 94 | boolean b = userService.insertUser(user); 95 | if (!b) { 96 | return ResultVOUtils.error(); 97 | } 98 | 99 | Long uid = user.getUid(); 100 | String token = UserLoginUtils.createSid(uid); 101 | 102 | UserLoginResVO userLoginResVO = new UserLoginResVO(); 103 | userLoginResVO.setUid(uid); 104 | userLoginResVO.setSid(token); 105 | return ResultVOUtils.success(userLoginResVO); 106 | } 107 | 108 | /** 109 | * 第三方QQ登录 110 | * 111 | * @return 112 | */ 113 | @PostMapping("/byQq") 114 | public BaseResVO byQq(@RequestParam(value = "code") String code, 115 | @RequestParam(value = "redirect_uri") String redirect_uri) { 116 | 117 | 118 | String accessToken = qqWebAuthService.getAccessToken(code, redirect_uri); 119 | if (accessToken == null || "".equals(accessToken)) { 120 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, "accessToken 获取失败~"); 121 | } 122 | 123 | QqOpenIdResVO openIdResVO = qqWebAuthService.getOpenID(accessToken); 124 | if (openIdResVO == null || openIdResVO.getOpenid() == null || "".equals(openIdResVO.getOpenid())) { 125 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, "openid 获取是吧~"); 126 | } 127 | QqUserInfoResVO userInfo = qqWebAuthService.getUserInfo(accessToken, openIdResVO.getOpenid()); 128 | 129 | if (userInfo == null) { 130 | return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, "userInfo 获取失败~"); 131 | } 132 | 133 | UserQq userQq = userQqService.findByOpenId(openIdResVO.getOpenid()); 134 | 135 | // 判断是否有过值 136 | if (userQq == null || userQq.getUid() == null) { 137 | // 创建用户 138 | User user = new User(); 139 | user.setName(userInfo.getNickname()); 140 | user.setAvatar(userInfo.getFigureurl()); 141 | String remark = "你今生有没有坚定不移地相信过一件事或一个人?是那种至死不渝的相信?"; 142 | user.setRemark(remark); 143 | boolean b = userService.insertUser(user); 144 | if (!b) { 145 | return ResultVOUtils.error(); 146 | } 147 | // 创建QQ用户 148 | userQq = new UserQq(); 149 | userQq.setUid(user.getUid()); 150 | userQq.setOpenid(openIdResVO.getOpenid()); 151 | boolean b1 = userQqService.insertUserQq(userQq); 152 | if (!b1) { 153 | return ResultVOUtils.error(); 154 | } 155 | } 156 | 157 | Long uid = userQq.getUid(); 158 | 159 | String sid = UserLoginUtils.createSid(uid); 160 | 161 | UserLoginResVO userLoginResVO = new UserLoginResVO(); 162 | userLoginResVO.setUid(uid); 163 | userLoginResVO.setSid(sid); 164 | return ResultVOUtils.success(userLoginResVO); 165 | } 166 | 167 | 168 | } 169 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/dao/group/GroupDao.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.dao.group; 2 | 3 | import com.lmxdawn.him.common.entity.group.Group; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | 9 | @Mapper 10 | public interface GroupDao { 11 | 12 | /** 13 | * 查询列表 14 | * @return 15 | */ 16 | Group findByGroupId(Long groupId); 17 | 18 | /** 19 | * 根据多个id查询 20 | * @return 21 | */ 22 | List listByGroupIdIn(List groupIds); 23 | 24 | /** 25 | * 插入 26 | * @return 27 | */ 28 | boolean insertGroup(Group group); 29 | 30 | /** 31 | * 更新 32 | * @return 33 | */ 34 | boolean updateGroup(Group group); 35 | 36 | /** 37 | * 递增用户数量 38 | * @return 39 | */ 40 | boolean incMemberNumByGroupId(@Param("groupId") Long groupId, 41 | @Param("memberNum") Integer memberNum); 42 | 43 | /** 44 | * 递减用户数量 45 | * @return 46 | */ 47 | boolean decMemberNumByGroupId(@Param("groupId") Long groupId); 48 | 49 | /** 50 | * 删除 51 | * @return 52 | */ 53 | boolean deleteByGroupId(Long groupId); 54 | 55 | } 56 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/dao/group/GroupMsgDao.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.dao.group; 2 | 3 | import com.lmxdawn.him.common.entity.group.GroupMsg; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.Date; 8 | import java.util.List; 9 | 10 | @Mapper 11 | public interface GroupMsgDao { 12 | 13 | /** 14 | * 根据最后一次获取的消息ID获取离线消息列表 15 | * 16 | * @return 17 | */ 18 | List listByGroupIdAndCreateTime(@Param(value = "groupId") Long groupId, 19 | @Param(value = "createTime") Date createTime, 20 | @Param("offset") Integer offset, 21 | @Param("limit") Integer limit); 22 | 23 | /** 24 | * 插入 25 | * 26 | * @return 27 | */ 28 | boolean insertGroupMsg(GroupMsg groupMsg); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/dao/group/GroupUserDao.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.dao.group; 2 | 3 | import com.lmxdawn.him.common.entity.group.GroupUser; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | 9 | @Mapper 10 | public interface GroupUserDao { 11 | 12 | /** 13 | * 查询群用户 14 | * @return 15 | */ 16 | GroupUser findByGroupIdAndUid(@Param("groupId") Long groupId, 17 | @Param("uid") Long uid); 18 | 19 | /** 20 | * 查询群的用户列表 21 | * @return 22 | */ 23 | List listByGroupId(@Param("groupId") Long groupId, 24 | @Param("offset") Integer offset, 25 | @Param("limit") Integer limit); 26 | 27 | /** 28 | * 查询用户的群列表 29 | * @return 30 | */ 31 | List listByUid(@Param("uid") Long uid, 32 | @Param("offset") Integer offset, 33 | @Param("limit") Integer limit); 34 | 35 | /** 36 | * 插入 37 | * @return 38 | */ 39 | boolean insertGroupUser(GroupUser groupUser); 40 | 41 | /** 42 | * 更新 43 | * @return 44 | */ 45 | boolean updateGroupUserByGroupIdAndUid(GroupUser groupUser); 46 | 47 | /** 48 | * 清空未读消息数量 49 | * @return 50 | */ 51 | boolean clearUnMsgCountByGroupIdAndUid(GroupUser groupUser); 52 | 53 | /** 54 | * 根据群ID批量更新 55 | * @return 56 | */ 57 | boolean updateGroupUserByGroupId(GroupUser groupUser); 58 | 59 | /** 60 | * 删除 61 | * @return 62 | */ 63 | boolean deleteByGroupIdAndUid(@Param(value = "groupId") Long groupId, @Param(value = "uid") Long uid); 64 | 65 | /** 66 | * 删除 67 | * @return 68 | */ 69 | boolean deleteByGroupId(@Param(value = "groupId") Long groupId); 70 | 71 | } 72 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/dao/user/UserDao.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.dao.user; 2 | 3 | import com.lmxdawn.him.common.entity.user.User; 4 | import org.apache.ibatis.annotations.Mapper; 5 | 6 | import java.util.List; 7 | 8 | @Mapper 9 | public interface UserDao { 10 | 11 | /** 12 | * 根据Uid查询 13 | * @param uid 14 | * @return 15 | */ 16 | User findByUid(Long uid); 17 | 18 | /** 19 | * 根据Uid查询密码 20 | * @param uid 21 | * @return 22 | */ 23 | User findPwdByUid(Long uid); 24 | 25 | /** 26 | * 根据多个Uid查询 27 | * @param uids 28 | * @return 29 | */ 30 | List listByUidIn(List uids); 31 | 32 | /** 33 | * 插入 34 | * @param user 35 | * @return 36 | */ 37 | boolean insertUser(User user); 38 | 39 | /** 40 | * 更新 41 | * @param user 42 | * @return 43 | */ 44 | boolean updateUser(User user); 45 | 46 | /** 47 | * 删除 48 | * @param uid 49 | * @return 50 | */ 51 | boolean deleteByUid(Long uid); 52 | 53 | } 54 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/dao/user/UserFriendAskDao.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.dao.user; 2 | 3 | import com.lmxdawn.him.common.entity.user.UserFriendAsk; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | 9 | @Mapper 10 | public interface UserFriendAskDao { 11 | 12 | /** 13 | * 查询列表 14 | * 15 | * @param 16 | * @return 17 | */ 18 | List listByUid(@Param("uid") Long uid, 19 | @Param("offset") Integer offset, 20 | @Param("limit") Integer limit); 21 | 22 | 23 | /** 24 | * 查询 25 | * @return 26 | */ 27 | UserFriendAsk findById(@Param("id") Long id); 28 | 29 | /** 30 | * 插入 31 | * 32 | * @param userFriendAsk 33 | * @return 34 | */ 35 | boolean insertUserFriendAsk(UserFriendAsk userFriendAsk); 36 | 37 | /** 38 | * 更新 39 | * 40 | * @param userFriendAsk 41 | * @return 42 | */ 43 | boolean updateUserFriendAsk(UserFriendAsk userFriendAsk); 44 | 45 | /** 46 | * 删除 47 | * 48 | * @return 49 | */ 50 | boolean deleteById(@Param("id") Long id); 51 | 52 | } 53 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/dao/user/UserFriendDao.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.dao.user; 2 | 3 | import com.lmxdawn.him.common.entity.user.UserFriend; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | 9 | @Mapper 10 | public interface UserFriendDao { 11 | 12 | /** 13 | * 查询朋友列表 14 | * @return 15 | */ 16 | List listByUid(@Param("uid") Long uid, 17 | @Param("offset") Integer offset, 18 | @Param("limit") Integer limit); 19 | 20 | /** 21 | * 查询两个用户是否是朋友关系 22 | * @return 23 | */ 24 | UserFriend findByUidAndFriendUid(@Param("uid") Long uid, @Param("friendUid") Long friendUid); 25 | 26 | /** 27 | * 插入 28 | * @param userFriends 29 | * @return 30 | */ 31 | boolean insertUserFriendAll(List userFriends); 32 | 33 | /** 34 | * 更新 35 | * @param userFriend 36 | * @return 37 | */ 38 | boolean updateUserFriend(UserFriend userFriend); 39 | 40 | /** 41 | * 删除 42 | * @return 43 | */ 44 | boolean deleteByUidAndFriendUid(@Param("uid") Long uid, @Param("friendUid") Long friendUid); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/dao/user/UserFriendMsgDao.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.dao.user; 2 | 3 | import com.lmxdawn.him.common.entity.user.UserFriendMsg; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | 9 | @Mapper 10 | public interface UserFriendMsgDao { 11 | 12 | /** 13 | * 根据最后一次获取的消息ID获取离线消息列表 14 | * 15 | * @return 16 | */ 17 | List listByUidAndToUid(@Param(value = "uid") Long uid, 18 | @Param(value = "toUid") Long toUid, 19 | @Param(value = "offset") Integer offset, 20 | @Param(value = "limit") Integer limit); 21 | 22 | /** 23 | * 插入 24 | * 25 | * @return 26 | */ 27 | boolean insertUserFriendMsg(UserFriendMsg userFriendMsg); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/dao/user/UserProfileDao.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.dao.user; 2 | 3 | import com.lmxdawn.him.common.entity.user.UserProfile; 4 | import org.apache.ibatis.annotations.Mapper; 5 | 6 | import java.util.List; 7 | 8 | @Mapper 9 | public interface UserProfileDao { 10 | 11 | /** 12 | * 根据Uid查询 13 | * 14 | * @param uid 15 | * @return 16 | */ 17 | UserProfile findByUid(Long uid); 18 | 19 | /** 20 | * 根据Uid查询 21 | * 22 | * @param uids 23 | * @return 24 | */ 25 | List listByUidIn(List uids); 26 | 27 | /** 28 | * 插入 29 | * 30 | * @param userProfile 31 | * @return 32 | */ 33 | boolean insertUserProfile(UserProfile userProfile); 34 | 35 | /** 36 | * 批量插入 37 | * 38 | * @param userProfiles 39 | * @return 40 | */ 41 | boolean insertUserProfileAll(List userProfiles); 42 | 43 | /** 44 | * 更新 45 | * 46 | * @return 47 | */ 48 | boolean updateUserProfile(UserProfile userProfile); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/dao/user/UserQqDao.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.dao.user; 2 | 3 | import com.lmxdawn.him.common.entity.user.UserQq; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | @Mapper 8 | public interface UserQqDao { 9 | 10 | /** 11 | * 根据Uid查询 12 | * @param openId 13 | * @return 14 | */ 15 | UserQq findByOpenId(@Param("openId") String openId); 16 | 17 | /** 18 | * 插入 19 | * @param userQq 20 | * @return 21 | */ 22 | boolean insertUserQq(UserQq userQq); 23 | 24 | /** 25 | * 删除 26 | * @param uid 27 | * @return 28 | */ 29 | boolean deleteByUid(@Param("uid") Long uid); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/dto/UserLoginDTO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 用户登录 7 | */ 8 | @Data 9 | public class UserLoginDTO { 10 | 11 | private Long uid; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/exception/JsonException.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.exception; 2 | 3 | import com.lmxdawn.him.common.enums.ResultEnum; 4 | import lombok.Getter; 5 | 6 | /** 7 | * 错误处理类 8 | */ 9 | @Getter 10 | public class JsonException extends RuntimeException{ 11 | 12 | private Integer code; 13 | 14 | public JsonException(ResultEnum resultEnum) { 15 | super(resultEnum.getMessage()); 16 | this.code = resultEnum.getCode(); 17 | } 18 | 19 | public JsonException(ResultEnum resultEnum, String message) { 20 | super(message); 21 | this.code = resultEnum.getCode(); 22 | } 23 | 24 | public JsonException(Integer code, String message) { 25 | super(message); 26 | this.code = code; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/filter/CorsFilter.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.filter; 2 | 3 | import com.lmxdawn.him.api.config.CorsConfig; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | 6 | import javax.servlet.*; 7 | import javax.servlet.annotation.WebFilter; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | 11 | /** 12 | * 跨域拦截设置 13 | */ 14 | @WebFilter(urlPatterns = "/*", filterName = "corsFilter") 15 | public class CorsFilter implements Filter { 16 | 17 | @Autowired 18 | private CorsConfig corsConfig; 19 | 20 | @Override 21 | public void destroy() { 22 | 23 | } 24 | 25 | @Override 26 | public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 27 | throws IOException, ServletException { 28 | HttpServletResponse response = (HttpServletResponse) res; 29 | response.setHeader("Access-Control-Allow-Origin", corsConfig.getAllowedOrigins()); 30 | response.setHeader("Access-Control-Allow-Methods", corsConfig.getAllowedMethods()); 31 | 32 | response.setHeader("Access-Control-Allow-Headers", corsConfig.getAllowedHeaders()); 33 | if ("true".equals(corsConfig.getAllowedCredentials())) { 34 | response.setHeader("Access-Control-Allow-Credentials", "true"); 35 | } 36 | chain.doFilter(req, res); 37 | } 38 | 39 | @Override 40 | public void init(FilterConfig arg0) throws ServletException { 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/handler/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.handler; 2 | 3 | import com.lmxdawn.him.api.exception.JsonException; 4 | import com.lmxdawn.him.common.enums.ResultEnum; 5 | import com.lmxdawn.him.common.utils.ResultVOUtils; 6 | import com.lmxdawn.him.common.vo.res.BaseResVO; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.web.bind.annotation.ExceptionHandler; 9 | import org.springframework.web.bind.annotation.RestControllerAdvice; 10 | 11 | /** 12 | * 错误回调 13 | */ 14 | @RestControllerAdvice 15 | @Slf4j 16 | public class GlobalExceptionHandler { 17 | 18 | // 拦截API异常 19 | @ExceptionHandler(value = JsonException.class) 20 | public BaseResVO handlerJsonException(JsonException e) { 21 | // 返回对应的错误信息 22 | return ResultVOUtils.error(e.getCode(), e.getMessage()); 23 | } 24 | 25 | // 拦截API异常 26 | @ExceptionHandler(value = RuntimeException.class) 27 | public BaseResVO handlerRuntimeException(RuntimeException e) { 28 | log.error(e.getMessage()); 29 | // 返回对应的错误信息 30 | return ResultVOUtils.error(ResultEnum.NOT_NETWORK); 31 | } 32 | 33 | // 拦截API异常 34 | @ExceptionHandler(value = Exception.class) 35 | public BaseResVO handlerRuntimeException(Exception e) { 36 | log.error(e.getMessage()); 37 | return ResultVOUtils.error(ResultEnum.NOT_NETWORK, "Request resource not found."); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/group/GroupMsgService.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.group; 2 | 3 | import com.lmxdawn.him.common.entity.group.GroupMsg; 4 | 5 | import java.util.Date; 6 | import java.util.List; 7 | 8 | public interface GroupMsgService { 9 | 10 | List listByGroupIdAndCreateTime(Long groupId, Date createTime, Integer page, Integer limit); 11 | 12 | boolean insertGroupMsg(GroupMsg groupMsg); 13 | 14 | boolean sendGroupMsg(Long uid, Long groupId, Integer type, Integer msgType, String msgContent); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/group/GroupService.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.group; 2 | 3 | import com.lmxdawn.him.common.entity.group.Group; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | public interface GroupService { 9 | 10 | Group findByGroupId(Long groupId); 11 | 12 | Map listByGroupIdIn(List groupIds); 13 | 14 | boolean insertGroup(Group group); 15 | 16 | boolean updateGroup(Group group); 17 | 18 | boolean incMemberNumByGroupId(Long groupId, Integer memberNum); 19 | 20 | boolean decMemberNumByGroupId(Long groupId); 21 | 22 | boolean deleteByGroupId(Long groupId); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/group/GroupUserService.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.group; 2 | 3 | import com.lmxdawn.him.common.entity.group.GroupUser; 4 | 5 | import java.util.List; 6 | 7 | public interface GroupUserService { 8 | 9 | /** 10 | * 查询群用户信息 11 | * @return 12 | */ 13 | GroupUser findByGroupIdAndUid(Long groupId, Long uid); 14 | 15 | /** 16 | * 查询群的用户列表 17 | * @return 18 | */ 19 | List listByGroupId(Long groupId, Integer page, Integer limit); 20 | 21 | /** 22 | * 查询用户的群列表 23 | * @return 24 | */ 25 | List listByUid(Long uid, Integer page, Integer limit); 26 | 27 | /** 28 | * 插入 29 | * @return 30 | */ 31 | boolean insertGroupUser(GroupUser groupUser); 32 | 33 | /** 34 | * 更新 35 | * @return 36 | */ 37 | boolean updateGroupUserByGroupIdAndUid(GroupUser groupUser); 38 | 39 | /** 40 | * 清空未读消息 41 | * @return 42 | */ 43 | boolean clearUnMsgCountByGroupIdAndUid(GroupUser groupUser); 44 | 45 | /** 46 | * 根据群ID更新 47 | * @return 48 | */ 49 | boolean updateGroupUserByGroupId(GroupUser groupUser); 50 | 51 | /** 52 | * 删除 53 | * @return 54 | */ 55 | boolean deleteByGroupIdAndUid(Long groupId, Long uid); 56 | 57 | /** 58 | * 删除 59 | * @return 60 | */ 61 | boolean deleteByGroupId(Long groupId); 62 | 63 | } 64 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/group/impl/GroupMsgServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.group.impl; 2 | 3 | import com.lmxdawn.him.api.constant.WSResTypeConstant; 4 | import com.lmxdawn.him.api.dao.group.GroupMsgDao; 5 | import com.lmxdawn.him.api.constant.WSMsgTypeConstant; 6 | import com.lmxdawn.him.api.service.group.GroupMsgService; 7 | import com.lmxdawn.him.api.service.group.GroupUserService; 8 | import com.lmxdawn.him.api.service.user.UserService; 9 | import com.lmxdawn.him.api.utils.PageUtils; 10 | import com.lmxdawn.him.api.utils.WSBaseReqUtils; 11 | import com.lmxdawn.him.api.vo.req.WSBaseReqVO; 12 | import com.lmxdawn.him.api.ws.WSServer; 13 | import com.lmxdawn.him.common.entity.group.GroupMsg; 14 | import com.lmxdawn.him.common.entity.group.GroupUser; 15 | import com.lmxdawn.him.common.entity.user.User; 16 | import org.springframework.stereotype.Service; 17 | 18 | import javax.annotation.Resource; 19 | import java.util.Date; 20 | import java.util.List; 21 | 22 | @Service 23 | public class GroupMsgServiceImpl implements GroupMsgService { 24 | 25 | @Resource 26 | private GroupMsgDao groupMsgDao; 27 | 28 | @Resource 29 | private GroupUserService groupUserService; 30 | 31 | @Resource 32 | private UserService userService; 33 | 34 | @Resource 35 | private WSServer wsServer; 36 | 37 | @Override 38 | public List listByGroupIdAndCreateTime(Long groupId, Date createTime, Integer page, Integer limit) { 39 | Integer offset = PageUtils.createOffset(page, limit); 40 | return groupMsgDao.listByGroupIdAndCreateTime(groupId, createTime, offset, limit); 41 | } 42 | 43 | @Override 44 | public boolean insertGroupMsg(GroupMsg groupMsg) { 45 | groupMsg.setCreateTime(new Date()); 46 | groupMsg.setModifiedTime(new Date()); 47 | return groupMsgDao.insertGroupMsg(groupMsg); 48 | } 49 | 50 | @Override 51 | public boolean sendGroupMsg(Long uid, Long groupId, Integer type, Integer msgType, String msgContent) { 52 | String lastMsgContent = msgContent; 53 | GroupMsg groupMsg = new GroupMsg(); 54 | groupMsg.setGroupId(groupId); 55 | groupMsg.setSenderUid(uid); 56 | groupMsg.setMsgType(msgType); 57 | groupMsg.setMsgContent(msgContent); 58 | switch (msgType) { 59 | case WSMsgTypeConstant.TEXT: 60 | break; 61 | case WSMsgTypeConstant.IMAGE: 62 | lastMsgContent = "[图片消息]"; 63 | break; 64 | case WSMsgTypeConstant.FILE: 65 | lastMsgContent = "[文件消息]"; 66 | break; 67 | case WSMsgTypeConstant.VOICE: 68 | lastMsgContent = "[语言消息]"; 69 | break; 70 | case WSMsgTypeConstant.VIDEO: 71 | lastMsgContent = "[视频消息]"; 72 | break; 73 | default: 74 | // 位置类型 75 | return false; 76 | } 77 | 78 | boolean b = insertGroupMsg(groupMsg); 79 | if (!b) { 80 | return false; 81 | } 82 | 83 | // 保存离线消息 84 | GroupUser groupUser = new GroupUser(); 85 | groupUser.setGroupId(groupId); 86 | groupUser.setLastMsgContent(lastMsgContent); 87 | groupUser.setLastMsgTime(new Date()); 88 | groupUser.setUnMsgCount(1); 89 | boolean b1 = groupUserService.updateGroupUserByGroupId(groupUser); 90 | 91 | // 发送在线消息 92 | // 查询用户信息 93 | User user = userService.findByUid(uid); 94 | Long sUid = user.getUid(); 95 | String name = user.getName(); 96 | String avatar = user.getAvatar(); 97 | String remark = user.getRemark(); 98 | WSBaseReqVO wsBaseReqVO = WSBaseReqUtils.create(type, groupId, msgType, msgContent, sUid, name, avatar, remark); 99 | 100 | // 查找群里的所有用户信息 101 | List groupUsers = groupUserService.listByGroupId(groupId, 1, 500); 102 | 103 | groupUsers.forEach(v -> { 104 | // 排除自己 105 | if (!uid.equals(v.getUid())) { 106 | wsServer.sendMsg(v.getUid(), wsBaseReqVO); 107 | } 108 | }); 109 | 110 | return true; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/group/impl/GroupServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.group.impl; 2 | 3 | import com.lmxdawn.him.api.dao.group.GroupDao; 4 | import com.lmxdawn.him.api.service.group.GroupService; 5 | import com.lmxdawn.him.common.entity.group.Group; 6 | import org.springframework.beans.BeanUtils; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.annotation.Resource; 10 | import java.util.Date; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | @Service 16 | public class GroupServiceImpl implements GroupService { 17 | 18 | @Resource 19 | private GroupDao groupDao; 20 | 21 | @Override 22 | public Group findByGroupId(Long groupId) { 23 | return groupDao.findByGroupId(groupId); 24 | } 25 | 26 | @Override 27 | public Map listByGroupIdIn(List groupIds) { 28 | Map groupMaps = new HashMap<>(); 29 | List groupList = groupDao.listByGroupIdIn(groupIds); 30 | groupList.forEach(v -> { 31 | groupMaps.put(v.getGroupId(), v); 32 | }); 33 | return groupMaps; 34 | } 35 | 36 | @Override 37 | public boolean insertGroup(Group group) { 38 | group.setCreateTime(new Date()); 39 | group.setModifiedTime(new Date()); 40 | return groupDao.insertGroup(group); 41 | } 42 | 43 | @Override 44 | public boolean updateGroup(Group group) { 45 | group.setModifiedTime(new Date()); 46 | return groupDao.updateGroup(group); 47 | } 48 | 49 | @Override 50 | public boolean incMemberNumByGroupId(Long groupId, Integer memberNum) { 51 | return groupDao.incMemberNumByGroupId(groupId, memberNum); 52 | } 53 | 54 | @Override 55 | public boolean decMemberNumByGroupId(Long groupId) { 56 | return groupDao.decMemberNumByGroupId(groupId); 57 | } 58 | 59 | @Override 60 | public boolean deleteByGroupId(Long groupId) { 61 | return groupDao.deleteByGroupId(groupId); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/group/impl/GroupUserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.group.impl; 2 | 3 | import com.lmxdawn.him.api.dao.group.GroupUserDao; 4 | import com.lmxdawn.him.api.service.group.GroupUserService; 5 | import com.lmxdawn.him.api.utils.PageUtils; 6 | import com.lmxdawn.him.common.entity.group.GroupUser; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.annotation.Resource; 10 | import java.util.Date; 11 | import java.util.List; 12 | 13 | @Service 14 | public class GroupUserServiceImpl implements GroupUserService { 15 | 16 | @Resource 17 | private GroupUserDao groupUserDao; 18 | 19 | @Override 20 | public GroupUser findByGroupIdAndUid(Long groupId, Long uid) { 21 | return groupUserDao.findByGroupIdAndUid(groupId, uid); 22 | } 23 | 24 | @Override 25 | public List listByGroupId(Long groupId, Integer page, Integer limit) { 26 | Integer offset = PageUtils.createOffset(page, limit); 27 | return groupUserDao.listByGroupId(groupId, offset, limit); 28 | } 29 | 30 | @Override 31 | public List listByUid(Long uid, Integer page, Integer limit) { 32 | Integer offset = PageUtils.createOffset(page, limit); 33 | return groupUserDao.listByUid(uid, offset, limit); 34 | } 35 | 36 | @Override 37 | public boolean insertGroupUser(GroupUser groupUser) { 38 | groupUser.setCreateTime(new Date()); 39 | groupUser.setModifiedTime(new Date()); 40 | return groupUserDao.insertGroupUser(groupUser); 41 | } 42 | 43 | @Override 44 | public boolean updateGroupUserByGroupIdAndUid(GroupUser groupUser) { 45 | groupUser.setModifiedTime(new Date()); 46 | return groupUserDao.updateGroupUserByGroupIdAndUid(groupUser); 47 | } 48 | 49 | @Override 50 | public boolean clearUnMsgCountByGroupIdAndUid(GroupUser groupUser) { 51 | groupUser.setModifiedTime(new Date()); 52 | return groupUserDao.clearUnMsgCountByGroupIdAndUid(groupUser); 53 | } 54 | 55 | @Override 56 | public boolean updateGroupUserByGroupId(GroupUser groupUser) { 57 | groupUser.setModifiedTime(new Date()); 58 | return groupUserDao.updateGroupUserByGroupId(groupUser); 59 | } 60 | 61 | @Override 62 | public boolean deleteByGroupIdAndUid(Long groupId, Long uid) { 63 | return groupUserDao.deleteByGroupIdAndUid(groupId, uid); 64 | } 65 | 66 | @Override 67 | public boolean deleteByGroupId(Long groupId) { 68 | return groupUserDao.deleteByGroupId(groupId); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/other/QqWebAuthService.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.other; 2 | 3 | import com.lmxdawn.him.api.vo.res.QqOpenIdResVO; 4 | import com.lmxdawn.him.api.vo.res.QqUserInfoResVO; 5 | 6 | public interface QqWebAuthService { 7 | 8 | /** 9 | * 获取 access_token 10 | * 11 | * @return 12 | */ 13 | public String getAccessToken(String code, String redirect_uri) ; 14 | 15 | /** 16 | * 获取 openID 17 | * 18 | * @return 19 | */ 20 | public QqOpenIdResVO getOpenID(String accessToken) ; 21 | 22 | /** 23 | * 获取用户信息 24 | * @return 25 | */ 26 | public QqUserInfoResVO getUserInfo(String code, String redirect_uri); 27 | } 28 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/other/impl/QqWebAuthServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.other.impl; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.lmxdawn.him.api.service.other.QqWebAuthService; 5 | import com.lmxdawn.him.api.utils.OkHttpUtil; 6 | import com.lmxdawn.him.api.vo.res.QqOpenIdResVO; 7 | import com.lmxdawn.him.api.vo.res.QqUserInfoResVO; 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | @Service 15 | public class QqWebAuthServiceImpl implements QqWebAuthService { 16 | 17 | 18 | @Value("${qq.auth.appid}") 19 | private String appid; 20 | 21 | @Value("${qq.auth.appkey}") 22 | private String appkey; 23 | 24 | @Override 25 | public String getAccessToken(String code, String redirect_uri) { 26 | Map map = new HashMap<>(); 27 | map.put("grant_type", "authorization_code"); 28 | map.put("client_id", appid); 29 | map.put("client_secret", appkey); 30 | map.put("code", code); 31 | map.put("redirect_uri", redirect_uri); 32 | String url = "https://graph.qq.com/oauth2.0/token"; 33 | String res = OkHttpUtil.get(url, map); 34 | if (res.contains("callback")) { 35 | return null; 36 | } 37 | String[] split = res.split("&"); 38 | return split[0].toString().split("=")[1].toString(); 39 | } 40 | 41 | @Override 42 | public QqOpenIdResVO getOpenID(String accessToken) { 43 | Map map = new HashMap<>(); 44 | map.put("access_token", accessToken); 45 | String url = "https://graph.qq.com/oauth2.0/me"; 46 | String res = OkHttpUtil.get(url, map); 47 | if (!res.contains("callback")) { 48 | return null; 49 | } 50 | 51 | int indexOf1 = res.indexOf("("); 52 | int indexOf2 = res.indexOf(")"); 53 | String json = res.substring(indexOf1 + 1, indexOf2); 54 | return JSON.parseObject(json, QqOpenIdResVO.class); 55 | } 56 | 57 | @Override 58 | public QqUserInfoResVO getUserInfo(String accessToken, String openID) { 59 | 60 | Map map = new HashMap<>(); 61 | map.put("access_token", accessToken); 62 | map.put("oauth_consumer_key", appid); 63 | map.put("openid", openID); 64 | String url = "https://graph.qq.com/user/get_user_info"; 65 | String json = OkHttpUtil.get(url, map); 66 | QqUserInfoResVO qqUserInfoResVO = JSON.parseObject(json, QqUserInfoResVO.class); 67 | if (null == qqUserInfoResVO.getRet() || qqUserInfoResVO.getRet() != 0) { 68 | return null; 69 | } 70 | return qqUserInfoResVO; 71 | } 72 | 73 | // 测试 QQ返回的数据能不能解析成功 74 | public static void main(String[] args) { 75 | 76 | String res = "callback( {\"client_id\":\"YOUR_APPID\",\"openid\":\"YOUR_OPENID\"} );"; 77 | int indexOf1 = res.indexOf("("); 78 | int indexOf2 = res.indexOf(")"); 79 | String json = res.substring(indexOf1 + 1, indexOf2); 80 | System.out.println(json); 81 | QqOpenIdResVO qqOpenIdResVO = JSON.parseObject(json, QqOpenIdResVO.class); 82 | 83 | System.out.println(qqOpenIdResVO.getOpenid()); 84 | 85 | res = "access_token=FE04************************CCE2&expires_in=7776000&refresh_token=88E4************************BE14"; 86 | String[] split = res.split("&"); 87 | String accessToken = split[0].toString().split("=")[1]; 88 | System.out.println(accessToken); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/user/UserFriendAskService.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user; 2 | 3 | import com.lmxdawn.him.common.entity.user.UserFriendAsk; 4 | 5 | import java.util.List; 6 | 7 | public interface UserFriendAskService { 8 | 9 | List listByUid(Long uid, Integer page, Integer limit); 10 | 11 | UserFriendAsk findById(Long id); 12 | 13 | boolean insertUserFriendAsk(UserFriendAsk userFriendAsk); 14 | 15 | boolean updateUserFriendAsk(UserFriendAsk userFriendAsk); 16 | 17 | boolean deleteById(Long id); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/user/UserFriendMsgService.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user; 2 | 3 | import com.lmxdawn.him.common.entity.user.UserFriendMsg; 4 | 5 | import java.util.List; 6 | 7 | public interface UserFriendMsgService { 8 | 9 | List listByUidAndToUid(Long uid, Long toUid, Integer offset, Integer limit); 10 | 11 | boolean insertUserFriendMsg(UserFriendMsg userFriendMsg); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/user/UserFriendService.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user; 2 | 3 | import com.lmxdawn.him.common.entity.user.UserFriend; 4 | 5 | import java.util.List; 6 | 7 | public interface UserFriendService { 8 | 9 | List listByUid(Long uid, Integer page, Integer limit); 10 | 11 | UserFriend findByUidAndFriendUid(Long uid, Long friendUid); 12 | 13 | boolean insertUserFriendAll(List userFriends); 14 | 15 | boolean updateUserFriend(UserFriend userFriend); 16 | 17 | boolean deleteByUidAndFriendUid(Long uid, Long friendUid); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/user/UserProfileService.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user; 2 | 3 | import com.lmxdawn.him.common.entity.user.UserProfile; 4 | 5 | import java.util.List; 6 | 7 | public interface UserProfileService { 8 | 9 | UserProfile findByUid(Long uid); 10 | 11 | List listByUidIn(List uids); 12 | 13 | boolean incFriendAskCount(Long uid, Integer count); 14 | 15 | boolean incFriendCountAll(List userProfiles); 16 | 17 | boolean clearFriendAskCount(Long uid); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/user/UserQqService.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user; 2 | 3 | import com.lmxdawn.him.common.entity.user.UserQq; 4 | 5 | public interface UserQqService { 6 | 7 | /** 8 | * 根据Uid查询 9 | * @param openId 10 | * @return 11 | */ 12 | UserQq findByOpenId(String openId); 13 | 14 | /** 15 | * 插入 16 | * @param userQq 17 | * @return 18 | */ 19 | boolean insertUserQq(UserQq userQq); 20 | 21 | /** 22 | * 删除 23 | * @param uid 24 | * @return 25 | */ 26 | boolean deleteByUid(Long uid); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/user/UserService.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user; 2 | 3 | import com.lmxdawn.him.api.vo.res.UserInfoListResVO; 4 | import com.lmxdawn.him.common.entity.user.User; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | public interface UserService { 10 | 11 | User findByUid(Long uid); 12 | 13 | User findPwdByUid(Long uid); 14 | 15 | Map listByUidIn(List uids); 16 | 17 | boolean insertUser(User user); 18 | 19 | boolean updateUser(User user); 20 | 21 | boolean deleteByUid(Long uid); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/user/impl/UserFriendAskServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user.impl; 2 | 3 | import com.lmxdawn.him.api.dao.user.UserFriendAskDao; 4 | import com.lmxdawn.him.api.service.user.UserFriendAskService; 5 | import com.lmxdawn.him.api.utils.PageUtils; 6 | import com.lmxdawn.him.common.entity.user.UserFriendAsk; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.annotation.Resource; 10 | import java.util.Date; 11 | import java.util.List; 12 | 13 | @Service 14 | public class UserFriendAskServiceImpl implements UserFriendAskService { 15 | 16 | @Resource 17 | private UserFriendAskDao userFriendAskDao; 18 | 19 | @Override 20 | public List listByUid(Long uid, Integer page, Integer limit) { 21 | Integer offset = PageUtils.createOffset(page, limit); 22 | return userFriendAskDao.listByUid(uid, offset, limit); 23 | } 24 | 25 | @Override 26 | public UserFriendAsk findById(Long id) { 27 | return userFriendAskDao.findById(id); 28 | } 29 | 30 | @Override 31 | public boolean insertUserFriendAsk(UserFriendAsk userFriendAsk) { 32 | userFriendAsk.setCreateTime(new Date()); 33 | userFriendAsk.setModifiedTime(new Date()); 34 | return userFriendAskDao.insertUserFriendAsk(userFriendAsk); 35 | } 36 | 37 | @Override 38 | public boolean updateUserFriendAsk(UserFriendAsk userFriendAsk) { 39 | userFriendAsk.setModifiedTime(new Date()); 40 | return userFriendAskDao.updateUserFriendAsk(userFriendAsk); 41 | } 42 | 43 | @Override 44 | public boolean deleteById(Long id) { 45 | return userFriendAskDao.deleteById(id); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/user/impl/UserFriendMsgServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user.impl; 2 | 3 | import com.lmxdawn.him.api.dao.user.UserFriendMsgDao; 4 | import com.lmxdawn.him.api.service.user.UserFriendMsgService; 5 | import com.lmxdawn.him.common.entity.user.UserFriendMsg; 6 | import org.springframework.stereotype.Service; 7 | 8 | import javax.annotation.Resource; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | @Service 13 | public class UserFriendMsgServiceImpl implements UserFriendMsgService { 14 | 15 | @Resource 16 | private UserFriendMsgDao userFriendMsgDao; 17 | 18 | @Override 19 | public List listByUidAndToUid(Long uid, Long toUid, Integer offset, Integer limit) { 20 | return userFriendMsgDao.listByUidAndToUid(uid, toUid, offset, limit); 21 | } 22 | 23 | @Override 24 | public boolean insertUserFriendMsg(UserFriendMsg userFriendMsg) { 25 | userFriendMsg.setCreateTime(new Date()); 26 | return userFriendMsgDao.insertUserFriendMsg(userFriendMsg); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/user/impl/UserFriendServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user.impl; 2 | 3 | import com.lmxdawn.him.api.dao.user.UserFriendDao; 4 | import com.lmxdawn.him.api.service.user.UserFriendService; 5 | import com.lmxdawn.him.api.utils.PageUtils; 6 | import com.lmxdawn.him.common.entity.user.UserFriend; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.annotation.Resource; 10 | import java.util.Date; 11 | import java.util.List; 12 | 13 | @Service 14 | public class UserFriendServiceImpl implements UserFriendService { 15 | 16 | @Resource 17 | private UserFriendDao userFriendDao; 18 | 19 | @Override 20 | public List listByUid(Long uid, Integer page, Integer limit) { 21 | Integer offset = PageUtils.createOffset(page, limit); 22 | return userFriendDao.listByUid(uid, offset, limit); 23 | } 24 | 25 | @Override 26 | public UserFriend findByUidAndFriendUid(Long uid, Long friendUid) { 27 | return userFriendDao.findByUidAndFriendUid(uid, friendUid); 28 | } 29 | 30 | @Override 31 | public boolean insertUserFriendAll(List userFriends) { 32 | return userFriendDao.insertUserFriendAll(userFriends); 33 | } 34 | 35 | @Override 36 | public boolean updateUserFriend(UserFriend userFriend) { 37 | userFriend.setModifiedTime(new Date()); 38 | return userFriendDao.updateUserFriend(userFriend); 39 | } 40 | 41 | @Override 42 | public boolean deleteByUidAndFriendUid(Long uid, Long friendUid) { 43 | return userFriendDao.deleteByUidAndFriendUid(uid, friendUid); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/user/impl/UserProfileServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user.impl; 2 | 3 | import com.lmxdawn.him.api.dao.user.UserProfileDao; 4 | import com.lmxdawn.him.api.service.user.UserProfileService; 5 | import com.lmxdawn.him.common.entity.user.UserProfile; 6 | import org.springframework.stereotype.Service; 7 | 8 | import javax.annotation.Resource; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | @Service 13 | public class UserProfileServiceImpl implements UserProfileService { 14 | 15 | @Resource 16 | private UserProfileDao userProfileDao; 17 | 18 | @Override 19 | public UserProfile findByUid(Long uid) { 20 | return userProfileDao.findByUid(uid); 21 | } 22 | 23 | @Override 24 | public List listByUidIn(List uids) { 25 | return userProfileDao.listByUidIn(uids); 26 | } 27 | 28 | /** 29 | * 增加好友请求数量 30 | * @param count 31 | * @return 32 | */ 33 | @Override 34 | public boolean incFriendAskCount(Long uid, Integer count) { 35 | UserProfile userProfile = new UserProfile(); 36 | userProfile.setUid(uid); 37 | userProfile.setFriendAskCount(count); 38 | userProfile.setCreateTime(new Date()); 39 | userProfile.setModifiedTime(new Date()); 40 | return userProfileDao.insertUserProfile(userProfile); 41 | } 42 | 43 | @Override 44 | public boolean incFriendCountAll(List userProfiles) { 45 | return userProfileDao.insertUserProfileAll(userProfiles); 46 | } 47 | 48 | /** 49 | * 清空好友请求数量 50 | * @return 51 | */ 52 | @Override 53 | public boolean clearFriendAskCount(Long uid) { 54 | UserProfile userProfile = new UserProfile(); 55 | userProfile.setUid(uid); 56 | userProfile.setFriendAskCount(0); 57 | userProfile.setModifiedTime(new Date()); 58 | return userProfileDao.updateUserProfile(userProfile); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/user/impl/UserQqServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user.impl; 2 | 3 | import com.lmxdawn.him.api.dao.user.UserQqDao; 4 | import com.lmxdawn.him.api.service.user.UserQqService; 5 | import com.lmxdawn.him.common.entity.user.UserQq; 6 | import org.springframework.stereotype.Service; 7 | 8 | import javax.annotation.Resource; 9 | import java.util.Date; 10 | 11 | @Service 12 | public class UserQqServiceImpl implements UserQqService { 13 | 14 | @Resource 15 | private UserQqDao userQqDao; 16 | 17 | @Override 18 | public UserQq findByOpenId(String openId) { 19 | return userQqDao.findByOpenId(openId); 20 | } 21 | 22 | @Override 23 | public boolean insertUserQq(UserQq userQq) { 24 | userQq.setCreateTime(new Date()); 25 | return userQqDao.insertUserQq(userQq); 26 | } 27 | 28 | @Override 29 | public boolean deleteByUid(Long uid) { 30 | return userQqDao.deleteByUid(uid); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/service/user/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user.impl; 2 | 3 | import com.lmxdawn.him.api.dao.user.UserDao; 4 | import com.lmxdawn.him.api.service.user.UserService; 5 | import com.lmxdawn.him.api.vo.res.UserInfoListResVO; 6 | import com.lmxdawn.him.common.entity.user.User; 7 | import org.springframework.beans.BeanUtils; 8 | import org.springframework.stereotype.Service; 9 | 10 | import javax.annotation.Resource; 11 | import java.util.*; 12 | import java.util.stream.Collectors; 13 | 14 | @Service 15 | public class UserServiceImpl implements UserService { 16 | 17 | @Resource 18 | private UserDao userDao; 19 | 20 | @Override 21 | public User findByUid(Long uid) { 22 | return userDao.findByUid(uid); 23 | } 24 | 25 | @Override 26 | public User findPwdByUid(Long uid) { 27 | return userDao.findPwdByUid(uid); 28 | } 29 | 30 | @Override 31 | public Map listByUidIn(List uids) { 32 | Map userInfoListResVOMap = new HashMap<>(); 33 | if (uids.size() == 0) { 34 | return userInfoListResVOMap; 35 | } 36 | List users = userDao.listByUidIn(uids); 37 | users.forEach(v -> { 38 | UserInfoListResVO userInfoListResVO = new UserInfoListResVO(); 39 | BeanUtils.copyProperties(v, userInfoListResVO); 40 | userInfoListResVOMap.put(v.getUid(), userInfoListResVO); 41 | }); 42 | return userInfoListResVOMap; 43 | } 44 | 45 | @Override 46 | public boolean insertUser(User user) { 47 | user.setCreateTime(new Date()); 48 | user.setModifiedTime(new Date()); 49 | return userDao.insertUser(user); 50 | } 51 | 52 | @Override 53 | public boolean updateUser(User user) { 54 | user.setModifiedTime(new Date()); 55 | return userDao.updateUser(user); 56 | } 57 | 58 | @Override 59 | public boolean deleteByUid(Long uid) { 60 | return userDao.deleteByUid(uid); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/utils/CacheUtils.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.utils; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.data.redis.core.RedisTemplate; 5 | import org.springframework.stereotype.Component; 6 | 7 | import javax.annotation.PostConstruct; 8 | import java.util.Collection; 9 | import java.util.Set; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | /** 13 | * 缓存操作类 14 | */ 15 | @Component 16 | public class CacheUtils { 17 | @Autowired 18 | private RedisTemplate redisTemplate; 19 | 20 | // 维护一个本类的静态变量 21 | private static CacheUtils cacheUtils; 22 | 23 | @PostConstruct 24 | public void init() { 25 | cacheUtils = this; 26 | cacheUtils.redisTemplate = this.redisTemplate; 27 | } 28 | 29 | /** 30 | * 将参数中的字符串值设置为键的值,不设置过期时间 31 | * @param key 32 | * @param value 必须要实现 Serializable 接口 33 | */ 34 | public static void set(String key, String value) { 35 | cacheUtils.redisTemplate.opsForValue().set(key, value); 36 | } 37 | 38 | /** 39 | * 将参数中的字符串值设置为键的值,设置过期时间 40 | * @param key 41 | * @param value 必须要实现 Serializable 接口 42 | * @param timeout 43 | */ 44 | public static void set(String key, String value, Long timeout) { 45 | cacheUtils.redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS); 46 | } 47 | 48 | /** 49 | * 获取与指定键相关的值 50 | * @param key 51 | * @return 52 | */ 53 | public static Object get(String key) { 54 | return cacheUtils.redisTemplate.opsForValue().get(key); 55 | } 56 | 57 | /** 58 | * 设置某个键的过期时间 59 | * @param key 键值 60 | * @param ttl 过期秒数 61 | */ 62 | public static boolean expire(String key, Long ttl) { 63 | return cacheUtils.redisTemplate.expire(key, ttl, TimeUnit.SECONDS); 64 | } 65 | 66 | /** 67 | * 判断某个键是否存在 68 | * @param key 键值 69 | */ 70 | public static boolean hasKey(String key) { 71 | return cacheUtils.redisTemplate.hasKey(key); 72 | } 73 | 74 | /** 75 | * 向集合添加元素 76 | * @param key 77 | * @param value 78 | * @return 返回值为设置成功的value数 79 | */ 80 | public static Long sAdd(String key, String... value) { 81 | return cacheUtils.redisTemplate.opsForSet().add(key, value); 82 | } 83 | 84 | /** 85 | * 获取集合中的某个元素 86 | * @param key 87 | * @return 返回值为redis中键值为key的value的Set集合 88 | */ 89 | public static Set sGetMembers(String key) { 90 | return cacheUtils.redisTemplate.opsForSet().members(key); 91 | } 92 | 93 | /** 94 | * 将给定分数的指定成员添加到键中存储的排序集合中 95 | * @param key 96 | * @param value 97 | * @param score 98 | * @return 99 | */ 100 | public static Boolean zAdd(String key, String value, double score) { 101 | return cacheUtils.redisTemplate.opsForZSet().add(key, value, score); 102 | } 103 | 104 | /** 105 | * 返回指定排序集中给定成员的分数 106 | * @param key 107 | * @param value 108 | * @return 109 | */ 110 | public static Double zScore(String key, String value) { 111 | return cacheUtils.redisTemplate.opsForZSet().score(key, value); 112 | } 113 | 114 | /** 115 | * 删除指定的键 116 | * @param key 117 | * @return 118 | */ 119 | public static Boolean delete(String key) { 120 | return cacheUtils.redisTemplate.delete(key); 121 | } 122 | 123 | /** 124 | * 删除多个键 125 | * @param keys 126 | * @return 127 | */ 128 | public static Long delete(Collection keys) { 129 | return cacheUtils.redisTemplate.delete(keys); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/utils/GroupUserUtils.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.utils; 2 | 3 | import io.jsonwebtoken.Claims; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * 群用户相关 10 | */ 11 | public class GroupUserUtils { 12 | 13 | /** 14 | * 创建群的验证码 15 | * @return 16 | */ 17 | public static String createCheckCode(Long groupId) { 18 | Map claims = new HashMap<>(); 19 | claims.put("gid", groupId); 20 | return JwtUtils.createToken(claims, null); // 不过期 21 | } 22 | 23 | /** 24 | * 验证 25 | * @param code 26 | * @return 27 | */ 28 | public static Long checkCode(String code) { 29 | 30 | if (null == code || "".equals(code)) { 31 | return null; 32 | } 33 | 34 | try { 35 | // 验证 token 36 | Claims claims = JwtUtils.parse(code); 37 | if (claims == null) { 38 | return null; 39 | } 40 | return Long.valueOf(claims.get("gid").toString()); 41 | 42 | } catch (Exception e) { 43 | return null; 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/utils/JwtUtils.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.utils; 2 | 3 | import io.jsonwebtoken.*; 4 | import org.apache.tomcat.util.codec.binary.Base64; 5 | 6 | import javax.crypto.SecretKey; 7 | import javax.crypto.spec.SecretKeySpec; 8 | import java.security.Key; 9 | import java.util.Date; 10 | import java.util.Map; 11 | 12 | /** 13 | * jwt 14 | */ 15 | public class JwtUtils { 16 | 17 | /** 18 | * 生成 token 19 | * 20 | * @param claims 自定义的 map 21 | * @param ttl 过期时间 22 | * @return 23 | */ 24 | public static String createToken(Map claims, Long ttl) { 25 | Key key = generateKey(); 26 | SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; 27 | Long nowMillis = System.currentTimeMillis(); //生成JWT的时间 28 | JwtBuilder builder = Jwts.builder() 29 | .setHeaderParam("typ", "JWT") //设置header 30 | .setHeaderParam("alg", "HS256") 31 | .setClaims(claims) //设置payload的键值对 32 | // .setIssuedAt(now) //设置iat 33 | // .setIssuer("vue-api") 34 | .signWith(signatureAlgorithm, key); //签名,需要算法和key 35 | if (ttl != null && ttl >= 0) { 36 | Long expMillis = nowMillis + ttl * 1000; 37 | Date exp = new Date(expMillis); 38 | builder.setExpiration(exp); //设置过期时间 39 | } 40 | return builder.compact(); 41 | } 42 | 43 | /** 44 | * 生成 token ,没有过期时间 45 | * 46 | * @param claims 自定义的 map 47 | * @return 48 | */ 49 | public static String createToken(Map claims) { 50 | return createToken(claims, null); 51 | } 52 | 53 | /** 54 | * 解密 jwt 55 | * @param jwt 创建的 jwt 字符串 56 | * @return 57 | */ 58 | public static Claims parse(String jwt) { 59 | 60 | if (jwt == null) { 61 | return null; 62 | } 63 | 64 | try { 65 | return Jwts.parser() 66 | .setSigningKey(generateKey()) //此处的key要与之前创建的key一致 67 | .parseClaimsJws(jwt) 68 | .getBody(); 69 | }catch (ExpiredJwtException e){ 70 | return null; 71 | } 72 | } 73 | 74 | /** 75 | * 获取 key 76 | * 77 | * @return 78 | */ 79 | private static SecretKey generateKey() { 80 | String stringKey = "hui-hui-im"; 81 | byte[] encodedKey = Base64.decodeBase64(stringKey); 82 | return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES"); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/utils/OkHttpUtil.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.utils; 2 | 3 | import java.io.IOException; 4 | import java.util.Map; 5 | 6 | import okhttp3.*; 7 | 8 | /** 9 | * 请求工具类 10 | **/ 11 | public class OkHttpUtil { 12 | 13 | /** 14 | * 根据map获取get请求参数 15 | * 16 | * @param queries 17 | * @return 18 | */ 19 | public static StringBuffer getQueryString(String url, Map queries) { 20 | StringBuffer sb = new StringBuffer(url); 21 | if (queries != null && queries.keySet().size() > 0) { 22 | boolean firstFlag = true; 23 | for (Object o : queries.entrySet()) { 24 | Map.Entry entry = (Map.Entry) o; 25 | if (firstFlag) { 26 | sb.append("?").append(entry.getKey()).append("=").append(entry.getValue()); 27 | firstFlag = false; 28 | } else { 29 | sb.append("&").append(entry.getKey()).append("=").append(entry.getValue()); 30 | } 31 | } 32 | } 33 | return sb; 34 | } 35 | 36 | /** 37 | * 调用okhttp的newCall方法 38 | * 39 | * @param request 40 | * @return 41 | */ 42 | private static String execNewCall(Request request) { 43 | OkHttpClient okHttpClient = SpringBeanFactoryUtils.getBean(OkHttpClient.class); 44 | 45 | ResponseBody body = null; 46 | try { 47 | Response response = okHttpClient.newCall(request).execute(); 48 | if (!response.isSuccessful()) { 49 | return ""; 50 | } 51 | body = response.body(); 52 | String json = ""; 53 | if (body != null) { 54 | json = body.string(); 55 | } 56 | return json; 57 | } catch (Exception exception) { 58 | return ""; 59 | } finally { 60 | if (body != null) { 61 | body.close(); 62 | } 63 | } 64 | 65 | } 66 | 67 | /** 68 | * get 69 | * 70 | * @param url 请求的url 71 | * @param queries 请求的参数,在浏览器?后面的数据,没有可以传null 72 | * @return 73 | */ 74 | public static String get(String url, Map queries) { 75 | StringBuffer sb = getQueryString(url, queries); 76 | Request request = new Request.Builder() 77 | .url(sb.toString()) 78 | .build(); 79 | return execNewCall(request); 80 | } 81 | 82 | /** 83 | * post 84 | * 85 | * @param url 请求的url 86 | * @param params post form 提交的参数 87 | * @return 请求成功 88 | */ 89 | public static String post(String url, Map params) { 90 | FormBody.Builder builder = new FormBody.Builder(); 91 | //添加参数 92 | if (params != null && params.keySet().size() > 0) { 93 | for (String key : params.keySet()) { 94 | builder.add(key, params.get(key)); 95 | } 96 | } 97 | Request request = new Request.Builder() 98 | .url(url) 99 | .post(builder.build()) 100 | .build(); 101 | return execNewCall(request); 102 | } 103 | 104 | 105 | /** 106 | * Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"} 107 | * 参数一:请求Url 108 | * 参数二:请求的JSON 109 | * 参数三:请求回调 110 | */ 111 | public static String postJson(String url, String jsonParams) { 112 | RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams); 113 | Request request = new Request.Builder() 114 | .url(url) 115 | .post(requestBody) 116 | .build(); 117 | return execNewCall(request); 118 | } 119 | 120 | /** 121 | * Post请求发送xml数据.... 122 | * 参数一:请求Url 123 | * 参数二:请求的xmlString 124 | * 参数三:请求回调 125 | */ 126 | public static String postXml(String url, String xml) { 127 | RequestBody requestBody = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml); 128 | Request request = new Request.Builder() 129 | .url(url) 130 | .post(requestBody) 131 | .build(); 132 | return execNewCall(request); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/utils/PageUtils.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.utils; 2 | 3 | /** 4 | * 分页工具类 5 | */ 6 | public class PageUtils { 7 | 8 | /** 9 | * 根据页数和每页显示条数返回 偏移量 10 | * @param page 11 | * @param limit 12 | * @return 13 | */ 14 | public static Integer createOffset(Integer page, Integer limit) { 15 | if (null == page || page <= 0) { 16 | page = 1; 17 | } 18 | if (null == limit || limit <= 0) { 19 | limit = 10; 20 | } 21 | return (page - 1) * limit; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/utils/PasswordUtils.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.utils; 2 | 3 | import org.springframework.util.DigestUtils; 4 | 5 | /** 6 | * 密码相关的工具类 7 | */ 8 | public class PasswordUtils { 9 | 10 | public static String md52md5(String pwd) { 11 | return DigestUtils.md5DigestAsHex(DigestUtils.md5DigestAsHex(pwd.getBytes()).getBytes()); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/utils/PublicFileUtils.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.utils; 2 | 3 | 4 | import com.lmxdawn.him.api.config.PublicFileUrlConfig; 5 | 6 | /** 7 | * 公共文件管理工具 8 | */ 9 | public class PublicFileUtils { 10 | 11 | public static String createUploadUrl(String filePath) { 12 | 13 | if (filePath == null || filePath.isEmpty()) { 14 | return ""; 15 | } 16 | 17 | if (filePath.indexOf("http") == 0 || filePath.indexOf("/") == 0) { 18 | return filePath; 19 | } 20 | 21 | return PublicFileUrlConfig.getDomain() + "/" + filePath; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/utils/SpringBeanFactoryUtils.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.utils; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public final class SpringBeanFactoryUtils implements ApplicationContextAware{ 10 | private static ApplicationContext context; 11 | 12 | public static T getBean(Class c){ 13 | return context.getBean(c); 14 | } 15 | 16 | 17 | public static T getBean(String name,Class clazz){ 18 | return context.getBean(name,clazz); 19 | } 20 | 21 | @Override 22 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 23 | context = applicationContext; 24 | } 25 | 26 | 27 | } -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/utils/UserFriendUtils.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.utils; 2 | 3 | import io.jsonwebtoken.Claims; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * 用户朋友相关 10 | */ 11 | public class UserFriendUtils { 12 | 13 | /** 14 | * 创建群的验证码 15 | * @return 16 | */ 17 | public static String createCheckCode(Long uid) { 18 | Map claims = new HashMap<>(); 19 | claims.put("uid", uid); 20 | return JwtUtils.createToken(claims, null); // 不过期 21 | } 22 | 23 | /** 24 | * 验证 25 | * @param code 26 | * @return 27 | */ 28 | public static Long checkCode(String code) { 29 | 30 | if (null == code || "".equals(code)) { 31 | return null; 32 | } 33 | 34 | try { 35 | // 验证 token 36 | Claims claims = JwtUtils.parse(code); 37 | if (claims == null) { 38 | return null; 39 | } 40 | return Long.valueOf(claims.get("uid").toString()); 41 | 42 | } catch (Exception e) { 43 | return null; 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/utils/UserLoginUtils.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.utils; 2 | 3 | import com.lmxdawn.him.api.dto.UserLoginDTO; 4 | import io.jsonwebtoken.Claims; 5 | 6 | import javax.servlet.http.Cookie; 7 | import javax.servlet.http.HttpServletRequest; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.Objects; 11 | 12 | /** 13 | * 用户登录工具类 14 | */ 15 | public class UserLoginUtils { 16 | 17 | /** 18 | * 创建 SID 19 | * @param uid 20 | * @return 21 | */ 22 | public static String createSid(Long uid, Long ttl) { 23 | Map claims = new HashMap<>(); 24 | claims.put("uid", uid); 25 | return JwtUtils.createToken(claims, ttl); // 一天后过期 26 | } 27 | 28 | /** 29 | * 创建 SID 没有过期时间 30 | * @param uid 31 | * @return 32 | */ 33 | public static String createSid(Long uid) { 34 | return createSid(uid, null); 35 | } 36 | 37 | /** 38 | * 通过token获取用户ID 39 | * @param token 40 | * @return 41 | */ 42 | public static Boolean checkToken(Long uid, String token) { 43 | if (token == null || token.isEmpty()) { 44 | return false; 45 | } 46 | try { 47 | // 验证 token 48 | Claims claims = JwtUtils.parse(token); 49 | if (claims == null) { 50 | return false; 51 | } 52 | Long jwtUid = Long.valueOf(claims.get("uid").toString()); 53 | if (uid.compareTo(jwtUid) != 0) { 54 | return false; 55 | } 56 | 57 | } catch (Exception e) { 58 | return false; 59 | } 60 | return true; 61 | } 62 | 63 | /** 64 | * 验证用户是否登录 65 | * @param request 66 | * @return 67 | */ 68 | public static UserLoginDTO check(HttpServletRequest request) { 69 | 70 | String sUid = request.getParameter("UID"); 71 | String token = request.getParameter("SID"); 72 | if (sUid == null || sUid.isEmpty() || token == null || token.isEmpty()) { 73 | Cookie[] cookies = request.getCookies(); 74 | if (cookies == null) { 75 | return null; 76 | } 77 | for (Cookie cookie : cookies) { 78 | if (cookie.getName().equals("UID")) { 79 | sUid = cookie.getValue(); 80 | } else if (cookie.getName().equals("SID")) { 81 | token = cookie.getValue(); 82 | } 83 | } 84 | } 85 | 86 | if (sUid == null || token == null) { 87 | return null; 88 | } 89 | 90 | Long uid = null; 91 | try { 92 | uid = Long.valueOf(sUid); 93 | }catch (Exception e){ 94 | return null; 95 | } 96 | 97 | if (!checkToken(uid, token)) { 98 | return null; 99 | } 100 | 101 | UserLoginDTO userLoginDTO = new UserLoginDTO(); 102 | 103 | userLoginDTO.setUid(uid); 104 | return userLoginDTO; 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/utils/WSBaseReqUtils.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.utils; 2 | 3 | import com.lmxdawn.him.api.vo.req.WSBaseReqVO; 4 | import com.lmxdawn.him.api.vo.req.WSMessageReqVO; 5 | import com.lmxdawn.him.api.vo.req.WSUserReqVO; 6 | 7 | public class WSBaseReqUtils { 8 | 9 | /** 10 | * 创建请求实体类 11 | * @return 12 | */ 13 | public static WSBaseReqVO create(Integer type, Long receiveId, Integer msgType, String msgContent, Long uid, String name, String avatar, String remark) { 14 | 15 | // 消息实体 16 | WSMessageReqVO wsMessageReqVO = new WSMessageReqVO(); 17 | wsMessageReqVO.setReceiveId(receiveId != null ? receiveId : 0); 18 | wsMessageReqVO.setMsgType(msgType != null ? msgType : 0); 19 | wsMessageReqVO.setMsgContent(msgContent); 20 | 21 | // 用户信息 22 | WSUserReqVO wsUserReqVO = new WSUserReqVO(); 23 | wsUserReqVO.setUid(uid != null ? uid : 0); 24 | wsUserReqVO.setName(name != null ? name : ""); 25 | wsUserReqVO.setAvatar(avatar != null ? avatar : ""); 26 | wsUserReqVO.setRemark(remark != null ? remark : ""); 27 | 28 | WSBaseReqVO wsBaseReqVO = new WSBaseReqVO(); 29 | wsBaseReqVO.setType(type != null ? type : 0); 30 | wsBaseReqVO.setMessage(wsMessageReqVO); 31 | wsBaseReqVO.setUser(wsUserReqVO); 32 | return wsBaseReqVO; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/req/GroupMsgCreateReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.req; 2 | 3 | import com.lmxdawn.him.common.vo.req.BaseReqVO; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import org.hibernate.validator.constraints.Length; 7 | 8 | import javax.validation.constraints.Max; 9 | import javax.validation.constraints.Min; 10 | import javax.validation.constraints.NotNull; 11 | 12 | /** 13 | * 创建群消息 14 | */ 15 | @EqualsAndHashCode(callSuper = true) 16 | @Data 17 | public class GroupMsgCreateReqVO extends BaseReqVO { 18 | 19 | /** 20 | * 群ID 21 | */ 22 | @NotNull(message = "参数错误~") 23 | @Min(value = 1, message = "参数错误~") 24 | private Long groupId; 25 | /** 26 | * 消息类型(0:普通文字消息,1:图片消息,2:文件消息,3:语音消息,4:视频消息) 27 | */ 28 | @NotNull(message = "参数错误~") 29 | @Min(value = 0, message = "参数错误~") 30 | @Max(value = 4, message = "参数错误~") 31 | private Integer msgType; 32 | /** 33 | * 消息内容 34 | */ 35 | @NotNull(message = "参数错误~") 36 | @Length(min = 1, max = 255, message = "参数错误~") 37 | private String msgContent; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/req/GroupSaveReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.req; 2 | 3 | import com.lmxdawn.him.common.vo.req.BaseLimitReqVO; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import org.hibernate.validator.constraints.Length; 7 | 8 | import javax.validation.constraints.NotEmpty; 9 | 10 | /** 11 | * 查询群里的用户列表 12 | */ 13 | @EqualsAndHashCode(callSuper = true) 14 | @Data 15 | public class GroupSaveReqVO extends BaseLimitReqVO { 16 | 17 | /** 18 | * 群ID 19 | */ 20 | private Long groupId; 21 | 22 | /** 23 | * 群昵称 24 | */ 25 | @NotEmpty(message = "参数错误~") 26 | @Length(min = 1, max = 255, message = "参数错误~") 27 | private String name; 28 | 29 | /**. 30 | * 群头像 31 | */ 32 | @Length(min = 0, max = 255, message = "参数错误~") 33 | private String avatar; 34 | 35 | /**. 36 | * 说明 37 | */ 38 | @Length(min = 0, max = 255, message = "参数错误~") 39 | private String remark; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/req/GroupUserListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.req; 2 | 3 | import com.lmxdawn.him.common.vo.req.BaseLimitReqVO; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | 7 | /** 8 | * 查询群里的用户列表 9 | */ 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | public class GroupUserListReqVO extends BaseLimitReqVO { 13 | 14 | /** 15 | * 群ID 16 | */ 17 | private Long groupId; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/req/GroupUserSaveReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.req; 2 | 3 | import com.lmxdawn.him.common.vo.req.BaseLimitReqVO; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import org.hibernate.validator.constraints.Length; 7 | 8 | import javax.validation.constraints.NotNull; 9 | 10 | /** 11 | * 查询群里的用户列表 12 | */ 13 | @EqualsAndHashCode(callSuper = true) 14 | @Data 15 | public class GroupUserSaveReqVO extends BaseLimitReqVO { 16 | 17 | /** 18 | * 群ID 19 | */ 20 | @NotNull(message = "参数错误~") 21 | private Long groupId; 22 | 23 | /**. 24 | * 说明 25 | */ 26 | @Length(min = 1, max = 255, message = "参数错误~") 27 | private String remark; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/req/UserFriendAskAckReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.req; 2 | 3 | import com.lmxdawn.him.common.vo.req.BaseReqVO; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | 7 | import javax.validation.constraints.NotNull; 8 | 9 | /** 10 | * 发起好友请求 11 | */ 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | public class UserFriendAskAckReqVO extends BaseReqVO { 15 | 16 | /** 17 | * 朋友的ID 18 | */ 19 | @NotNull(message = "参数错误!") 20 | private Long id; 21 | 22 | /** 23 | * 状态 24 | */ 25 | private Integer status; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/req/UserFriendDeleteReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.req; 2 | 3 | import com.lmxdawn.him.common.vo.req.BaseReqVO; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | 7 | import javax.validation.constraints.NotNull; 8 | 9 | /** 10 | * 删除好友 11 | */ 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | public class UserFriendDeleteReqVO extends BaseReqVO { 15 | 16 | /** 17 | * 朋友的ID 18 | */ 19 | @NotNull(message = "参数错误!") 20 | private Long friendUid; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/req/UserFriendMsgClearMsgCountReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.req; 2 | 3 | import com.lmxdawn.him.common.vo.req.BaseReqVO; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import org.hibernate.validator.constraints.Length; 7 | 8 | import javax.validation.constraints.Max; 9 | import javax.validation.constraints.Min; 10 | import javax.validation.constraints.NotNull; 11 | 12 | /** 13 | * 删除好友 14 | */ 15 | @EqualsAndHashCode(callSuper = true) 16 | @Data 17 | public class UserFriendMsgClearMsgCountReqVO extends BaseReqVO { 18 | 19 | /** 20 | * 消息接收方 21 | */ 22 | @NotNull(message = "参数错误~") 23 | @Min(value = 1, message = "参数错误~") 24 | private Long receiverUid; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/req/UserFriendMsgSaveReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.req; 2 | 3 | import com.lmxdawn.him.common.vo.req.BaseReqVO; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import org.hibernate.validator.constraints.Length; 7 | 8 | import javax.validation.constraints.Max; 9 | import javax.validation.constraints.Min; 10 | import javax.validation.constraints.NotNull; 11 | 12 | /** 13 | * 删除好友 14 | */ 15 | @EqualsAndHashCode(callSuper = true) 16 | @Data 17 | public class UserFriendMsgSaveReqVO extends BaseReqVO { 18 | 19 | /** 20 | * 消息接收方 21 | */ 22 | @NotNull(message = "参数错误~") 23 | @Min(value = 1, message = "参数错误~") 24 | private Long receiverUid; 25 | /** 26 | * 消息类型(0:普通文字消息,1:图片消息,2:文件消息,3:语音消息,4:视频消息) 27 | */ 28 | @NotNull(message = "参数错误~") 29 | @Min(value = 0, message = "参数错误~") 30 | @Max(value = 4, message = "参数错误~") 31 | private Integer msgType; 32 | /** 33 | * 消息内容 34 | */ 35 | @NotNull(message = "参数错误~") 36 | @Length(min = 1, max = 255, message = "参数错误~") 37 | private String msgContent; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/req/UserGroupListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.req; 2 | 3 | import com.lmxdawn.him.common.vo.req.BaseLimitReqVO; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | 7 | /** 8 | * 获取用户的群列表 9 | */ 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | public class UserGroupListReqVO extends BaseLimitReqVO { 13 | 14 | /** 15 | * 用户的ID 16 | */ 17 | private Long uid; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/req/UserLoginPwdReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.req; 2 | 3 | import com.lmxdawn.him.common.vo.req.BaseReqVO; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | 7 | import javax.validation.constraints.NotEmpty; 8 | import javax.validation.constraints.NotNull; 9 | 10 | /** 11 | * 密码登录 12 | */ 13 | @EqualsAndHashCode(callSuper = true) 14 | @Data 15 | public class UserLoginPwdReqVO extends BaseReqVO { 16 | 17 | @NotNull(message = "用户ID不能为空") 18 | private Long uid; 19 | 20 | /** 21 | * 密码 22 | */ 23 | @NotEmpty(message = "密码不能为空") 24 | private String pwd; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/req/WSBaseReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.req; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * websocket 通信的类 7 | */ 8 | @Data 9 | public class WSBaseReqVO { 10 | 11 | /** 12 | * 类型 13 | */ 14 | private Integer type; 15 | 16 | /** 17 | * 消息实体 18 | */ 19 | private WSMessageReqVO message; 20 | 21 | /** 22 | * 发送者用户信息 23 | */ 24 | private WSUserReqVO user; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/req/WSMessageReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.req; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * websocket 消息实体 7 | */ 8 | @Data 9 | public class WSMessageReqVO { 10 | 11 | /** 12 | * 接收者ID 13 | */ 14 | private Long receiveId; 15 | 16 | /** 17 | * 消息类型 18 | */ 19 | private Integer msgType; 20 | 21 | /** 22 | * 消息内容 23 | */ 24 | private String msgContent; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/req/WSUserReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.req; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * websocket 通信的用户信息 7 | */ 8 | @Data 9 | public class WSUserReqVO { 10 | /** 11 | * 用户id 12 | */ 13 | private Long uid; 14 | /** 15 | * 用户昵称 16 | */ 17 | private String name; 18 | /** 19 | * 用户头像 20 | */ 21 | private String avatar; 22 | /** 23 | * 个性签名 24 | */ 25 | private String remark; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/res/GroupIndexListResVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.res; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 查询群里的用户列表 7 | */ 8 | @Data 9 | public class GroupIndexListResVO { 10 | 11 | /** 12 | * 群ID 13 | */ 14 | private Long groupId; 15 | /** 16 | * 说明 17 | */ 18 | private Long remark; 19 | /** 20 | * 等级(0:普通成员,1:管理员,2:群主) 21 | */ 22 | private Integer rank; 23 | 24 | /** 25 | * 用户信息 26 | */ 27 | private UserInfoListResVO user; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/res/GroupMsgListResVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.res; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * 查询群里的用户列表 9 | */ 10 | @Data 11 | public class GroupMsgListResVO { 12 | 13 | /** 14 | * 消息ID 15 | */ 16 | private Long msgId; 17 | /** 18 | * 群ID 19 | */ 20 | private Long groupId; 21 | /** 22 | * 发送消息的用户ID 23 | */ 24 | private Long senderUid; 25 | /** 26 | * 消息类型(0:普通文字消息,1:图片消息,2:文件消息,3:语音消息,4:视频消息) 27 | */ 28 | private Integer msgType; 29 | /** 30 | * 消息内容 31 | */ 32 | private String msgContent; 33 | /** 34 | * 创建时间 35 | */ 36 | private Date createTime; 37 | /** 38 | * 更新时间 39 | */ 40 | private Date modifiedTime; 41 | 42 | /** 43 | * 用户信息 44 | */ 45 | private UserInfoListResVO user; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/res/GroupUserListResVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.res; 2 | 3 | import com.lmxdawn.him.common.entity.group.Group; 4 | import lombok.Data; 5 | 6 | import java.util.Date; 7 | 8 | 9 | /** 10 | * 用户朋友列表信息 11 | */ 12 | @Data 13 | public class GroupUserListResVO { 14 | 15 | /** 16 | * 自增ID 17 | */ 18 | private Long id; 19 | 20 | /** 21 | * 群ID 22 | */ 23 | private Long groupId; 24 | 25 | /** 26 | * 用户id 27 | */ 28 | private Long uid; 29 | /** 30 | * 群内名称 31 | */ 32 | private String remark; 33 | /** 34 | * 最后一次确认的消息ID 35 | */ 36 | private Long lastAckMsgId; 37 | /** 38 | * 最后一次的消息内容 39 | */ 40 | private String lastMsgContent; 41 | /** 42 | * 最后一次的消息的时间 43 | */ 44 | private Date lastMsgTime; 45 | /** 46 | * 未读消息数量 47 | */ 48 | private Integer unMsgCount; 49 | /** 50 | * 等级(0:普通成员,1:管理员,2:群主) 51 | */ 52 | private Integer rank; 53 | 54 | /** 55 | * 群信息 56 | */ 57 | private Group group; 58 | 59 | } 60 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/res/QqOpenIdResVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.res; 2 | 3 | /** 4 | * QQ 授权获取 openID 5 | */ 6 | public class QqOpenIdResVO { 7 | 8 | /** 9 | * client_id : YOUR_APPID 10 | * openid : YOUR_OPENID 11 | */ 12 | 13 | private String client_id; 14 | private String openid; 15 | 16 | public String getClient_id() { 17 | return client_id; 18 | } 19 | 20 | public void setClient_id(String client_id) { 21 | this.client_id = client_id; 22 | } 23 | 24 | public String getOpenid() { 25 | return openid; 26 | } 27 | 28 | public void setOpenid(String openid) { 29 | this.openid = openid; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/res/QqUserInfoResVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.res; 2 | 3 | /** 4 | * QQ 授权获取 userInfo 5 | */ 6 | public class QqUserInfoResVO { 7 | 8 | /** 9 | * ret : 0 10 | * msg : 11 | * nickname : Peter 12 | * figureurl : http://qzapp.qlogo.cn/qzapp/111111/942FEA70050EEAFBD4DCE2C1FC775E56/30 13 | * figureurl_1 : http://qzapp.qlogo.cn/qzapp/111111/942FEA70050EEAFBD4DCE2C1FC775E56/50 14 | * figureurl_2 : http://qzapp.qlogo.cn/qzapp/111111/942FEA70050EEAFBD4DCE2C1FC775E56/100 15 | * figureurl_qq_1 : http://q.qlogo.cn/qqapp/100312990/DE1931D5330620DBD07FB4A5422917B6/40 16 | * figureurl_qq_2 : http://q.qlogo.cn/qqapp/100312990/DE1931D5330620DBD07FB4A5422917B6/100 17 | * gender : 男 18 | * is_yellow_vip : 1 19 | * vip : 1 20 | * yellow_vip_level : 7 21 | * level : 7 22 | * is_yellow_year_vip : 1 23 | */ 24 | 25 | private Integer ret; 26 | private String msg; 27 | private String nickname; 28 | private String figureurl; 29 | private String figureurl_1; 30 | private String figureurl_2; 31 | private String figureurl_qq_1; 32 | private String figureurl_qq_2; 33 | private String gender; 34 | private String is_yellow_vip; 35 | private String vip; 36 | private String yellow_vip_level; 37 | private String level; 38 | private String is_yellow_year_vip; 39 | 40 | public Integer getRet() { 41 | return ret; 42 | } 43 | 44 | public void setRet(Integer ret) { 45 | this.ret = ret; 46 | } 47 | 48 | public String getMsg() { 49 | return msg; 50 | } 51 | 52 | public void setMsg(String msg) { 53 | this.msg = msg; 54 | } 55 | 56 | public String getNickname() { 57 | return nickname; 58 | } 59 | 60 | public void setNickname(String nickname) { 61 | this.nickname = nickname; 62 | } 63 | 64 | public String getFigureurl() { 65 | return figureurl; 66 | } 67 | 68 | public void setFigureurl(String figureurl) { 69 | this.figureurl = figureurl; 70 | } 71 | 72 | public String getFigureurl_1() { 73 | return figureurl_1; 74 | } 75 | 76 | public void setFigureurl_1(String figureurl_1) { 77 | this.figureurl_1 = figureurl_1; 78 | } 79 | 80 | public String getFigureurl_2() { 81 | return figureurl_2; 82 | } 83 | 84 | public void setFigureurl_2(String figureurl_2) { 85 | this.figureurl_2 = figureurl_2; 86 | } 87 | 88 | public String getFigureurl_qq_1() { 89 | return figureurl_qq_1; 90 | } 91 | 92 | public void setFigureurl_qq_1(String figureurl_qq_1) { 93 | this.figureurl_qq_1 = figureurl_qq_1; 94 | } 95 | 96 | public String getFigureurl_qq_2() { 97 | return figureurl_qq_2; 98 | } 99 | 100 | public void setFigureurl_qq_2(String figureurl_qq_2) { 101 | this.figureurl_qq_2 = figureurl_qq_2; 102 | } 103 | 104 | public String getGender() { 105 | return gender; 106 | } 107 | 108 | public void setGender(String gender) { 109 | this.gender = gender; 110 | } 111 | 112 | public String getIs_yellow_vip() { 113 | return is_yellow_vip; 114 | } 115 | 116 | public void setIs_yellow_vip(String is_yellow_vip) { 117 | this.is_yellow_vip = is_yellow_vip; 118 | } 119 | 120 | public String getVip() { 121 | return vip; 122 | } 123 | 124 | public void setVip(String vip) { 125 | this.vip = vip; 126 | } 127 | 128 | public String getYellow_vip_level() { 129 | return yellow_vip_level; 130 | } 131 | 132 | public void setYellow_vip_level(String yellow_vip_level) { 133 | this.yellow_vip_level = yellow_vip_level; 134 | } 135 | 136 | public String getLevel() { 137 | return level; 138 | } 139 | 140 | public void setLevel(String level) { 141 | this.level = level; 142 | } 143 | 144 | public String getIs_yellow_year_vip() { 145 | return is_yellow_year_vip; 146 | } 147 | 148 | public void setIs_yellow_year_vip(String is_yellow_year_vip) { 149 | this.is_yellow_year_vip = is_yellow_year_vip; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/res/UserFriendAskListResVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.res; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * 用户朋友列表信息 9 | */ 10 | @Data 11 | public class UserFriendAskListResVO { 12 | 13 | /** 14 | * 自增ID 15 | */ 16 | private Long id; 17 | 18 | /** 19 | * 用户id 20 | */ 21 | private Long uid; 22 | /** 23 | * 朋友的用户id 24 | */ 25 | private Long friendUid; 26 | /** 27 | * 备注 28 | */ 29 | private String remark; 30 | /** 31 | * 状态(0:未确认过,1:已确认, 2: 已拒绝) 32 | */ 33 | private Integer status; 34 | /** 35 | * 创建时间 36 | */ 37 | private Date createTime; 38 | 39 | // 用户信息 40 | private UserInfoListResVO user; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/res/UserFriendListInfoResVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.res; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * 用户朋友列表信息 9 | */ 10 | @Data 11 | public class UserFriendListInfoResVO { 12 | 13 | /** 14 | * 用户ID 15 | */ 16 | private Long uid; 17 | /** 18 | * 朋友的ID 19 | */ 20 | private Long friendUid; 21 | /** 22 | * 备注 23 | */ 24 | private String remark; 25 | 26 | /** 27 | * 未读消息数量 28 | */ 29 | private Integer unMsgCount; 30 | 31 | /** 32 | * 最后一次接收的消息 33 | */ 34 | private String lastMsgContent; 35 | 36 | private Date modifiedTime; 37 | 38 | /** 39 | * 用户 40 | */ 41 | private UserInfoListResVO user; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/res/UserInfoListResVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.res; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 用户列表信息 7 | */ 8 | @Data 9 | public class UserInfoListResVO { 10 | 11 | /** 12 | * 用户id 13 | */ 14 | private Long uid; 15 | /** 16 | * 用户昵称 17 | */ 18 | private String name; 19 | /** 20 | * 用户头像 21 | */ 22 | private String avatar; 23 | /** 24 | * 个性签名 25 | */ 26 | private String remark; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/res/UserInfoResVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.res; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * 用户信息 9 | */ 10 | @Data 11 | public class UserInfoResVO { 12 | 13 | /** 14 | * 用户id 15 | */ 16 | private Long uid; 17 | /** 18 | * 用户昵称 19 | */ 20 | private String name; 21 | /** 22 | * 用户头像 23 | */ 24 | private String avatar; 25 | /** 26 | * 个性签名 27 | */ 28 | private String remark; 29 | /** 30 | * 创建时间 31 | */ 32 | private Date createTime; 33 | 34 | private UserProfileInfoResVO profile; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/res/UserLoginResVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.res; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 用户登录后返回的 7 | */ 8 | @Data 9 | public class UserLoginResVO { 10 | 11 | private Long uid; 12 | 13 | private String sid; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/res/UserProfileInfoResVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.res; 2 | 3 | import com.lmxdawn.him.common.entity.user.UserProfile; 4 | import lombok.Data; 5 | 6 | import java.util.Date; 7 | 8 | /** 9 | * 用户额外信息 10 | */ 11 | @Data 12 | public class UserProfileInfoResVO { 13 | 14 | /** 15 | * 好友请求的数量 16 | */ 17 | private Integer friendAskCount; 18 | /** 19 | * 好友数量 20 | */ 21 | private Integer friendCount; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/vo/res/UserReadResVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.vo.res; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * 用户信息 9 | */ 10 | @Data 11 | public class UserReadResVO { 12 | 13 | /** 14 | * 用户id 15 | */ 16 | private Long uid; 17 | /** 18 | * 用户昵称 19 | */ 20 | private String name; 21 | /** 22 | * 用户头像 23 | */ 24 | private String avatar; 25 | /** 26 | * 个性签名 27 | */ 28 | private String remark; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/ws/WSServer.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.ws; 2 | 3 | import com.lmxdawn.him.api.vo.req.WSMessageReqVO; 4 | import com.lmxdawn.him.api.vo.req.WSBaseReqVO; 5 | import com.lmxdawn.him.api.vo.req.WSUserReqVO; 6 | import com.lmxdawn.him.common.protobuf.WSBaseResProtoOuterClass; 7 | import com.lmxdawn.him.common.protobuf.WSMessageResProtoOuterClass; 8 | import com.lmxdawn.him.common.protobuf.WSUserResProtoOuterClass; 9 | import io.netty.bootstrap.ServerBootstrap; 10 | import io.netty.channel.*; 11 | import io.netty.channel.nio.NioEventLoopGroup; 12 | import io.netty.channel.socket.nio.NioServerSocketChannel; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.springframework.beans.factory.annotation.Value; 15 | import org.springframework.stereotype.Component; 16 | 17 | import javax.annotation.PostConstruct; 18 | import javax.annotation.PreDestroy; 19 | import java.net.InetSocketAddress; 20 | import java.util.Date; 21 | 22 | @Component 23 | @Slf4j 24 | public class WSServer { 25 | 26 | @Value("${ws.port}") 27 | private int wsPort; 28 | 29 | private EventLoopGroup boss = new NioEventLoopGroup(); 30 | private EventLoopGroup work = new NioEventLoopGroup(); 31 | 32 | /** 33 | * 启动 ws server 34 | * 35 | * @return 36 | * @throws InterruptedException 37 | */ 38 | @PostConstruct 39 | public void start() throws InterruptedException { 40 | 41 | ServerBootstrap bootstrap = new ServerBootstrap() 42 | .group(boss, work) 43 | .channel(NioServerSocketChannel.class) 44 | .localAddress(new InetSocketAddress(wsPort)) 45 | //保持长连接 46 | .childOption(ChannelOption.SO_KEEPALIVE, true) 47 | .childHandler(new WSServerInitializer()); 48 | 49 | ChannelFuture future = bootstrap.bind().sync(); 50 | if (future.isSuccess()) { 51 | log.info("启动 ws server 成功"); 52 | } 53 | } 54 | 55 | /** 56 | * 销毁 57 | */ 58 | @PreDestroy 59 | public void destroy() { 60 | boss.shutdownGracefully().syncUninterruptibly(); 61 | work.shutdownGracefully().syncUninterruptibly(); 62 | log.info("关闭 ws server 成功"); 63 | } 64 | 65 | /** 66 | * 发送 Google Protocol 编码消息 67 | * @param fromUid 发送给谁 68 | * @param wsBaseReqVO 消息 69 | * @return 70 | */ 71 | public Boolean sendMsg(Long fromUid, WSBaseReqVO wsBaseReqVO) { 72 | Channel channel = WSSocketHolder.get(fromUid); 73 | 74 | if (null == channel) { 75 | log.info("用户ID[" + fromUid + "]不在线!"); 76 | return false; 77 | } 78 | WSMessageReqVO wsMessageReqVO = wsBaseReqVO.getMessage(); 79 | WSMessageResProtoOuterClass.WSMessageResProto wsMessageResProto = WSMessageResProtoOuterClass.WSMessageResProto.newBuilder() 80 | .setReceiveId(wsMessageReqVO.getReceiveId()) 81 | .setMsgType(wsMessageReqVO.getMsgType()) 82 | .setMsgContent(wsMessageReqVO.getMsgContent()) 83 | .build(); 84 | 85 | WSUserReqVO wsUserReqVO = wsBaseReqVO.getUser(); 86 | WSUserResProtoOuterClass.WSUserResProto wsUserResProto = WSUserResProtoOuterClass.WSUserResProto.newBuilder() 87 | .setUid(wsUserReqVO.getUid()) 88 | .setName(wsUserReqVO.getName()) 89 | .setAvatar(wsUserReqVO.getAvatar()) 90 | .setRemark(wsUserReqVO.getRemark()) 91 | .build(); 92 | 93 | WSBaseResProtoOuterClass.WSBaseResProto wsBaseResProto = WSBaseResProtoOuterClass.WSBaseResProto.newBuilder() 94 | .setType(wsBaseReqVO.getType()) 95 | .setMessage(wsMessageResProto) 96 | .setUser(wsUserResProto) 97 | .setCreateTime(new Date().toString()) 98 | .build(); 99 | 100 | channel.writeAndFlush(wsBaseResProto); 101 | return true; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/ws/WSServerHandler.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.ws; 2 | 3 | import com.lmxdawn.him.api.constant.WSResTypeConstant; 4 | import com.lmxdawn.him.api.constant.WSReqTypeConstant; 5 | import com.lmxdawn.him.api.utils.UserLoginUtils; 6 | import com.lmxdawn.him.common.protobuf.WSBaseReqProtoOuterClass; 7 | import com.lmxdawn.him.common.protobuf.WSBaseResProtoOuterClass; 8 | import io.netty.channel.Channel; 9 | import io.netty.channel.ChannelHandler; 10 | import io.netty.channel.ChannelHandlerContext; 11 | import io.netty.channel.SimpleChannelInboundHandler; 12 | import io.netty.handler.timeout.IdleState; 13 | import io.netty.handler.timeout.IdleStateEvent; 14 | import lombok.extern.slf4j.Slf4j; 15 | 16 | import java.io.IOException; 17 | import java.util.Date; 18 | 19 | @ChannelHandler.Sharable 20 | @Slf4j 21 | public class WSServerHandler extends SimpleChannelInboundHandler { 22 | 23 | /** 24 | * 取消绑定 25 | * @param ctx 26 | * @throws Exception 27 | */ 28 | @Override 29 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 30 | // 可能出现业务判断离线后再次触发 channelInactive 31 | log.warn("触发 channelInactive 掉线![{}]", ctx.channel().id()); 32 | userOffLine(ctx); 33 | } 34 | 35 | /** 36 | * 心跳检查 37 | * @param ctx 38 | * @param evt 39 | * @throws Exception 40 | */ 41 | @Override 42 | public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { 43 | if (evt instanceof IdleStateEvent) { 44 | IdleStateEvent idleStateEvent = (IdleStateEvent) evt; 45 | // 读空闲 46 | if (idleStateEvent.state() == IdleState.READER_IDLE) { 47 | // 关闭用户的连接 48 | userOffLine(ctx); 49 | } 50 | } 51 | super.userEventTriggered(ctx, evt); 52 | } 53 | 54 | /** 55 | * 用户下线 56 | */ 57 | private void userOffLine(ChannelHandlerContext ctx) throws IOException { 58 | WSSocketHolder.remove(ctx.channel()); 59 | ctx.channel().close(); 60 | } 61 | 62 | /** 63 | * 读到客户端的内容 (这里只做心跳检查) 64 | * @param ctx 65 | * @param msg 66 | * @throws Exception 67 | */ 68 | @Override 69 | protected void channelRead0(ChannelHandlerContext ctx, WSBaseReqProtoOuterClass.WSBaseReqProto msg) throws Exception { 70 | 71 | String sid = msg.getSid(); 72 | long uid = msg.getUid(); 73 | Integer type = msg.getType(); 74 | switch (type) { 75 | case WSReqTypeConstant.LOGIN: // 登录类型 76 | log.info("用户登录"); 77 | userLogin(ctx, uid, sid); 78 | break; 79 | case WSReqTypeConstant.PING: // 心跳 80 | log.info("客户端心跳"); 81 | break; 82 | default: 83 | log.info("未知类型"); 84 | } 85 | 86 | } 87 | 88 | private void userLogin(ChannelHandlerContext ctx, Long uid, String sid) throws IOException { 89 | if (!UserLoginUtils.checkToken(uid, sid)) { 90 | log.info("非法登录: {}, {}", uid, sid); 91 | // 登录异常, 发送下线通知 92 | WSBaseResProtoOuterClass.WSBaseResProto wsBaseResProto = WSBaseResProtoOuterClass.WSBaseResProto.newBuilder() 93 | .setType(WSResTypeConstant.LOGIN_OUT) 94 | .setCreateTime(new Date().toString()) 95 | .build(); 96 | // 发送下线消息 97 | ctx.channel().writeAndFlush(wsBaseResProto); 98 | return; 99 | } 100 | 101 | // 判断是否在线, 如果在线, 则剔除当前在线用户 102 | Channel channel = WSSocketHolder.get(uid); 103 | // 如果不是第一次登陆, 并且 客户端ID和当前的不匹配, 则通知之前的客户端下线 104 | if (channel != null && !ctx.channel().id().equals(channel.id())) { 105 | WSBaseResProtoOuterClass.WSBaseResProto wsBaseResProto = WSBaseResProtoOuterClass.WSBaseResProto.newBuilder() 106 | .setType(WSResTypeConstant.WS_OUT) 107 | .setCreateTime(new Date().toString()) 108 | .build(); 109 | // 发送下线消息 110 | channel.writeAndFlush(wsBaseResProto); 111 | } 112 | 113 | // 加入 在线 map 中 114 | WSSocketHolder.put(uid, ctx.channel()); 115 | } 116 | 117 | @Override 118 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 119 | if ("Connection reset by peer".equals(cause.getMessage())) { 120 | log.error("连接出现问题"); 121 | return; 122 | } 123 | 124 | log.error(cause.getMessage(), cause); 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/ws/WSServerInitializer.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.ws; 2 | 3 | import com.google.protobuf.MessageLite; 4 | import com.google.protobuf.MessageLiteOrBuilder; 5 | import com.lmxdawn.him.common.protobuf.WSBaseReqProtoOuterClass; 6 | import io.netty.buffer.ByteBuf; 7 | import io.netty.channel.ChannelHandlerContext; 8 | import io.netty.channel.ChannelInitializer; 9 | import io.netty.channel.ChannelPipeline; 10 | import io.netty.channel.socket.SocketChannel; 11 | import io.netty.handler.codec.MessageToMessageDecoder; 12 | import io.netty.handler.codec.MessageToMessageEncoder; 13 | import io.netty.handler.codec.http.HttpObjectAggregator; 14 | import io.netty.handler.codec.http.HttpServerCodec; 15 | import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; 16 | import io.netty.handler.codec.http.websocketx.WebSocketFrame; 17 | import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; 18 | import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler; 19 | import io.netty.handler.codec.protobuf.ProtobufDecoder; 20 | import io.netty.handler.stream.ChunkedWriteHandler; 21 | import io.netty.handler.timeout.IdleStateHandler; 22 | 23 | import java.util.List; 24 | 25 | import static io.netty.buffer.Unpooled.wrappedBuffer; 26 | 27 | 28 | public class WSServerInitializer extends ChannelInitializer { 29 | 30 | @Override 31 | protected void initChannel(SocketChannel ch) throws Exception { 32 | ChannelPipeline pipeline = ch.pipeline(); 33 | //15 秒客户端没有向服务器发送心跳则关闭连接 34 | pipeline.addLast(new IdleStateHandler(15, 0, 0)); 35 | // HTTP请求的解码和编码 36 | pipeline.addLast(new HttpServerCodec()); 37 | // 把多个消息转换为一个单一的FullHttpRequest或是FullHttpResponse, 38 | // 原因是HTTP解码器会在每个HTTP消息中生成多个消息对象HttpRequest/HttpResponse,HttpContent,LastHttpContent 39 | pipeline.addLast(new HttpObjectAggregator(65536)); 40 | // 主要用于处理大数据流,比如一个1G大小的文件如果你直接传输肯定会撑暴jvm内存的; 增加之后就不用考虑这个问题了 41 | pipeline.addLast(new ChunkedWriteHandler()); 42 | // WebSocket数据压缩 43 | pipeline.addLast(new WebSocketServerCompressionHandler()); 44 | // 协议包长度限制 45 | pipeline.addLast(new WebSocketServerProtocolHandler("/ws", null, true)); 46 | // 协议包解码 47 | pipeline.addLast(new MessageToMessageDecoder() { 48 | @Override 49 | protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, List objs) throws Exception { 50 | ByteBuf buf = ((BinaryWebSocketFrame) frame).content(); 51 | objs.add(buf); 52 | buf.retain(); 53 | } 54 | }); 55 | // 协议包编码 56 | pipeline.addLast(new MessageToMessageEncoder() { 57 | @Override 58 | protected void encode(ChannelHandlerContext ctx, MessageLiteOrBuilder msg, List out) throws Exception { 59 | ByteBuf result = null; 60 | if (msg instanceof MessageLite) { 61 | result = wrappedBuffer(((MessageLite) msg).toByteArray()); 62 | } 63 | if (msg instanceof MessageLite.Builder) { 64 | result = wrappedBuffer(((MessageLite.Builder) msg).build().toByteArray()); 65 | } 66 | 67 | // ==== 上面代码片段是拷贝自TCP ProtobufEncoder 源码 ==== 68 | // 然后下面再转成websocket二进制流,因为客户端不能直接解析protobuf编码生成的 69 | 70 | WebSocketFrame frame = new BinaryWebSocketFrame(result); 71 | out.add(frame); 72 | } 73 | }); 74 | 75 | // 协议包解码时指定Protobuf字节数实例化为CommonProtocol类型 76 | pipeline.addLast(new ProtobufDecoder(WSBaseReqProtoOuterClass.WSBaseReqProto.getDefaultInstance())); 77 | 78 | // websocket定义了传递数据的6中frame类型 79 | pipeline.addLast(new WSServerHandler()); 80 | 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /him-api/src/main/java/com/lmxdawn/him/api/ws/WSSocketHolder.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.ws; 2 | 3 | import io.netty.channel.Channel; 4 | 5 | import java.util.Map; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | /** 9 | * 操作 在线用户的 Channel 10 | */ 11 | public class WSSocketHolder { 12 | 13 | private static final Map CHANNEL_MAP = new ConcurrentHashMap<>(16); 14 | 15 | public static void put(Long id, Channel channel) { 16 | CHANNEL_MAP.put(id, channel); 17 | } 18 | 19 | public static Channel get(Long id) { 20 | return CHANNEL_MAP.get(id); 21 | } 22 | 23 | public static Map getMAP() { 24 | return CHANNEL_MAP; 25 | } 26 | 27 | public static void remove(Channel channel) { 28 | CHANNEL_MAP.entrySet().stream().filter(entry -> entry.getValue() == channel).forEach(entry -> CHANNEL_MAP.remove(entry.getKey())); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /him-api/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | # 本地环境 2 | 3 | server.port=9000 4 | spring.datasource.url=jdbc:mysql://localhost/him?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull 5 | spring.datasource.username=root 6 | spring.datasource.password=root 7 | 8 | logging.level.com.lmxdawn.him.api.dao=debug 9 | 10 | #公共文件的配置 11 | # 上传的地址 12 | public-file.uploadUrl=https://upload.qiniup.com 13 | # 资源的域名 14 | public-file.domain=https://upload.qiniup.com 15 | 16 | # 跨域设置 17 | cors.allowed-origins=http://localhost:8080 18 | cors.allowed-headers=Content-Type 19 | cors.allowed-methods=GET,POST,OPTIONS 20 | cors.allowed-credentials=true 21 | 22 | # WS 配置 23 | ws.port=9001 24 | 25 | # QQ 授权的配置 26 | qq.auth.appid=101578922 27 | qq.auth.appkey=dfa5af4458050b588e46393c2c6d6c92 28 | 29 | # Redis数据库索引(默认为0) 30 | spring.redis.database=0 31 | # Redis服务器地址 32 | spring.redis.host=localhost 33 | # Redis服务器连接端口 34 | spring.redis.port=6379 35 | # Redis服务器连接密码(默认为空) 36 | #spring.redis.password= 37 | #连接池最大连接数(使用负值表示没有限制) 38 | #spring.redis.jedis.pool.max-active=8 39 | # 连接池最大阻塞等待时间(使用负值表示没有限制) 40 | #spring.redis.jedis.pool.max-wait= 41 | # 连接池中的最大空闲连接 42 | #spring.redis.jedis.pool.max-idle=8 43 | # 连接池中的最小空闲连接 44 | #spring.redis.jedis.pool.min-idle=0 45 | # 连接超时时间(毫秒) 46 | #spring.redis.timeout=0 -------------------------------------------------------------------------------- /him-api/src/main/resources/application-pro.properties: -------------------------------------------------------------------------------- 1 | # 生产环境 2 | 3 | server.port=9000 4 | spring.datasource.url=jdbc:mysql://localhost/him?serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull 5 | spring.datasource.username=him 6 | spring.datasource.password=dzmRNYxDXtCA7bTW 7 | 8 | #logging.level.com.lmxdawn.him.api.dao=debug 9 | 10 | #公共文件的配置 11 | # 上传的地址 12 | public-file.uploadUrl=https://upload.qiniup.com 13 | # 资源的域名 14 | public-file.domain=https://upload.qiniup.com 15 | 16 | # 跨域设置 , 这样设置了还是不能跨域传 Cookie 不知道怎么回事 17 | cors.allowed-origins=http://him-netty.await.fun 18 | cors.allowed-headers=Content-Type 19 | cors.allowed-methods=GET,POST,OPTIONS 20 | cors.allowed-credentials=true 21 | 22 | # WS 配置 23 | ws.port=9001 24 | 25 | # QQ 授权的配置 26 | qq.auth.appid=101574853 27 | qq.auth.appkey= 28 | 29 | # Redis数据库索引(默认为0) 30 | spring.redis.database=0 31 | # Redis服务器地址 32 | spring.redis.host=localhost 33 | # Redis服务器连接端口 34 | spring.redis.port=6379 35 | # Redis服务器连接密码(默认为空) 36 | #spring.redis.password= 37 | #连接池最大连接数(使用负值表示没有限制) 38 | #spring.redis.jedis.pool.max-active=8 39 | # 连接池最大阻塞等待时间(使用负值表示没有限制) 40 | #spring.redis.jedis.pool.max-wait= 41 | # 连接池中的最大空闲连接 42 | #spring.redis.jedis.pool.max-idle=8 43 | # 连接池中的最小空闲连接 44 | #spring.redis.jedis.pool.min-idle=0 45 | # 连接超时时间(毫秒) 46 | #spring.redis.timeout=0 -------------------------------------------------------------------------------- /him-api/src/main/resources/application-test.properties: -------------------------------------------------------------------------------- 1 | # 线上测试环境 2 | 3 | server.port=9998 4 | spring.datasource.url=jdbc:mysql://localhost/him?serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull 5 | spring.datasource.username= 6 | spring.datasource.password= 7 | 8 | logging.level.com.lmxdawn.api.admin.dao=debug 9 | 10 | #公共文件的配置 11 | # 上传的地址 12 | public-file.uploadUrl= 13 | # 资源的域名 14 | public-file.domain= 15 | 16 | # 跨域设置 17 | cors.allowed-origins=http://test.com 18 | cors.allowed-headers=Content-Type 19 | cors.allowed-methods=GET,POST,OPTIONS 20 | cors.allowed-credentials=true 21 | 22 | # WS 配置 23 | ws.port=9999 24 | 25 | # QQ 授权的配置 26 | qq.auth.appid=101578922 27 | qq.auth.appkey=dfa5af4458050b588e46393c2c6d6c92 28 | 29 | # Redis数据库索引(默认为0) 30 | spring.redis.database=0 31 | # Redis服务器地址 32 | spring.redis.host=localhost 33 | # Redis服务器连接端口 34 | spring.redis.port=6379 35 | # Redis服务器连接密码(默认为空) 36 | #spring.redis.password= 37 | #连接池最大连接数(使用负值表示没有限制) 38 | #spring.redis.jedis.pool.max-active=8 39 | # 连接池最大阻塞等待时间(使用负值表示没有限制) 40 | #spring.redis.jedis.pool.max-wait= 41 | # 连接池中的最大空闲连接 42 | #spring.redis.jedis.pool.max-idle=8 43 | # 连接池中的最小空闲连接 44 | #spring.redis.jedis.pool.min-idle=0 45 | # 连接超时时间(毫秒) 46 | #spring.redis.timeout=0 -------------------------------------------------------------------------------- /him-api/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.profiles.active=dev 2 | 3 | server.servlet.context-path=/api 4 | 5 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 6 | spring.datasource.druid.connection-init-sql=set names utf8mb4 7 | 8 | mybatis.config-location=classpath:mybatis/mybatis-config.xml 9 | mybatis.mapper-locations=classpath:mybatis/mapper/*/*.xml -------------------------------------------------------------------------------- /him-api/src/main/resources/mybatis/mapper/group/GroupDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 21 | 22 | 23 | INSERT INTO `group`(uid,`name`,avatar,member_num,remark,create_time,modified_time) 24 | VALUES 25 | (#{uid}, 26 | #{name}, 27 | #{avatar}, 28 | #{memberNum}, 29 | #{remark}, 30 | #{createTime}, 31 | #{modifiedTime}) 32 | 33 | 34 | 35 | UPDATE `group` 36 | 37 | `uid`=#{uid}, 38 | `name`=#{name}, 39 | `member_num`= member_num + #{memberNum}, 40 | `remark`=#{remark}, 41 | modified_time=#{modifiedTime} 42 | 43 | WHERE group_id=#{groupId} 44 | 45 | 46 | 47 | UPDATE `group` 48 | 49 | `member_num`= member_num - 1 50 | 51 | WHERE group_id=#{groupId} AND member_num > 0 52 | 53 | 54 | 55 | UPDATE `group` 56 | 57 | `member_num`= member_num + #{memberNum} 58 | 59 | WHERE group_id=#{groupId} 60 | 61 | 62 | 63 | delete from `group` where group_id=#{groupId} 64 | 65 | 66 | -------------------------------------------------------------------------------- /him-api/src/main/resources/mybatis/mapper/group/GroupMsgDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 13 | 14 | 15 | insert into `group_msg`(`group_id`,sender_uid,msg_type,msg_content,create_time,modified_time) 16 | values 17 | (#{groupId}, 18 | #{senderUid}, 19 | #{msgType}, 20 | #{msgContent}, 21 | #{createTime}, 22 | #{modifiedTime}) 23 | 24 | -------------------------------------------------------------------------------- /him-api/src/main/resources/mybatis/mapper/group/GroupUserDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 19 | 20 | 26 | 27 | 28 | insert into `group_user`(group_id,uid,remark,`rank`,create_time,modified_time) 29 | values 30 | (#{groupId}, 31 | #{uid}, 32 | #{remark}, 33 | #{rank}, 34 | #{createTime}, 35 | #{modifiedTime}) 36 | ON DUPLICATE KEY UPDATE modified_time = VALUES(modified_time) 37 | 38 | 39 | 40 | update `group_user` 41 | 42 | `remark`=#{remark}, 43 | `rank`=#{rank}, 44 | modified_time=#{modifiedTime} 45 | 46 | where group_id = #{groupId} and uid = #{uid} 47 | 48 | 49 | 50 | update `group_user` 51 | 52 | `un_msg_count`=0, 53 | modified_time=#{modifiedTime} 54 | 55 | where group_id = #{groupId} and uid = #{uid} 56 | 57 | 58 | 59 | update `group_user` 60 | 61 | `last_ack_msg_id`=#{lastAckMsgId}, 62 | `last_msg_content`=#{lastMsgContent}, 63 | `last_msg_time`=#{lastMsgTime}, 64 | `un_msg_count`= un_msg_count + #{unMsgCount}, 65 | modified_time=#{modifiedTime} 66 | 67 | where group_id = #{groupId} 68 | 69 | 70 | 71 | delete from `group_user` where group_id = #{groupId} and uid = #{uid} and `rank` != 2 72 | 73 | 74 | 75 | delete from `group_user` where group_id = #{groupId} 76 | 77 | 78 | -------------------------------------------------------------------------------- /him-api/src/main/resources/mybatis/mapper/user/UserDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 19 | 20 | 28 | 29 | 30 | INSERT INTO user(`name`,avatar,remark,create_time,modified_time) 31 | VALUES 32 | (#{name}, 33 | #{avatar}, 34 | #{remark}, 35 | #{createTime}, 36 | #{modifiedTime}) 37 | 38 | 39 | 40 | UPDATE `user` 41 | 42 | `name`=#{name}, 43 | `avatar`=#{avatar}, 44 | `remark`=#{remark}, 45 | modified_time=#{modifiedTime} 46 | 47 | WHERE uid=#{uid} 48 | 49 | 50 | 51 | delete from `user` where uid = #{uid} 52 | 53 | 54 | -------------------------------------------------------------------------------- /him-api/src/main/resources/mybatis/mapper/user/UserFriendAskDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 13 | 14 | 20 | 21 | 22 | insert into `user_friend_ask`(`uid`,friend_uid,remark,`status`,create_time,modified_time) 23 | values 24 | (#{uid}, 25 | #{friendUid}, 26 | #{remark}, 27 | #{status}, 28 | #{createTime}, 29 | #{modifiedTime}) 30 | 31 | 32 | 33 | update `user_friend_ask` 34 | 35 | `status`=#{status}, 36 | `remark`=#{remark}, 37 | modified_time=#{modifiedTime} 38 | 39 | where id = #{id} 40 | and status = 0 41 | 42 | 43 | 44 | delete from `user_friend_ask` where id = #{id} 45 | 46 | 47 | -------------------------------------------------------------------------------- /him-api/src/main/resources/mybatis/mapper/user/UserFriendDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 19 | 20 | 21 | insert into `user_friend` 22 | (`uid`,friend_uid,remark,un_msg_count,last_msg_content,create_time,modified_time) 23 | values 24 | 25 | 29 | (#{item.uid}, 30 | #{item.friendUid}, 31 | #{item.remark}, 32 | 33 | 34 | #{item.unMsgCount}, 35 | 36 | 37 | 0, 38 | 39 | 40 | 0, 41 | 42 | 43 | #{item.lastMsgContent}, 44 | #{item.createTime}, 45 | #{item.modifiedTime}) 46 | 47 | 48 | ON DUPLICATE KEY UPDATE 49 | un_msg_count=un_msg_count + VALUES(un_msg_count), 50 | last_msg_content=VALUES(last_msg_content), 51 | modified_time = VALUES(modified_time) 52 | 53 | 54 | 55 | update `user_friend` 56 | 57 | `remark`=#{remark}, 58 | 59 | 60 | un_msg_count = un_msg_count + #{unMsgCount}, 61 | 62 | 63 | un_msg_count = 0, 64 | 65 | 66 | 67 | 68 | last_msg_content=#{lastMsgContent}, 69 | modified_time=#{modifiedTime} 70 | 71 | where uid = #{uid} and friend_uid = #{friendUid} 72 | 73 | 74 | 75 | delete from `user_friend` where uid = #{uid} and friend_uid = #{friendUid} 76 | 77 | 78 | -------------------------------------------------------------------------------- /him-api/src/main/resources/mybatis/mapper/user/UserFriendMsgDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 14 | 15 | 16 | insert into `user_friend_msg`(`uid`,to_uid,sender_uid,msg_type,msg_content,create_time) 17 | values 18 | (#{uid}, 19 | #{toUid}, 20 | #{senderUid}, 21 | #{msgType}, 22 | #{msgContent}, 23 | #{createTime}) 24 | 25 | -------------------------------------------------------------------------------- /him-api/src/main/resources/mybatis/mapper/user/UserProfileDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 21 | 22 | 23 | INSERT INTO user_profile(uid,friend_ask_count,friend_count,create_time,modified_time) 24 | VALUES 25 | (#{uid}, 26 | 27 | 28 | #{friendAskCount}, 29 | 30 | 31 | 0, 32 | 33 | 34 | 35 | 36 | #{friendCount}, 37 | 38 | 39 | 0, 40 | 41 | 42 | #{createTime}, 43 | #{modifiedTime}) 44 | ON DUPLICATE KEY UPDATE 45 | friend_ask_count = friend_ask_count + VALUES(friend_ask_count), 46 | friend_count = friend_count + VALUES(friend_count), 47 | modified_time = VALUES(modified_time) 48 | 49 | 50 | 51 | INSERT INTO user_profile(uid,friend_ask_count,friend_count,create_time,modified_time) 52 | VALUES 53 | 54 | 57 | (#{item.uid}, 58 | 59 | 60 | #{item.friendAskCount}, 61 | 62 | 63 | 0, 64 | 65 | 66 | 67 | 68 | #{item.friendCount}, 69 | 70 | 71 | 0, 72 | 73 | 74 | #{item.createTime}, 75 | #{item.modifiedTime}) 76 | 77 | 78 | ON DUPLICATE KEY UPDATE 79 | friend_ask_count = friend_ask_count + VALUES(friend_ask_count), 80 | friend_count = friend_count + VALUES(friend_count), 81 | modified_time = VALUES(modified_time) 82 | 83 | 84 | 85 | UPDATE user_profile 86 | 87 | friend_ask_count=#{friendAskCount}, 88 | modified_time=#{modifiedTime} 89 | 90 | WHERE uid=#{uid} 91 | 92 | 93 | -------------------------------------------------------------------------------- /him-api/src/main/resources/mybatis/mapper/user/UserQqDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 14 | INSERT INTO user_qq(`uid`,openid,create_time) 15 | VALUES 16 | (#{uid}, 17 | #{openid}, 18 | #{createTime}) 19 | 20 | 21 | 22 | delete from `user_qq` where uid = #{uid} 23 | 24 | 25 | -------------------------------------------------------------------------------- /him-api/src/main/resources/mybatis/mybatis-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /him-api/src/main/resources/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/him-netty/8af0555b4931e286f75269b67a3a2bb507ccd912/him-api/src/main/resources/static/favicon.ico -------------------------------------------------------------------------------- /him-api/src/main/resources/templates/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /him-api/src/test/java/com/lmxdawn/him/api/BaseApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | import org.springframework.test.context.junit4.SpringRunner; 6 | 7 | @RunWith(SpringRunner.class) 8 | @SpringBootTest 9 | public class BaseApplicationTest { 10 | } 11 | -------------------------------------------------------------------------------- /him-api/src/test/java/com/lmxdawn/him/api/service/group/impl/GroupServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.group.impl; 2 | 3 | import com.lmxdawn.him.api.BaseApplicationTest; 4 | import com.lmxdawn.him.api.service.group.GroupService; 5 | import com.lmxdawn.him.common.entity.group.Group; 6 | import org.junit.Test; 7 | 8 | import javax.annotation.Resource; 9 | 10 | import java.util.Arrays; 11 | import java.util.List; 12 | 13 | import static org.junit.Assert.*; 14 | 15 | public class GroupServiceImplTest extends BaseApplicationTest { 16 | 17 | @Resource 18 | private GroupService groupService; 19 | 20 | @Test 21 | public void findByGroupId() { 22 | 23 | } 24 | 25 | @Test 26 | public void listByGroupIdIn() { 27 | 28 | } 29 | 30 | @Test 31 | public void insertGroup() { 32 | 33 | 34 | } 35 | 36 | @Test 37 | public void updateGroup() { 38 | 39 | } 40 | 41 | @Test 42 | public void deleteByGroupId() { 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /him-api/src/test/java/com/lmxdawn/him/api/service/user/impl/UserFriendMsgServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user.impl; 2 | 3 | import com.lmxdawn.him.api.BaseApplicationTest; 4 | import com.lmxdawn.him.api.service.user.UserFriendMsgService; 5 | import com.lmxdawn.him.common.entity.user.UserFriendMsg; 6 | import org.junit.Test; 7 | 8 | import javax.annotation.Resource; 9 | import java.util.List; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | public class UserFriendMsgServiceImplTest extends BaseApplicationTest { 14 | 15 | @Resource 16 | private UserFriendMsgService userFriendMsgService; 17 | 18 | @Test 19 | public void listByLastMsgId() { 20 | 21 | } 22 | 23 | @Test 24 | public void insertUserOfflineMsg() { 25 | 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /him-api/src/test/java/com/lmxdawn/him/api/service/user/impl/UserFriendServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.api.service.user.impl; 2 | 3 | import com.lmxdawn.him.api.BaseApplicationTest; 4 | import com.lmxdawn.him.api.service.user.UserFriendService; 5 | import com.lmxdawn.him.common.entity.user.UserFriend; 6 | import org.junit.Test; 7 | 8 | import javax.annotation.Resource; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | public class UserFriendServiceImplTest extends BaseApplicationTest { 13 | 14 | @Resource 15 | private UserFriendService userFriendService; 16 | 17 | @Test 18 | public void listByUid() { 19 | 20 | 21 | } 22 | 23 | @Test 24 | public void insertUserFriend() { 25 | 26 | } 27 | 28 | @Test 29 | public void updateUserFriend() { 30 | } 31 | 32 | @Test 33 | public void deleteByUserFriend() { 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /him-common/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ -------------------------------------------------------------------------------- /him-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | him 7 | com.lmxdawn 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | him-common 13 | 14 | 15 | 16 | 17 | org.projectlombok 18 | lombok 19 | true 20 | 21 | 22 | 23 | com.google.protobuf 24 | protobuf-java 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/constant/CookieConstant.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.constant; 2 | 3 | /** 4 | * cookie常量 5 | */ 6 | public interface CookieConstant { 7 | 8 | String TOKEN = "token"; 9 | 10 | Integer EXPIRE = 7200; 11 | } 12 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/constant/RedisConstant.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.constant; 2 | 3 | /** 4 | * redis 常量 5 | */ 6 | public interface RedisConstant { 7 | 8 | String ADMIN_AUTH_RULES = "admin_auth_rules:%s"; // 管理员的权限 9 | 10 | } 11 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/converter/OrderForm2OrderDTOConverter.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.converter; 2 | 3 | 4 | /** 5 | * 某个对象转另外一个对象 6 | */ 7 | public class OrderForm2OrderDTOConverter { 8 | 9 | public static Object convert(Object orderForm) { 10 | return new Object(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/entity/group/Group.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.entity.group; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * table:group 9 | */ 10 | @Data 11 | public class Group { 12 | 13 | /** 14 | * 群ID 15 | */ 16 | private Long groupId; 17 | /** 18 | * 创建者用户ID 19 | */ 20 | private Long uid; 21 | /** 22 | * 群昵称 23 | */ 24 | private String name; 25 | /** 26 | * 群头像 27 | */ 28 | private String avatar; 29 | /** 30 | * 成员数量 31 | */ 32 | private Integer memberNum; 33 | /** 34 | * 描述 35 | */ 36 | private String remark; 37 | /** 38 | * 创建时间 39 | */ 40 | private Date createTime; 41 | /** 42 | * 更新时间 43 | */ 44 | private Date modifiedTime; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/entity/group/GroupMsg.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.entity.group; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * table:group_msg 9 | */ 10 | @Data 11 | public class GroupMsg { 12 | 13 | /** 14 | * 消息ID 15 | */ 16 | private Long msgId; 17 | /** 18 | * 群ID 19 | */ 20 | private Long groupId; 21 | /** 22 | * 发送消息的用户ID 23 | */ 24 | private Long senderUid; 25 | /** 26 | * 消息类型(0:普通文字消息,1:图片消息,2:文件消息,3:语音消息,4:视频消息) 27 | */ 28 | private Integer msgType; 29 | /** 30 | * 消息内容 31 | */ 32 | private String msgContent; 33 | /** 34 | * 创建时间 35 | */ 36 | private Date createTime; 37 | /** 38 | * 更新时间 39 | */ 40 | private Date modifiedTime; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/entity/group/GroupUser.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.entity.group; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * table:group_user 9 | */ 10 | @Data 11 | public class GroupUser { 12 | 13 | /** 14 | * 自增ID 15 | */ 16 | private Long id; 17 | /** 18 | * 群ID 19 | */ 20 | private Long groupId; 21 | /** 22 | * 用户ID 23 | */ 24 | private Long uid; 25 | /** 26 | * 群里的备注 27 | */ 28 | private String remark; 29 | /** 30 | * 最后一次确认的消息ID 31 | */ 32 | private Long lastAckMsgId; 33 | /** 34 | * 最后一次的消息内容 35 | */ 36 | private String lastMsgContent; 37 | /** 38 | * 最后一次的消息时间 39 | */ 40 | private Date lastMsgTime; 41 | /** 42 | * 未读消息数量 43 | */ 44 | private Integer unMsgCount; 45 | /** 46 | * 等级(0:普通成员,1:管理员,2:群主) 47 | */ 48 | private Integer rank; 49 | /** 50 | * 创建时间 51 | */ 52 | private Date createTime; 53 | /** 54 | * 创建时间 55 | */ 56 | private Date modifiedTime; 57 | 58 | } 59 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/entity/user/User.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.entity.user; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * table:user 9 | */ 10 | @Data 11 | public class User { 12 | 13 | /** 14 | * 用户id 15 | */ 16 | private Long uid; 17 | /** 18 | * 密码 19 | */ 20 | private String pwd; 21 | /** 22 | * 用户昵称 23 | */ 24 | private String name; 25 | /** 26 | * 用户头像 27 | */ 28 | private String avatar; 29 | /** 30 | * 个性签名 31 | */ 32 | private String remark; 33 | /** 34 | * 创建时间 35 | */ 36 | private Date createTime; 37 | /** 38 | * 更新时间 39 | */ 40 | private Date modifiedTime; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/entity/user/UserFriend.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.entity.user; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * table:user_friend 9 | */ 10 | @Data 11 | public class UserFriend { 12 | 13 | /** 14 | * 自增id 15 | */ 16 | private Integer id; 17 | /** 18 | * 用户id 19 | */ 20 | private Long uid; 21 | /** 22 | * 朋友的用户id 23 | */ 24 | private Long friendUid; 25 | /** 26 | * 备注 27 | */ 28 | private String remark; 29 | /** 30 | * 未读消息数量 31 | */ 32 | private Integer unMsgCount; 33 | /** 34 | * 最后一次接收的消息内容 35 | */ 36 | private String lastMsgContent; 37 | /** 38 | * 创建时间 39 | */ 40 | private Date createTime; 41 | /** 42 | * 更新的时间 43 | */ 44 | private Date modifiedTime; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/entity/user/UserFriendAsk.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.entity.user; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * table:user_friend_ask 9 | */ 10 | @Data 11 | public class UserFriendAsk { 12 | 13 | /** 14 | * 自增ID 15 | */ 16 | private Long id; 17 | /** 18 | * 用户ID 19 | */ 20 | private Long uid; 21 | /** 22 | * 发送消息的用户ID 23 | */ 24 | private Long friendUid; 25 | /** 26 | * 备注信息 27 | */ 28 | private String remark; 29 | /** 30 | * 状态(0:未确认过,1:已确认, 2: 已拒绝) 31 | */ 32 | private Integer status; 33 | private Date createTime; 34 | private Date modifiedTime; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/entity/user/UserFriendMsg.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.entity.user; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * table:user_friend_msg 9 | */ 10 | @Data 11 | public class UserFriendMsg { 12 | 13 | /** 14 | * 消息ID 15 | */ 16 | private Long msgId; 17 | /** 18 | * 用户ID 19 | */ 20 | private Long uid; 21 | /** 22 | * 和上面的uid做查询用 23 | */ 24 | private Long toUid; 25 | /** 26 | * 发送方用户ID 27 | */ 28 | private Long senderUid; 29 | /** 30 | * 消息类型(0:普通文字消息,1:图片消息,2:文件消息,3:语音消息,4:视频消息) 31 | */ 32 | private Integer msgType; 33 | /** 34 | * 消息内容 35 | */ 36 | private String msgContent; 37 | /** 38 | * 消息创建时间 39 | */ 40 | private Date createTime; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/entity/user/UserProfile.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.entity.user; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * table:user_profile 9 | */ 10 | @Data 11 | public class UserProfile { 12 | 13 | /** 14 | * 用户的消息配置表 15 | */ 16 | private Long id; 17 | /** 18 | * 用户ID 19 | */ 20 | private Long uid; 21 | /** 22 | * 好友请求的数量 23 | */ 24 | private Integer friendAskCount; 25 | /** 26 | * 好友数量 27 | */ 28 | private Integer friendCount; 29 | private Date createTime; 30 | private Date modifiedTime; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/entity/user/UserQq.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.entity.user; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * table:user_qq 9 | */ 10 | @Data 11 | public class UserQq { 12 | 13 | private Integer id; 14 | /** 15 | * 用户uid(关联 user 表) 16 | */ 17 | private Long uid; 18 | /** 19 | * 用户openID 20 | */ 21 | private String openid; 22 | /** 23 | * 创建时间 24 | */ 25 | private Date createTime; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/enums/ResultEnum.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * 返回结果的枚举类 7 | */ 8 | @Getter 9 | public enum ResultEnum { 10 | 11 | NOT_NETWORK(-1, "系统繁忙,请稍后再试~"), 12 | SUCCESS(0, "success"), 13 | LOGIN_VERIFY_FALL(1, "登录失效~"), 14 | PARAM_VERIFY_FALL(2, "参数验证错误~"), 15 | AUTH_FAILED(3, "权限验证失败~"), 16 | DATA_NOT(4, "没有相关数据~"), 17 | DATA_CHANGE(5, "数据没有任何更改~"), 18 | DATA_REPEAT(6, "数据已存在~"), 19 | 20 | ; 21 | 22 | private Integer code; 23 | 24 | private String message; 25 | 26 | ResultEnum(Integer code, String message) { 27 | this.code = code; 28 | this.message = message; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/utils/ResultVOUtils.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.utils; 2 | 3 | import com.lmxdawn.him.common.enums.ResultEnum; 4 | import com.lmxdawn.him.common.vo.res.BaseResVO; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * 返回结果的操作类 11 | */ 12 | public class ResultVOUtils { 13 | 14 | /** 15 | * 成功时返回 16 | * @param data 返回的data对象 17 | * @return {@link BaseResVO} 18 | */ 19 | public static BaseResVO success(Object data) { 20 | BaseResVO baseResVO = new BaseResVO<>(); 21 | baseResVO.setCode(0); 22 | baseResVO.setMessage("success"); 23 | baseResVO.setData(data); 24 | return baseResVO; 25 | } 26 | 27 | /** 28 | * 成功时返回 29 | * @return {@link BaseResVO} 30 | */ 31 | public static BaseResVO success() { 32 | Map data = new HashMap(); 33 | return success(data); 34 | } 35 | 36 | /** 37 | * 错误时返回 38 | * @param code 错误码 39 | * @param message 错误信息 40 | * @return {@link BaseResVO} 41 | */ 42 | public static BaseResVO error(Integer code, String message) { 43 | BaseResVO baseResVO = new BaseResVO<>(); 44 | baseResVO.setCode(code); 45 | baseResVO.setMessage(message); 46 | Map data = new HashMap(); 47 | baseResVO.setData(data); 48 | return baseResVO; 49 | } 50 | 51 | /** 52 | * 错误时返回 53 | * @param resultEnum 错误枚举类 54 | * @return {@link BaseResVO} 55 | */ 56 | public static BaseResVO error(ResultEnum resultEnum) { 57 | return error(resultEnum.getCode(), resultEnum.getMessage()); 58 | } 59 | 60 | /** 61 | * 错误时返回 62 | * @param resultEnum 错误枚举类 63 | * @param message 错误的信息 64 | * @return {@link BaseResVO} 65 | */ 66 | public static BaseResVO error(ResultEnum resultEnum, String message) { 67 | return error(resultEnum.getCode(), message); 68 | } 69 | 70 | /** 71 | * 默认的错误 72 | * @return {@link BaseResVO} 73 | */ 74 | public static BaseResVO error() { 75 | return error(ResultEnum.NOT_NETWORK); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/vo/req/BaseLimitReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.vo.req; 2 | 3 | /** 4 | * 分页的请求 5 | */ 6 | public class BaseLimitReqVO extends BaseReqVO{ 7 | 8 | /** 9 | * 页码 10 | */ 11 | private Integer page; 12 | 13 | /** 14 | * 数量 15 | */ 16 | private Integer limit; 17 | 18 | /** 19 | * 偏移量 20 | */ 21 | private Integer offset; 22 | 23 | public Integer getPage() { 24 | return page; 25 | } 26 | 27 | public void setPage(Integer page) { 28 | this.page = page; 29 | } 30 | 31 | public Integer getLimit() { 32 | return limit; 33 | } 34 | 35 | public void setLimit(Integer limit) { 36 | this.limit = limit; 37 | } 38 | 39 | public Integer getOffset() { 40 | return offset; 41 | } 42 | 43 | /** 44 | * 设置偏移量 45 | */ 46 | public void setOffset() { 47 | if (null == this.getPage() || this.getPage() <= 0) { 48 | this.setPage(1); 49 | } 50 | if (null == this.getLimit() || this.getLimit() <= 0) { 51 | this.setLimit(10); 52 | } 53 | this.offset = (this.getPage() - 1) * this.getLimit(); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/vo/req/BaseReqVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.vo.req; 2 | 3 | import java.util.UUID; 4 | 5 | public class BaseReqVO { 6 | 7 | /** 8 | * 唯一请求号 9 | */ 10 | private String reqNo; 11 | 12 | /** 13 | * 请求的时间戳 14 | */ 15 | private Long timeStamp; 16 | 17 | public BaseReqVO() { 18 | this.reqNo = UUID.randomUUID().toString(); 19 | this.timeStamp = System.currentTimeMillis(); 20 | } 21 | 22 | public String getReqNo() { 23 | return reqNo; 24 | } 25 | 26 | public void setReqNo(String reqNo) { 27 | this.reqNo = reqNo; 28 | } 29 | 30 | public Long getTimeStamp() { 31 | return timeStamp; 32 | } 33 | 34 | public void setTimeStamp(Long timeStamp) { 35 | this.timeStamp = timeStamp; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /him-common/src/main/java/com/lmxdawn/him/common/vo/res/BaseResVO.java: -------------------------------------------------------------------------------- 1 | package com.lmxdawn.him.common.vo.res; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 返回结果类 7 | * @param 8 | */ 9 | @Data 10 | public class BaseResVO { 11 | 12 | private Integer code; 13 | 14 | private String message; 15 | 16 | private T data; 17 | } 18 | -------------------------------------------------------------------------------- /him-common/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/him-netty/8af0555b4931e286f75269b67a3a2bb507ccd912/him-common/src/main/resources/application.properties -------------------------------------------------------------------------------- /him-common/src/test/java/com/lmxdawn/him/common/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/him-netty/8af0555b4931e286f75269b67a3a2bb507ccd912/him-common/src/test/java/com/lmxdawn/him/common/.gitignore -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | pom 6 | 7 | com.lmxdawn 8 | him 9 | 0.0.1-SNAPSHOT 10 | him 11 | netty 即时通讯 12 | 13 | 14 | 1.8 15 | 4.1.42.Final 16 | 17 | 18 | 19 | him-common 20 | him-api 21 | 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-parent 26 | 2.1.2.RELEASE 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | com.lmxdawn 35 | him-common 36 | 0.0.1-SNAPSHOT 37 | 38 | 39 | 40 | 41 | com.alibaba 42 | fastjson 43 | 1.2.51 44 | 45 | 46 | 47 | 48 | com.google.protobuf 49 | protobuf-java 50 | 3.16.1 51 | 52 | 53 | 54 | 55 | io.netty 56 | netty-all 57 | ${netty.version} 58 | 59 | 60 | 61 | 62 | com.squareup.okhttp3 63 | okhttp 64 | 3.8.1 65 | 66 | 67 | 68 | 69 | org.apache.commons 70 | commons-lang3 71 | 3.8.1 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /protocol/README.md: -------------------------------------------------------------------------------- 1 | # 安装 2 | 3 | # 请求类 4 | 5 | ``` 6 | 消息类型 (0: 心跳, 1: 登录) 7 | ``` 8 | 9 | # 传输内容介绍 10 | 11 | ``` 12 | 返回整体消息: 13 | 消息类型:(-1: 异地登录, 0: 心跳, 1: 好友消息,2: 群消息,3: 好友请求消息,4: 好友同意消息,5: 加入群消息) 14 | 消息实体:(附录1) 15 | 16 | 附录1(消息实体): 17 | 18 | 好友消息: 19 | 发送者ID: 20 | 接收者ID: 21 | 消息类型: 22 | 消息内容: 23 | 24 | 群消息: 25 | 发送者ID: 26 | 接收群ID: 27 | 消息类型: 28 | 消息内容: 29 | 30 | 好友请求消息: 31 | 发送者ID: 32 | 接收者ID: 33 | 消息类型: 34 | 消息内容: 35 | 36 | 好友同意消息: 37 | 发送者ID: 38 | 接收者ID: 39 | 消息类型: 40 | 消息内容: 41 | 42 | 加入群消息: 43 | 发送者ID: 44 | 接收群ID: 45 | 消息类型: 46 | 消息内容: 47 | ``` 48 | -------------------------------------------------------------------------------- /protocol/WSBaseReqProto.proto: -------------------------------------------------------------------------------- 1 | syntax ="proto3"; 2 | package protocol; 3 | 4 | //optimize_for 加快解析的速度 5 | option optimize_for = SPEED; 6 | option java_package = "com.lmxdawn.him.common.protobuf"; 7 | 8 | // 请求实体 type (0: 心跳, 1: 登录) 9 | message WSBaseReqProto{ 10 | int32 type = 1; 11 | uint64 uid = 2; // 用户ID 12 | string sid = 3; // 登录验证 13 | } 14 | -------------------------------------------------------------------------------- /protocol/WSBaseResProto.proto: -------------------------------------------------------------------------------- 1 | syntax ="proto3"; 2 | package protocol; 3 | 4 | import "WSMessageResProto.proto"; 5 | import "WSUserResProto.proto"; 6 | 7 | //optimize_for 加快解析的速度 8 | option optimize_for = SPEED; 9 | option java_package = "com.lmxdawn.him.common.protobuf"; 10 | 11 | // 返回实体 12 | message WSBaseResProto{ 13 | int32 type = 1; 14 | WSMessageResProto message = 2; 15 | WSUserResProto user = 3; 16 | string create_time = 4; 17 | } 18 | -------------------------------------------------------------------------------- /protocol/WSMessageResProto.proto: -------------------------------------------------------------------------------- 1 | syntax ="proto3"; 2 | package protocol; 3 | 4 | //optimize_for 加快解析的速度 5 | option optimize_for = SPEED; 6 | option java_package = "com.lmxdawn.him.common.protobuf"; 7 | 8 | // 请求实体 9 | message WSMessageResProto{ 10 | uint64 receive_id = 1; 11 | int32 msg_type = 2; 12 | string msg_content = 3; 13 | } 14 | -------------------------------------------------------------------------------- /protocol/WSUserResProto.proto: -------------------------------------------------------------------------------- 1 | syntax ="proto3"; 2 | package protocol; 3 | 4 | //optimize_for 加快解析的速度 5 | option optimize_for = SPEED; 6 | option java_package = "com.lmxdawn.him.common.protobuf"; 7 | 8 | // 请求实体 9 | message WSUserResProto{ 10 | uint64 uid = 1; 11 | string name = 2; 12 | string avatar = 3; 13 | string remark = 4; 14 | } 15 | -------------------------------------------------------------------------------- /protocol/proto.bat: -------------------------------------------------------------------------------- 1 | set outPath=../him-common/src/main/java 2 | set fileArray=(WSBaseReqProto WSBaseResProto WSMessageResProto WSUserResProto) 3 | 4 | # 将.proto文件生成java类 5 | for %%i in %fileArray% do ( 6 | echo generate cli protocol java code: %%i.proto 7 | protoc --java_out=%outPath% ./%%i.proto 8 | ) 9 | 10 | pause -------------------------------------------------------------------------------- /protocol/proto.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | outPath=../him-common/src/main/java 4 | fileArray=(WSBaseReqProto WSBaseResProto WSMessageResProto WSUserResProto) 5 | 6 | for i in ${fileArray[@]}; 7 | do 8 | echo "generate cli protocol java code: ${i}.proto" 9 | protoc --java_out=$outPath ./$i.proto 10 | done 11 | -------------------------------------------------------------------------------- /protocol/说明文档.txt: -------------------------------------------------------------------------------- 1 | 整体消息: 2 | 消息类型:(好友消息,群消息,好友请求消息,加入群消息) 3 | 消息实体:(附录1) 4 | 5 | 附录1(消息实体): 6 | 7 | 好友消息: 8 | 发送者ID: 9 | 接收者ID: 10 | 消息类型: 11 | 消息内容: 12 | 13 | 群消息: 14 | 发送者ID: 15 | 接收群ID: 16 | 消息类型: 17 | 消息内容: 18 | 19 | 好友请求消息: 20 | 发送者ID: 21 | 接收者ID: 22 | 消息类型: 23 | 消息内容: 24 | 25 | 加入群消息: 26 | 发送者ID: 27 | 接收群ID: 28 | 消息类型: 29 | 消息内容: -------------------------------------------------------------------------------- /scripts/him.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat Premium Data Transfer 3 | 4 | Source Server : php 5 | Source Server Type : MySQL 6 | Source Server Version : 50719 7 | Source Host : localhost 8 | Source Database : him 9 | 10 | Target Server Type : MySQL 11 | Target Server Version : 50719 12 | File Encoding : utf-8 13 | 14 | Date: 05/15/2019 07:54:42 AM 15 | */ 16 | 17 | SET NAMES utf8mb4; 18 | SET FOREIGN_KEY_CHECKS = 0; 19 | 20 | -- ---------------------------- 21 | -- Table structure for `group` 22 | -- ---------------------------- 23 | DROP TABLE IF EXISTS `group`; 24 | CREATE TABLE `group` ( 25 | `group_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '群ID', 26 | `uid` bigint(20) NOT NULL COMMENT '创建者用户ID', 27 | `name` varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '群昵称', 28 | `avatar` varchar(255) DEFAULT NULL COMMENT '群头像', 29 | `member_num` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '成员数量', 30 | `remark` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '描述', 31 | `create_time` datetime NOT NULL COMMENT '创建时间', 32 | `modified_time` datetime NOT NULL COMMENT '更新时间', 33 | PRIMARY KEY (`group_id`) USING BTREE 34 | ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; 35 | 36 | -- ---------------------------- 37 | -- Table structure for `group_msg` 38 | -- ---------------------------- 39 | DROP TABLE IF EXISTS `group_msg`; 40 | CREATE TABLE `group_msg` ( 41 | `msg_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '消息ID', 42 | `group_id` bigint(20) unsigned NOT NULL COMMENT '群ID', 43 | `sender_uid` bigint(20) unsigned NOT NULL COMMENT '发送消息的用户ID', 44 | `msg_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '消息类型(0:普通文字消息,1:图片消息,2:文件消息,3:语音消息,4:视频消息)', 45 | `msg_content` varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '消息内容', 46 | `create_time` datetime NOT NULL COMMENT '创建时间', 47 | `modified_time` datetime NOT NULL COMMENT '更新时间', 48 | PRIMARY KEY (`msg_id`) USING BTREE, 49 | KEY `idx_group_id_create_time` (`group_id`,`create_time`) USING BTREE 50 | ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='群的消息表'; 51 | 52 | -- ---------------------------- 53 | -- Table structure for `group_user` 54 | -- ---------------------------- 55 | DROP TABLE IF EXISTS `group_user`; 56 | CREATE TABLE `group_user` ( 57 | `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID', 58 | `group_id` bigint(20) unsigned NOT NULL COMMENT '群ID', 59 | `uid` bigint(20) unsigned NOT NULL COMMENT '用户ID', 60 | `remark` varchar(30) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '群里的备注', 61 | `last_ack_msg_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '最后一次确认的消息ID', 62 | `last_msg_content` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '最后一次的消息内容', 63 | `last_msg_time` datetime DEFAULT NULL COMMENT '最后一次的消息时间', 64 | `un_msg_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '未读消息数量', 65 | `rank` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '等级(0:普通成员,1:管理员,2:群主)', 66 | `create_time` datetime NOT NULL COMMENT '创建时间', 67 | `modified_time` datetime NOT NULL COMMENT '创建时间', 68 | PRIMARY KEY (`id`) USING BTREE, 69 | UNIQUE KEY `uk_group_id_uid` (`group_id`,`uid`) USING BTREE, 70 | KEY `idx_uid` (`uid`) USING BTREE 71 | ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='群组表'; 72 | 73 | -- ---------------------------- 74 | -- Table structure for `user` 75 | -- ---------------------------- 76 | DROP TABLE IF EXISTS `user`; 77 | CREATE TABLE `user` ( 78 | `uid` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户id', 79 | `pwd` varchar(255) DEFAULT NULL COMMENT '密码', 80 | `name` varchar(20) CHARACTER SET utf8mb4 NOT NULL COMMENT '用户昵称', 81 | `avatar` varchar(255) DEFAULT NULL COMMENT '用户头像', 82 | `remark` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '个性签名', 83 | `create_time` datetime NOT NULL COMMENT '创建时间', 84 | `modified_time` datetime NOT NULL COMMENT '更新时间', 85 | PRIMARY KEY (`uid`) USING BTREE 86 | ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='用户表'; 87 | 88 | -- ---------------------------- 89 | -- Table structure for `user_friend` 90 | -- ---------------------------- 91 | DROP TABLE IF EXISTS `user_friend`; 92 | CREATE TABLE `user_friend` ( 93 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', 94 | `uid` bigint(20) unsigned NOT NULL COMMENT '用户id', 95 | `friend_uid` bigint(20) NOT NULL COMMENT '朋友的用户id', 96 | `remark` varchar(30) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '备注', 97 | `un_msg_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '未读消息数量', 98 | `last_msg_content` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '最后一次接收的消息内容', 99 | `create_time` datetime NOT NULL COMMENT '创建时间', 100 | `modified_time` datetime NOT NULL COMMENT '更新的时间', 101 | PRIMARY KEY (`id`) USING BTREE, 102 | UNIQUE KEY `uk_uid_friend_uid` (`uid`,`friend_uid`) USING BTREE 103 | ) ENGINE=InnoDB AUTO_INCREMENT=170 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='用户的朋友表'; 104 | 105 | -- ---------------------------- 106 | -- Table structure for `user_friend_ask` 107 | -- ---------------------------- 108 | DROP TABLE IF EXISTS `user_friend_ask`; 109 | CREATE TABLE `user_friend_ask` ( 110 | `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID', 111 | `uid` bigint(20) unsigned NOT NULL COMMENT '用户ID', 112 | `friend_uid` bigint(20) unsigned NOT NULL COMMENT '发送消息的用户ID', 113 | `remark` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '备注信息', 114 | `status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '状态(0:未确认过,1:已确认,2: 拒绝)', 115 | `create_time` datetime NOT NULL, 116 | `modified_time` datetime NOT NULL, 117 | PRIMARY KEY (`id`) USING BTREE, 118 | KEY `idx_uid` (`uid`) USING BTREE 119 | ) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='好友请求表'; 120 | 121 | -- ---------------------------- 122 | -- Table structure for `user_friend_msg` 123 | -- ---------------------------- 124 | DROP TABLE IF EXISTS `user_friend_msg`; 125 | CREATE TABLE `user_friend_msg` ( 126 | `msg_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '消息ID', 127 | `uid` bigint(20) unsigned NOT NULL COMMENT '用户ID', 128 | `to_uid` bigint(20) unsigned NOT NULL COMMENT '和上面的uid做查询用', 129 | `sender_uid` bigint(20) unsigned NOT NULL COMMENT '发送方用户ID', 130 | `msg_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '消息类型(0:普通文字消息,1:图片消息,2:文件消息,3:语音消息,4:视频消息)', 131 | `msg_content` varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '消息内容', 132 | `create_time` datetime NOT NULL COMMENT '消息创建时间', 133 | PRIMARY KEY (`msg_id`) USING BTREE, 134 | KEY `idx_uid_to_uid` (`uid`,`to_uid`) USING BTREE 135 | ) ENGINE=InnoDB AUTO_INCREMENT=112 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='用户的好友消息表'; 136 | 137 | -- ---------------------------- 138 | -- Table structure for `user_profile` 139 | -- ---------------------------- 140 | DROP TABLE IF EXISTS `user_profile`; 141 | CREATE TABLE `user_profile` ( 142 | `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户的消息配置表', 143 | `uid` bigint(20) unsigned NOT NULL COMMENT '用户ID', 144 | `friend_ask_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '好友请求的数量', 145 | `friend_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '好友数量', 146 | `create_time` datetime NOT NULL, 147 | `modified_time` datetime NOT NULL, 148 | PRIMARY KEY (`id`) USING BTREE, 149 | UNIQUE KEY `uk_uid` (`uid`) USING BTREE 150 | ) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='用户的额外信息表'; 151 | 152 | -- ---------------------------- 153 | -- Table structure for `user_qq` 154 | -- ---------------------------- 155 | DROP TABLE IF EXISTS `user_qq`; 156 | CREATE TABLE `user_qq` ( 157 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 158 | `uid` bigint(20) unsigned DEFAULT NULL COMMENT '用户uid(关联 user 表)', 159 | `openid` varchar(40) DEFAULT NULL COMMENT '用户openID', 160 | `create_time` datetime DEFAULT NULL COMMENT '创建时间', 161 | PRIMARY KEY (`id`), 162 | UNIQUE KEY `uniq_user_id` (`uid`) USING BTREE, 163 | UNIQUE KEY `uniq_openid` (`openid`) USING BTREE 164 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='QQ用户授权表'; 165 | 166 | SET FOREIGN_KEY_CHECKS = 1; 167 | --------------------------------------------------------------------------------