栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

WebSocket实现聊天功能

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力
使用SpringBoot + WebSocket 实现模拟QQ聊天功能

登录界面展示

登录界面模仿QQ登录操作,支持拖动、最小化和关闭

聊天界面展示

登录后的右侧显示在线用户,右下方显示在线用户的登录日志
窗口支持拖动、关闭操作


发送消息界面展示

在线用户实现及时聊天功能,可以对指定用户发起聊天(实现点对点的消息推送功能)
支持消息的本地缓存,聊天内容不会因为页面的刷新、关闭、退出登录等操作而丢失(消息只是做了简单缓存),清理浏览器缓存数据时消息数据便会丢失。

点对点消息推送,实现一对一的即时通信功能

Demo的目录代码

该Demo主要使用的是 SpringBoot + WebSocket 技术实现

下面是Demo的后端代码实现及说明 创建SpringBoot项目,导入依赖

项目pom依赖配置

	
		1.8
		1.8
		1.8
		UTF-8
		UTF-8
	

	
		
		
			org.springframework.boot
			spring-boot-starter-web
		

		
		
			org.springframework.boot
			spring-boot-starter-websocket
		

		
		
			org.springframework.boot
			spring-boot-devtools
			true
			true
		

		
		
			org.apache.commons
			commons-lang3
		
        
        
			cn.hutool
			hutool-all
			5.7.16
		

		
		
			org.slf4j
			slf4j-api
		
		
			org.slf4j
			slf4j-log4j12
		

		
		
			com.alibaba
			fastjson
			1.2.55
		
	

	
		
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	
项目配置文件说明

application.properties

# 项目名称
spring.application.name=websocket-chatroom
# 配置资源路径
spring.resource.static-locations=classpath:/static/
# 视图前缀配置
spring.mvc.view.prefix=/chat/
# 视图后缀配置
spring.mvc.view.suffix=.html
###########################【热部署】#########################
# 重启目录
spring.devtools.restart.additional-paths=src/main/java
# 设置开启热部署
spring.devtools.restart.enabled=true
# 设置字符集
spring.freemarker.charset=utf-8
# 页面不加载缓存,修改后立即生效
spring.freemarker.cache=false
# 服务端口配置
server.port=80

application.yml

spring:
  resource:
    static-locations: classpath:/static/    
  application:
    name: websocket-chatroom
  mvc:
    view:
      suffix: .html
      prefix: /chat/
  devtools: 
    restart:
      additional-paths: src/main/java
      enabled: true
  freemarker: 
    charset: utf-8
    cache: false
server:
  port: 80
项目的配置类说明

WebConfig.java

WebConfig 配置类

配置后项目启动时,访问默认项目路径时,会跳转到该类指定的页面中

@Configuration
public class WebConfig implements WebMvcConfigurer {
	
	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		registry.addViewController("/").setViewName("/chat/login");
	}
}

WebSocketConfig.java

使用WebSocket前首先配置 @ServerEndpoint

  • 首先需要注入 ServerEndpointExporter ,

  • 这个bean会自动注册使用 @ServerEndpoint 注解来声明WebSocket endpoint。

  • 注意:如果使用独立的Servlet容器,而不是直接使用SpringBoot内置容器,就不需要注入 ServerEndpointExporter,因为他将由容器自己提供和管理。

@Configuration
public class WebSocketConfig {
	
	@Bean
	public ServerEndpointExporter serverEndpointExporter() {
		return new ServerEndpointExporter();
	}
}

GetHttpSessionConfigurator.java

该类可以在建立连接后存放HttpSession,方便后续的使用

用户建立连接时,通过 EndpointConfig 获取存在 session 中的用户数据

public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator {
	
	@Override
	public void modifyHandshake(ServerEndpointConfig sec, 
                                HandshakeRequest request, 
                                HandshakeResponse response) {
		// 获取httpsession对象
		HttpSession httpSession = (HttpSession) request.getHttpSession();
		// 存放httpsession对象
		Map userProperties = sec.getUserProperties();
		userProperties.put(HttpSession.class.getName(), httpSession);
	}
}
创建用户对象实体
@Data
public class User implements Serializable {
    private static final long serialVersionUID = -31513108721728277L;
    
	private String userId;
    
    private String username;
    
    private String phone;
    
    private String password;
    public User(String userId, String username, String password, String phone) {
		this.userId = userId;
		this.username = username;
		this.password = password;
		this.phone = phone;
	}
    public User() {
    }
}  
创建数据信息对象

使用数据信息对象来模拟数据存储数据,实现用户的登录和注册

import cn.hutool.core.lang.Validator;
import cn.molu.app.pojo.User;
import cn.molu.app.vo.R;

public class UserData {
	
	public static Map userMap = new HashMap();
	static {
        //userMap.key=phone, userMap.value=user(id, name, password, phone);
		userMap.put("150******67", new User("001", "jack", "123456", "150******67"));
		userMap.put("135******88", new User("002", "mary", "123456", "135******88"));
		userMap.put("136******66", new User("003", "tom", "123456", "136******66"));
		userMap.put("159******21", new User("004", "tim", "123456", "159******21"));
		userMap.put("188******88", new User("005", "jenny", "123456", "188******88"));
		userMap.put("177******14", new User("006", "admin", "123456", "177******14"));
		userMap.put("176******67", new User("007", "lover", "123456", "176******67"));
		userMap.put("150******83", new User("008", "molu", "123456", "150******83"));
	}
	
	public static User loginByPhone(String phone) {
		boolean mobile = Validator.isMobile(phone);
		if (!mobile) {
			return null;
		}
		User user = userMap.get(phone);
		if (ObjectUtils.isBlank(user)) {
			return null;
		}
		return user;
	}
	
	public static R register(HttpServletResponse res, User user) {
		if (null == user) {
			return R.err("请输入手机号、用户名和密码!");
		}
		String phone = user.getPhone();
		String username = user.getUsername();
		String password = user.getPassword();
		ObjectUtils.checkNull(res, "手机号、用户名和密码不能为空!", phone, username, password);
		user.setUserId(String.format("%03d", String.valueOf(userMap.size() + 1)));
		userMap.put(phone, user);
		return R.ok("注册成功!");
	}
}
数据响应实体类

响应数据结果,存储用户基本数据,过滤掉用户的重要信息

@Data
public class Result {
	
	private boolean flag;
	
	private String message;
	
	private String username;
	
	private String userId;
	
	private String dateStr;

	public void setDateStr(Date date) {
		this.dateStr = dateFormat(date);
	}

	public Result() {
		super();
	}

	public static String dateFormat(Date date) {
		return ObjectUtils.dateFormat(date);
	}
}
消息接收和响应类

用于接收和返回数据前台数据

public class ResultMessage {
	
	private Boolean systemMsgFlag;
	
	private String fromName;
	
	private String fromId;
	
	private String toName;
	
	private String toId;
	
	private Object message;
	
	private String dateStr;

	public void setDateStr(String dateStr) {
		this.dateStr = dateStr;
	}

	public String getDateStr(Date date) {
		if (date == null) {
			date = new Date();
		}
		return dateFormat(date);
	}

	public void setDateStr() {
		this.dateStr = dateFormat(new Date());
	}

	public void setDateStr(Date date) {
		if (date == null) {
			date = new Date();
		}
		this.dateStr = dateFormat(date);
	}

	public ResultMessage() {
		super();
	}
    
	public static String dateFormat(Object date) {
		return ObjectUtils.dateFormat(date);
	}
}
WS核心服务类

webSocket 的核心服务类,建立连接、发送消息、推送通知、关闭连接释放资源、消息处理等。。。

@Component
@ServerEndpoint(value = "/webSocket/{userId}", configurator = GetHttpSessionConfigurator.class)
public class ChatEndpoint {
	private final static Logger LOGGER = LogManager.getLogger(ChatEndpoint.class);
	
	private static Map onLineUsers = new ConcurrentHashMap();
	
	public static Map cacheUser = new HashMap();
    
	
	private HttpSession httpSession;

	
	@OnOpen
	public void onOpen(Session session, EndpointConfig endpointConfig) {
        // 获取GetHttpSessionConfigurator中存放的HttpSession
		Map userProperties = endpointConfig.getUserProperties();
		HttpSession httpSession = (HttpSession) userProperties.get(HttpSession.class.getName());
		this.httpSession = httpSession;
		String username = ObjectUtils.getStr(httpSession.getAttribute("username")) ;
		String userId = ObjectUtils.getStr(httpSession.getAttribute("userId"));
        // 如果用户名和用户id为空,则直接返回
		if (ObjectUtils.isEmpty(username,userId)) {
			return;
		}
        LOGGER.info("{}	建立了连接。。。", username);
        Result res = new Result();
		res.setUserId(userId);
		res.setUsername(username);
		// 缓存数据
		onLineUsers.put(userId, session);
		cacheUser.put(userId, res);
		// 组织消息体数据,将数据推送给所有在线用户
		String message = getSysMessage(getusers());
		// 调用方法进行系统消息的推送
		broadcastAllUsers(message);
		LOGGER.info("推送系统消息:{}	", message);
	}

	
	@OnMessage
	public void onMessage(String message, Session session) throws IOException {
		LOGGER.info("接收到消息:{}", message);
		if (StringUtils.isBlank(message)) {
			return;
		}
        // 心跳检测机制
		if ("PING".toUpperCase().equals(message.toUpperCase())) {
			heartCheck(session);
			return;
		}
		LOGGER.info("接收到好友的消息:{}", message);
		ResultMessage msgObj = JSON.parseObject(message, ResultMessage.class);
        // 消息接收人id
		String toId = msgObj.getToId();
        // 获取消息体内容
		String text = ObjectUtils.getStr(msgObj.getMessage());
		// 获取推送指定用户数据
		String resultMessage = getMessage(msgObj, text);
		LOGGER.info("接收到好友发来的数据:{}", resultMessage);
		// 点对点发送数据(给指定用户发送消息)
		Session toSession = onLineUsers.get(toId);
		if (toSession != null && toSession.isOpen()) {
            Basic basicRemote = toSession.getBasicRemote();
            basicRemote.sendText(resultMessage);
		}
	}

	
	@OnClose
	public void onClose(Session session) {
		if (httpSession == null) {
			return;
		}
		String username = ObjectUtils.getStr(httpSession.getAttribute("username"));
		String userId = ObjectUtils.getStr(httpSession.getAttribute("userId"));
		if (StringUtils.isBlank(userId)) {
			return;
		}
		LOGGER.info("{}:关闭了连接。。。", username);
		// 移除已关闭连接的用户
		onLineUsers.remove(userId);
        // 移除缓存的用户数据
		cacheUser.remove(userId);
		LOGGER.info("已从onLineUsers移除:{},从cacheUser中移除:{}", username, username);
		String message = getSysMessage(getusers());
		// 设置已关闭连接的用户数据在HttpSession域中有效时间
		httpSession.setMaxInactiveInterval(1800);
		broadcastAllUsers(message);
        LOGGER.info("关闭连接,推送内容:{}", message);
	}

	
	@OnError
	public void onError(Session session, Throwable error) {
		LOGGER.info("连接出错了......{}", error);
	}
    
	
	private void broadcastAllUsers(String message) {
		try {
			// 将消息推送给所有的在线用户
			Set ids = getIds();
			LOGGER.info("onLineUsers的所有id:{}", ids);
			for (String id : ids) {
				Session session = onLineUsers.get(id);
				Result result = cacheUser.get(id);
				LOGGER.info("获取到用户信息:{}", result);
				// 判断用户是否是连接状态
				if (session.isOpen()) {
					session.getBasicRemote().sendText(message);
				}
			}
			LOGGER.info("给{}推送了{}", getIds(), message);
		} catch (Exception e) {
			LOGGER.error("广播发送系统消息失败!{}", e);
			e.printStackTrace();
		}
	}
    
    
	public static String getMessage(ResultMessage resultMessage, String message) {
		resultMessage.setSystemMsgFlag(false);
		resultMessage.setMessage(message);
		ObjectMapper objectMapper = new ObjectMapper();
		try {
			return objectMapper.writeValueAsString(resultMessage);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return "";
	}
    
    
	public static String getSysMessage(Collection collection) {
		ResultMessage resultMessage = new ResultMessage();
		resultMessage.setSystemMsgFlag(true);
		resultMessage.setMessage(collection);
		ObjectMapper objectMapper = new ObjectMapper();
		try {
			return objectMapper.writeValueAsString(resultMessage);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return "";
	}
    
    
	public static void heartCheck(Session session) {
		try {
			Map params = new HashMap();
			params.put("type", "PONG");
			session.getAsyncRemote().sendText(JSON.toJSONString(params));
			LOGGER.info("应答客户端的消息:{}", JSON.toJSONString(params));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
    
    
	
	private Set getIds() {
		return ChatEndpoint.onLineUsers.keySet();
	}

	
	private Collection getusers() {
		return cacheUser.values();
	}

	
	public static String dateFormat(Date date) {
		return ObjectUtils.dateFormat(date);
	}
}
后台控制器接口

后端访问接口

@Controller
@RequestMapping("index")
public class LoginController {

	
	@ResponseBody
	@PostMapping("/login")
	public Result login(User user, HttpServletRequest req,HttpServletResponse res) {
        HttpSession session = req.getSession();
        ObjectUtils.checkNull(res,"请输入手机号和密码!",user,user.getPhone(),user.getPassword());
		String phone = user.getPhone();
		String password = user.getPassword();
        boolean mobile = Validator.isMobile(phone);
        Result result = new Result();
        if(!mobile){
            result.setMessage("手机号格式错误!");
			result.setFlag(false);
            return result;
        }
		try {
            User userData = UserData.loginByPhone(phone);
			ObjectUtils.checkNull(res,userData,String.format("登录失败,未获取到%s的用户信息!", phone));
			if (password.equals(userData.getPassword())) {
				String username = userData.getUsername();
				result.setFlag(true);
				result.setMessage("登录成功!");
				result.setUsername(username);
				String userId = userData.getUserId();
				result.setUserId(userId);
				result.setDateStr(new Date());
				session.setAttribute("username", username);
				session.setAttribute("userId", userId);
			} else {
				result.setMessage("登录失败,密码输入错误!");
				result.setFlag(false);
			}
		} catch (Exception e) {
			e.printStackTrace();
			result.setMessage("登录失败!",e.getMessage());
			result.setFlag(false);
		}
		return result;
	}

	
	@GetMapping("/toChatroom")
	public String toChatroom(HttpSession session) {
		String username =ObjectUtils.getStr(session.getAttribute("username"));
		if (StringUtils.isBlank(username)) {
			return "login";
		}
		return "div";
	}

	
	@ResponseBody
	@GetMapping("/getUsername")
	public Map getUsername(HttpSession session) {
		Map map = new HashMap();
		String username = (String) session.getAttribute("username");
		String userId = (String) session.getAttribute("userId");
		map.put("flag", true);
		map.put("username", username);
		map.put("userId", userId);
		return map;
	}
    
    
    @GetMapping(value = "/toIndex")
	public String toIndexPage() {
		return "login";
	}
}
登录页面代码

	
		
		登录
		
		
		
		
		
	
	
		
WS   请登录   X 一

WebSocket实现聊天功能

找回密码
登录页面JS代码
$(function() {
    $(".close").click(function() {
        $(".box").hide();
    });
    $("#loginFormBtn").click(function() {
        if (loginCheckData()) {
            login();
        }
    });
    $(".showPwd").bind("input propertychange", function() {
        if ($(this).prop("checked")) {
            $(".upwd").attr("type", "text");
        } else {
            $(".upwd").attr("type", "password");
        }
	})
});

function login() {
    let params = {};
    params.phone = ml.empty($('.phone').val());
    params.password = ml.empty($('.upwd').val());
    params.flag = $("input[name='rememberMe']").prop("checked");
    $.post("/index/login", params, function(res) {
        if (res.flag) {
            ml.msgBox(res.message);
            location.href = "/index/toChatroom";
        } else {
            ml.msgBox(res.message, 5, 5);
        }
    }).error(function(err) {
        ml.msgBoxBtn(err.responseJSON.status + ":" + err.responseJSON.message, "错误提示");
    })
}

function loginCheckData() {
    let phone = ml.empty($('.phone').val());
    if (!phone || phone.length != 11) {
        ml.tips("请输入正确的手机号!", "phone");
        return false;
    }
    // 不可包含中文及中文字符
    let regZh = /[u4e00-u9fa5][u3000-u301eufe10-ufe19ufe30-ufe44ufe50-ufe6buff01-uffee]/;
    //1.验证手机号 规则:第一位1,第二位是358中的一个,第三到十一位必须是数字。总长度11
    let reg = /^[1][358][0-9]{9}$/;
    if (!reg.test(phone) || regZh.test(phone)) {
        ml.tips("输入的手机号格式不正确!", "phone");
        return false;
    }
    let password = ml.empty($('.upwd').val());
    if (!password) {
        ml.tips("请输入密码!", "upwd");
        return false;
    }
    if (regZh.test(password)) {
        ml.tips("密码不可包含中文字符!", "upwd");
        return false;
    }
    if (password.length < 6) {
        ml.tips("密码必须为6~16个字符之间!", "upwd");
        return false;
    }
    let regPwd = /[A-Za-z0-9.!?]{12,30}/;
    if (!regPwd.test(password)) {
        ml.tips("密码仅支持数字、大小写字母和.!?符号", "upwd");
        return false;
    }
    //ml.msgBox("校验通过!");
    return true;
}
聊天界面代码











	
X
请选择好友聊天
    系统消息

      • WebSocket实现聊天功能
        快去找朋友聊聊吧。。。
      聊天界面JS代码
      let webObj = null;//全局WebSocket对象
      let lockReconnect = false; // 网络断开重连
      let wsCreateHandler = null; // 创建连接
      let username = null; // 当前登录人姓名
      let userId = null; //当亲登录人id
      let toName = null; //消息接收人姓名
      let toId = null;//消息接收人id
      $(function() {
      	$(".bg_change_size").remove();
      	// 在ajax请求开始前将请求设为同步请求:$.ajaxSettings.async = false。
      	// 在ajax请求结束后不要忘了将请求设为异步请求,否则其他的ajax请求也都变成了同步请求 $.ajaxSettings.async = true。
      	$.ajax({
      		async: false,
      		type: 'GET',
      		url: "/index/getUsername",
      		success: function(res) {
      			if (!res.userId || !res.username) {
      				location.href = '/index/toIndex';
      			}
      			username = res.username;
      			userId = res.userId;
      		}
      	});
      	// 创建webSocket对象
      	createWebSocket();
      	// 发送消息到服务器
      	$(".sendMsg").on("click", function() {
      		sendMessage();
      	})
      });
      
      
      function createWebSocket() {
      	try {
      		// 获取访问路径,带有端口号:ws://localhost/webSocket/001
      		let host = window.location.host;
      		// 创建WebSocket连接对象
      		webObj = new WebSocket(`ws://${host}/webSocket/${userId}`);
      		// 加载组件
      		initWsEventHandle();
      	} catch (e) {
      		ml.msgBox("连接出错,正在尝试重新连接,请稍等。。。");
      		// 尝试重新连接服务器
      		reconnect();
      	}
      }
      
      
      function initWsEventHandle() {
      	try {
      		// 建立连接
      		webObj.onOpen = function(evt) {
      			onWsOpen(evt);
      			// 建立连接之后,开始传输心跳包
      			heartCheck.start();
      		};
      		// 传送消息
      		webObj.onmessage = function(evt) {
      			// 发送消息
      			onWsMessage(evt);
      			// 接收消息后 也需要心跳包的传送
      			heartCheck.start();
      		};
      		// 关闭连接
      		webObj.onclose = function(evt) {
      			// 关闭连接,可能是异常关闭,需要重新连接
      			onWsClose(evt);
      			// 尝试重新连接
      			reconnect();
      		};
      		// 连接出错
      		webObj.onerror = function(evt) {
      			// 连接出错
      			onWsError(evt);
      			// 尝试重新连接
      			reconnect();
      		}
      	} catch (e) {
      		if (e) {
      			conlog("catch", e);
      		}
      		ml.msgBox("初始化组件失败,正在重试,请稍后。。。");
      		// 尝试重新创建连接
      		reconnect();
      	}
      }
      
      
      function onWsOpen(e) {
      	if (e.data) {
      		conlog("onWsOpen", e.data);
      	}
      	ml.msgBox("建立连接成功。。。");
      }
      
      
      function onWsMessage(e) {
      	if (e.data) {
      		conlog("onWsMessage", e.data);
      	}
      	let jsonStr = e.data;
      	//接收到服务器推送的消息后触发事件
      	message(e);
      }
      
      
      function onWsClose(e) {
      	if (e.data) {
      		conlog("onWsClose", e.data);
      	}
      	ml.msgBox("连接关闭,尝试重新连接服务器,请稍侯。。。");
      	closeFun(e);
      }
      
      function onWsError(e) {
      	ml.msgBox("连接出错,正在尝试重新连接服务器,请稍侯。。。" + e.data);
      }
      
      
      function conlog(msg) {
      	conlog('', msg);
      }
      
      
      function conlog(title, msg) {
      	let content = msg;
      	if (title) {
      		content = `${title}:${msg}`;
      	}
      	console.log(`${content}`);
      }
      
      
      function reconnect() {
      	if (lockReconnect) {
      		return;
      	}
      	conlog("reconnect");
      	ml.msgBox("正在尝试重新连接,请稍侯。。。");
      	lockReconnect = true;
      	// 没链接上会一直连接,设置延迟,避免过多请求
      	wsCreateHandler && clearTimeout(wsCreateHandler);
      	wsCreateHandler = setTimeout(function() {
      		ml.msgBox("正在重新连接。。。");
      		createWebSocket();
      		lockReconnect = false;
      		ml.msgBox("重连完成。。。");
      	}, 1000);
      }
      
      
      var heartCheck = {
      	// 在15s内若没收到服务端消息,则认为连接断开,需要重新连接
      	timeout: 15000, // 心跳检测触发时间
      	timeoutObj: null,
      	serverTimeoutObj: null,
      	// 重新连接
      	reset: function() {
      		clearTimeout(this.timeoutObj);
      		clearTimeout(this.serverTimeoutObj);
      		this.start();
      	},
      	// 开启定时器
      	start: function() {
      		let self = this;
      		this.timeoutObj && clearTimeout(this.timeoutObj);
      		this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
      		this.timeoutObj = setTimeout(function() {
      			ml.msgBox("发送ping到后台服务。。。");
      			try {
      				webObj.send("PING");
      			} catch (e) {
      				ml.msgBox("发送ping异常。。。");
      			}
      			//内嵌定时器
      			self.serverTimeoutObj = setTimeout(function() {
      				// 若onclose方法会执行reconnect方法,我们只需执行close()就行,
                      // 若直接执行reconnect会触发onclose导致重连两次
      				ml.msgBox("没有收到后台数据,关闭连接。。。");
      				webObj.close();
      				//reconnect();
      			}, self.timeout);
      		}, this.timeout);
      	}
      };
      
      
      function message(e) {
      	//获取服务端推送过来的消息
      	let message = e.data;
      	// 将message转为JSON对象
      	let res = JSON.parse(message);
      	// 是否为系统消息
      	if (res.systemMsgFlag) {
      		let allNames = res.message;
      		//1. 好友列表展示   2. 系统推广
      		let userListStr = "";
      		let broadcastListStr = "";
      		let imgUrl = "..https://blog.csdn.net/imgs/chatIc.png";
      		for (let user of allNames) {
      			if (user.userId != userId) {
      				userListStr += `
    • ${imgUrl}" class='friendList-img'>${user.username}
    • `; broadcastListStr += `
    • ${user.dateStr}
      好友${user.username}上线了!
    • `; } } $(".friend-list").html(userListStr); $(".sys-msg").html(broadcastListStr); } else { // 不是系统消息 let msgText = res.message; let msg = `
    • ${imgUrl}' class='img'/>${msgText}
    • `; if (toId === res.fromId) { $(".chat-msg").append(msg); } let chatData = sessionStorage.getItem(res.fromId); if (chatData) { msg = chatData + msg; } sessionStorage.setItem(res.fromId, msg); $(".chat-main")[0].scrollTop = $(".chat-main")[0].scrollHeight; } } // 关闭连接 function closeFun(e) { let tips = `${new Date()}
      `; $(".sys-msg").html(`${tips}用户:${username}离开了`); } // 选择好友 function chatWith(id, name, obj) { toId = id; toName = name; $(".edit-msg").attr("disabled", false); $(".div-btn").show(); $(".chat-msg").show(); $(obj).addClass("selected-li").siblings().removeClass("selected-li"); let chatNow = `正在和${name}聊天`; $(".div-main-title").html(chatNow); $(".chat-msg").html(""); var chatData = sessionStorage.getItem(toId); if (chatData) { //渲染聊天数据到聊天区 $(".chat-msg").html(chatData); } $(".chat-main")[0].scrollTop = $(".chat-main")[0].scrollHeight; } function sendMessage() { // 发送消息 if (!toId || !toName) { ml.tips("sendMsg", "请选择好友..."); return; } let msg = $(".edit-msg").val(); if (!msg) { ml.tips("sendMsg", "请输入内容..."); return; } let img = `${imgUrl}' class='myself-img'/>`; let li = $("
    • "); li.html(`${img}${msg}`); $(".chat-msg").append(li); $(".edit-msg").val(''); $(".chat-main")[0].scrollTop = $(".chat-main")[0].scrollHeight; let chatData = sessionStorage.getItem(toId); let liStr = `
    • ${img}${msg}
    • `; if (chatData) { liStr = chatData + liStr; } let jsonMessage = { "fromName": username, //消息发送人姓名 "fromId": userId, //消息发送人id "toName": toName, //消息接收人姓名 "toId": toId, //消息接收人id "message": msg //发送的消息内容 }; // 将消息存放到sessionStorage中 sessionStorage.setItem(toId, liStr); // 发送数据给服务器(消息发送格式为JSON格式) webObj.send(JSON.stringify(jsonMessage)); }
      转载请注明:文章转载自 www.mshxw.com
      本文地址:https://www.mshxw.com/it/871572.html
      我们一直用心在做
      关于我们 文章归档 网站地图 联系我们

      版权所有 (c)2021-2022 MSHXW.COM

      ICP备案号:晋ICP备2021003244-6号