十次方社交项目-im即时消息通讯3
一、即时通讯的业务场景和需求
即时通信(Instant Messaging,简称IM)是一个允许两人或多人使用网络实时的传递文字消息、文件、语音与视频交流。 即时通讯技术应用于需要实时收发消息的业务场景。
现在各种各样的即时通讯软件也层出不穷:
- 客服系统
招商银行客服中心
- 直播互动

- 社交APP

- 智能硬件,物联网

二、系统设计
1. 技术选型
- 环信im云
- 前端框架 vue
2. 架构设计
前端页面使用十次方用户微服务认证用户身份,使用环信im云进行即时消息通信。

三、环境和工具
- nodejs
- npm
- 前端框架 vue
- 开发工具 vscode
四、十次方即时通讯功能
1. 用户微服务实现
1) 创建tensquare_user子模块
创建Maven工程
2) 在pom.xml中添加依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>tensquare_parent</artifactId> <groupId>com.tensquare</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>tesquare_user</artifactId> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.tensquare</groupId> <artifactId>tensquare_common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatisplus-spring-boot-starter</artifactId> <version>${mybatisplus-spring-boot-starter.version}</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>${mybatisplus.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.1.1.RELEASE</version> </dependency> </dependencies> </project>
3) 编写application.yml配置文件
server:
port: 9008
spring:
application:
name: tensquare-user
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.240.134:3306/tensquare_user?characterEncoding=utf-8
username: root
password: root
mybatis-plus:
type-aliases-package: com.tensquare.user.pojo
global-config:
id-type: 1
db-column-underline: false
refresh-mapper: true
configuration:
map-underscore-to-camel-case: true
cache-enabled: true #配置的缓存的全局开关
lazyLoadingEnable: true #延时加载的开关,开启延时加载,否则按需加载属性
multipleResultSetsEnabled: true #允许单语句返回多结果集
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句,调试用
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:6868/eureka/
instance:
prefer-ip-address: true
4)编写MyBatis配置Bean
package com.tensquare.user.config;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisPlusConfig {
@Bean
public PaginationInterceptor createPaginationInterceptor(){
return new PaginationInterceptor();
}
}
5) 编写引导类
package com.tensquare.user;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@MapperScan("com.tensquare.user.dao")
@EnableEurekaClient
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class);
}
}
6) 编写pojo
package com.tensquare.user.pojo;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@TableName("tb_user")
@Data
public class User implements Serializable {
@TableId(type = IdType.INPUT)
private String id;
private String mobile;
private String password;
private String nickname;
private String sex;
private Date birthday;
private String avatar;
private String email;
private Date regdate;
private Date updatedate;
private Date lastdate;
private Long online;
private String interest;
private String personality;
private Integer fanscount;
private Integer followcount;
}
7) 编写dao
package com.tensquare.user.dao; import com.baomidou.mybatisplus.mapper.BaseMapper; import com.tensquare.user.pojo.User; public interface UserDao extends BaseMapper<User> { }
8) 编写service
package com.tensquare.user.service;
import com.tensquare.user.dao.UserDao;
import com.tensquare.user.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserDao userDao;
public User login(User user) {
return userDao.selectOne(user);
}
}
9) 编写controller
package com.tensquare.user.controller;
import com.tensquare.entity.Result;
import com.tensquare.entity.StatusCode;
import com.tensquare.user.pojo.User;
import com.tensquare.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("user")
@CrossOrigin
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "login",method = RequestMethod.POST)
public Result login(@RequestBody User user){
User result = userService.login(user);
if(result != null){
return new Result(true, StatusCode.OK,"登录成功",result);
}
return new Result(false, StatusCode.ERROR,"登录失败");
}
}
2. 即时通讯前端准备
访问环信IM开发文档--> Web客户端 --> SDK集成介绍 --》Web IM 集成介绍
或者直接访问http://docs-im.easemob.com/im/web/intro/integration
2.1 按照文档,使用git下载集成案例:
$ git clone https://github.com/easemob/webim.git
2.2 复制案例中的\webim\sdk目录下的所有js文件到项目resources\static\js中
2.3 复制webim\simpleDemo中的资料到resources\static中

测试demo.html,确认即时通讯的用户登录,发文本消息,效果如下

3. 发送和接收消息
复制Spring-websocket项目中的chatroom.jsp改造为chatroom.html,根据demo.html案例实现用户注册和登录和即时消息功能。最终效果:
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="edge" /> <title>聊天室</title> <script src="js/jquery-1.12.3.min.js"></script> <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"> <script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> <style> body{ margin-top:5px; } </style> <script type="text/javascript" src="WebIMConfig.js"></script> <script type="text/javascript" src="js/EMedia_x1v1.js"></script> <script type="text/javascript" src="js/webimSDK3.0.4.js"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-md-3"> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">登录和注册</h3> </div> <div class="panel-body"> <input type="text" class="form-control" id="userId" placeholder="用户id"/><br> <button id="reg" type="button" class="btn btn-primary">注册</button> <button id="login" type="button" class="btn btn-primary">登录</button> </div> </div> </div> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">消息接收者</h3> </div> <div class="panel-body"> <div class="list-group"> <input type="text" class="form-control" id="toUserId" placeholder="接收消息用户id"/><br> </div> </div> </div> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">群发系统广播</h3> </div> <div class="panel-body"> <input type="text" class="form-control" id="msg" /><br> <button id="broadcast" type="button" class="btn btn-primary">发送</button> </div> </div> </div> <div class="col-md-9"> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title" id="talktitle"></h3> </div> <div class="panel-body"> <div class="well" id="log-container" style="height:400px;overflow-y:scroll"> </div> <input type="text" id="myinfo" class="form-control col-md-12" /> <br> <button id="send" type="button" class="btn btn-primary">发送</button> </div> </div> </div> </div> </div> <script> //创建连接 var conn = {}; console.log(WebIM, window.WebIM); WebIM.config = config; conn = WebIM.conn = new WebIM.default.connection({ appKey: WebIM.config.appkey, isHttpDNS: WebIM.config.isHttpDNS, isMultiLoginSessions: WebIM.config.isMultiLoginSessions, host: WebIM.config.Host, https: WebIM.config.https, url: WebIM.config.xmppURL, apiUrl: WebIM.config.apiURL, isAutoLogin: false, heartBeatWait: WebIM.config.heartBeatWait, autoReconnectNumMax: WebIM.config.autoReconnectNumMax, autoReconnectInterval: WebIM.config.autoReconnectInterval, isStropheLog: WebIM.config.isStropheLog, delivery: WebIM.config.delivery }) //回调方法 conn.listen({ onOpened: function (message) { //连接成功回调 var myDate = new Date().toLocaleString(); console.log("%c [opened] 连接已成功建立", "color: green"); console.log(myDate); // rek(); // alert(myDate + "登陆成功") }, onClosed: function (message) { console.log("onclose:" + message); console.log(error); }, //连接关闭回调 onTextMessage: function (message) { console.log('onTextMessage: ', message); $("#log-container").append("<div class='bg-info'><label class='text-danger'>接收到id为"+message.from+"的消息:</label><div class='text-success'>"+message.data+"</div></div><br>"); alert("end"); } }); var userId; var nickname; var password; //注册 //本案例使用用户id即可完成注册和登录 document.getElementById("reg").onclick = function () { userId = document.getElementById("userId").value; //设置Ajax 是同步的,需要先获取用户数据再注册 $.ajaxSettings.async = false $.get("/user/"+userId,function (data) { nickname = data.data.nickname; password = data.data.password; }); alert(nickname); alert(password); var option = { username: userId, nickname: nickname, password: password, appKey: WebIM.config.appkey, success: function () { console.log('注册成功'); }, error: function () { console.log('注册失败'); }, apiUrl: WebIM.config.apiURL }; conn.signup(option); }; //登录 document.getElementById("login").onclick = function () { userId = document.getElementById("userId").value; $.ajaxSettings.async = false $.get("/user/"+userId,function (data) { password = data.data.password; }); var options= { user: userId, pwd: password, appKey: WebIM.config.appkey, apiUrl: WebIM.config.apiURL }; conn.open(options); console.log(options); }; //文本消息 var conf = WebIM.config WebIM.config = conf WebIM.message = WebIM.default.message WebIM.utils = WebIM.default.utils WebIM.debug = WebIM.default.debug WebIM.statusCode = WebIM.default.statusCode var myDate = new Date().toLocaleString(); document.getElementById('send').onclick = function () { var tname = document.getElementById('toUserId').value; var tmsg = document.getElementById("myinfo").value; var id = conn.getUniqueId(); //生成本地消息id var msg = new WebIM.default.message('txt',id);// msg.set({ msg: tmsg, //消息内容 to: tname, ext:{ 'time': myDate }, // 接收消息对象(用户id) success: function (id,serverMsgId) { console.log('send private text success'); msgText = msg.body.msg; }, fail: function (e) { console.log('send private text error'); } }); msg.body.chatType = 'singleChat'; conn.send(msg.body); //在聊天信息显示页面展示聊天数据 $("#log-container").append("<div class='bg-info'><label class='text-danger'>发送给id为"+tname+"的" + "消息:</label><div class='text-success'>"+tmsg+"</div></div><br>"); console.log(msg); }; </script> </body> </html>
浙公网安备 33010602011771号