socket 内聊工具另一个版本
来源:互联网 发布:浙江软件协会 编辑:程序博客网 时间:2024/05/24 07:15
1. 后台结构:
2.需求的jar 包
3. WSConfig.java
/** * */package com.ws.config;import java.util.Set;import javax.websocket.Endpoint;import javax.websocket.server.ServerApplicationConfig;import javax.websocket.server.ServerEndpointConfig;/** * @author zhong * */public class WSConfig implements ServerApplicationConfig {/** * 用注解的方式实现 */@Overridepublic Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scand) {System.out.println("=======> WSConfig:"+scand.size());return scand;}/** * 用接口的方式实现 */@Overridepublic Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> arg0) {return null;}}
4.ChatSocket.java
/** * */package com.ws.socket;import java.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import javax.websocket.OnClose;import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.ServerEndpoint;import com.alibaba.fastjson.JSON;import com.ws.bean.Content;import com.ws.bean.Message;import com.ws.bean.User;/** * @author zhong * */@ServerEndpoint(value="/echo")public class ChatSocket {private static String user = null;private static List<Session> sessions = new ArrayList<Session>();private static List<Map<String,Object>> userList = new ArrayList<Map<String,Object>>();private static Map<String, Session> map = new HashMap<String, Session>();public ChatSocket(){}@OnOpenpublic void open(Session session){user = getSessionUser(session);Session ms = map.get(user);if(ms == null){map.put(user, session);sessions.add(session);User u = new User();u.setGroup("myfriend");u.setNickname(user);u.setSignature("我就是我,大名叫"+user+"的我~");userList.add(getUserMap(u));Message message = new Message();message.setType("online");message.setUsers(userList);message.setFrom(user);broadcast(sessions,JSON.toJSONString(message));System.out.println("===== 欢迎 "+user+" 进入IM, 当前共 "+userList.size() +" 人在线!");}}/** * 消息广播 * @param sessions * @param json */private void broadcast(List<Session> sessions, String msg) {for(Iterator<Session> iterator = sessions.iterator(); iterator.hasNext();){Session session = (Session) iterator.next();try {if(session != null){session.getBasicRemote().sendText(msg);}else{System.out.println("======> broadcast session is NUll. by "+user);}} catch (IOException e) {System.out.println("=======> broadcast:"+user+" 已退出");e.printStackTrace();}}}@OnClosepublic void close(Session session){user = getSessionUser(session);sessions.remove(session);if(userList != null && userList.size() > 0){for (int i=0; i<userList.size(); i++) {Map<String, Object> map = userList.get(i);if(map.get(user) != null){userList.remove(map);}}}map.remove(user);Message message = new Message();message.setType("offline");message.setUsers(userList);System.out.println("======> "+user +" 已离线, 当前在线共 "+userList.size() +" 人!");broadcast(sessions,JSON.toJSONString(message));}/** * 消息响应方法 * @param session * @param json */@OnMessagepublic void message(Session session,String json){String fromUser = getSessionUser(session);String toUser = null;Content content = (Content) JSON.parseArray(json, Content.class);if(content == null){return;}System.out.println("===== message:"+content.getMsg());//null 或 singleif(content.getMode() == null){String to = content.getTo();if(to != null && to != ""){String toArr[] = to.split(","); if(toArr == null || toArr.length == 0 ){return;}for(int i=0; i<toArr.length; i++){Session toSession = map.get(toArr[i]);if(toSession == null){continue;}toUser = getSessionUser(toSession);try {Message message = new Message();message.setType("message");message.setFrom(fromUser);message.setTo(toUser);message.setLayer(content.getLayer());message.setContent(content.getMsg());toSession.getBasicRemote().sendText(JSON.toJSONString(message));} catch (IOException e) {e.printStackTrace();}}}}else if(("model").equalsIgnoreCase(content.getMode())){Message message = new Message();message.setLayer(content.getLayer());message.setFrom(user);message.setType("message");message.setContent(content.getMsg());broadcast(sessions, JSON.toJSONString(message));}}/** * 获取用户map * @author zhong * @param u * @return */public static Map<String, Object> getUserMap(User u){Map<String, Object> umap = null;if(u != null){umap = new HashMap<String, Object>();umap.put(user, JSON.toJSONString(u));}return umap;}/** * 获取session用户 * @author zhong * @param session * @return */public static String getSessionUser(Session session){String result = null;if(session != null){String parms = session.getQueryString();String[] parmArr = parms.split("=");if(parmArr != null && parmArr.length > 1){result = parmArr[1];}}return result;}}
另外的消息类我就不贴代码了
6.前台核心代码:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";pageContext.setAttribute("basePath", basePath);%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="<%=basePath%>"> <title>PQ - 内聊版</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><%@ include file="include.jsp" %><style type="text/css">form {margin:0 auto;margin-top:10%;}</style> </head> <body><div class="content"></div><script type="text/javascript">var ws = null;var userName = "${userName}"; //当前登录用户var host = "192.168.1.100:8080";var isOpen = false; //主窗口是否打开var sidx; //im主窗口indexvar slayero;var wsMsg;var wins = []; //存放当前打开的layer窗口 $(function(){ initWs(); }); function initWs(){ //页面打开后,连接socket var target = "ws://"+host+"/pwtchat/echo?userName="+userName; if ('WebSocket' in window) { ws = new WebSocket(target); console.log("WebSocket 请求成功"); } else if ('MozWebSocket' in window) { ws = new MozWebSocket(target); console.log("MozWebSocket 请求成功"); } else { alert('WebSocket is not supported by this browser.'); return; } //注册接收消息监听方法 ws.onmessage = function(event){ console.log(event); wsMsg = eval("("+event.data+")"); var type = wsMsg.type; if(!isOpen){ //显示im主窗口 isOpen = true; showIm(wsMsg); }else{ //更新好友上线或下线 if("online" == type || "offline" == type){ var imWin = window[slayero.find('iframe')[0]['name']]; imWin.updateFirendGroup(wsMsg.users); } } //好友消息接收 if(undefined != wsMsg.content && "message" == type){ console.log(wsMsg); var from = wsMsg.from;var idx = getLayerIdx(from); var body = layer.getChildFrame('body', idx); if(undefined != body){ var $show = body.find("#msg-show"); if(undefined != $show && $show.length> 0){ var msg = { nickname: from, msg: wsMsg.content, time: FY.getFormatLongDate(new Date()) }; $show.append(getMsgTemplate(msg)); //滚动条保持底部 $show.scrollTop( $show[0].scrollHeight ); } } } }; ws.onclose = function (event) { console.log(event); }; }; //发送一条消息 function wsSend(msgs){ ws.send(JSON.stringify(msgs)); } /* 显示主窗口 */ function showIm(msg){ return layer.open({ type: 2, id: "im-main", title: ['PQ - 内聊版', 'font-size:14px;'], area: ['270px', '430px'], fix: false, //不固定 maxmin: true, shade :0.1, content: "chat/chat-main-template.jsp", success: function(layero, index){ var win = { name: "im-main", idx: index }; wins.push(win); slayero = layero; sidx = index; }, end: function(){ window.location.href= "login.jsp"; } }); }; /* 显示聊天窗口 */function showMsgWindow(user){ if(userName == user.nickname){ FY.alert({ type: "warning",msg : "跟自家自儿发消息就没意思了!" }); return false; } var smidx = layer.open({ type: 2, id: user.nickname, title: ['PQ - 内聊版', 'font-size:14px;'], area: ['450px', '370px'], fix: false, //不固定 maxmin: false, shade :0, content: 'chat/chat-msg-template.jsp', success: function(layero, index){ var win = { name: "im-msg", idx: index, user: user.nickname == null ? "pwt_" : user.nickname }; wins.push(win);console.log(wins); var body = layer.getChildFrame('body', index); //更新当前用户信息 body.find("#nickname").text(user.nickname); body.find("#signature").text(user.signature); //动态绑定send事件 body.find("#msg-send").bind("click",function(){ var $inp = body.find("#msg-input"); var msg = $inp.text(); if(msg){ var msgs = { layer: index, msg: msg, to: user.nickname }; //提交给socket wsSend(msgs); //显示在自己的界面上 var msg = { nickname : userName, msg: msg, time: FY.getFormatLongDate(new Date()) }; var $show = body.find("#msg-show"); $show.append(getMsgTemplate(msg)); $show.scrollTop($show[0].scrollHeight ); //清空输入框 $inp.text(""); } }); }, end: function(){ removeLayerWin(smidx); } }); }; function getMsgTemplate(msg){var html="";if(msg){html+="<div class='msg-item'>"+ "<div class='msg-title'>"+ "<img class='mt-face' alt='' src='${basePath}images/face.jpg'>"+ "<div class='mt-name'>"+ "<span class='nickname'>"+msg.nickname+"</span>"+ "<span class='datetime'>"+msg.time+"</span>"+ "</div>"+ " </div>"+ "<div class='msg-content'>"+msg.msg+"</div>"+ "</div>";}return html;}/* 根据用户信息获取layer的index */function getLayerIdx(user){var idx = -1;if(FY.isEmpty(user)){return;}for(w in wins){if(wins[w].user == user){return wins[w].idx;}}return idx;}/* 关闭窗口时删除wins中的窗口信息 */function removeLayerWin(smidx){if(FY.isEmpty(smidx)){return;}for(w in wins){if(wins[w].idx == smidx){wins.splice(w,1);}}} </script> </body></html>
chat/chat-main-template.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";pageContext.setAttribute("basePath", basePath);%><link rel="stylesheet" type="text/css" href="${basePath}css/bootstrap/bootstrap.css"><link rel="stylesheet" type="text/css" href="${basePath}css/bootstrap/bootstrap-theme.css"><link rel="stylesheet" type="text/css" href="${basePath}css/bootstrap/fileinput.min.css"><link rel="stylesheet" type="text/css" href="${basePath}js/layer.2.4/layui.css"><script type="text/javascript" src='${basePath}js/jquery.min.js'></script><script type="text/javascript" src='${basePath}js/bootstrap/bootstrap.min.js'></script><script type="text/javascript" src='${basePath}js/layer.2.4/layer.js'></script><script type="text/javascript" src='${basePath}js/fy.utils.js'></script><style>body,html {padding: 0;margin: 0;}.im-header {width:100%;height: 75px;background: #F9f9f9;border-bottom:1px solid #eee;}.im-header .im-face-box,.im-info-box {float: left;}.im-header .im-face-box {width: 80px;height: 54px;border-radius: 54px;padding: 5px 5px 5px 20px;}.im-header .im-face-box>img {width: 54px;height: 54px;border-radius: 54px;}.im-header .im-info-box {width:165px;margin-left: 10px;overflow: hidden;}.im-header .im-info-box p {font-size: 12px;line-height: 20px;height: 20px;padding: 2px;margin: 2px;}/* 好友列表 */.im-friends {}.im-friends .friend-group {height:auto;margin:0 10px;line-height:30px;cursor: pointer;}.im-group-collapse {/* 分组折叠 */}.im-friends .friend-group .iconfont {padding-right:2px;font-size:10px;}.im-friends .im-ul-box {display:none;}.im-friends .im-ul-box .im-li {width:100%;height:50px;overflow: hidden;padding-left:30px;list-style: none;padding-top:3px;padding-bottom:3px;}.im-friends .im-li:hover {background: #eee;}.im-friends .im-li:hover .nickname {color:#000;}.im-friends .im-li .im-li-img,.im-li-text {float:left;}.im-friends .im-li .im-li-img {width:40px;border-radius:40px;}.im-friends .im-li .im-li-text {margin-left:10px;color:#888;}.im-friends .im-li-text .nickname,.signature {height:20px;line-height:15px;font-size:8px;cursor: default;}.im-friends .im-li-text .nickname {font-size:14px;}</style><div class="im-header"><div class="im-face-box"><img alt="" src="${basePath}images/face.jpg" width="100%"></div><div class="im-info-box"><p>在线 <i class="iconfont icon-nryc"></i></p><p id="nickname">vip 88888</p><p>IM实验田,来搞一个自己的聊天工具</p></div></div><div class="im-friends"><div class="friend-group" data-idx="0" data-name="myfriend"><span class="iconfont icon-nextpage"></span> 我的好友</div><div class="im-ul-box" data-name="myfriend"><ul class="im-group-ul collapse"><li class="im-li"><img class="im-li-img" alt="" src="${basePath}images/face.jpg"><div class="im-li-text"><div class="nickname">zeke</div><div class="signature">每天进步一点</div></div></li><li class="im-li"><img class="im-li-img" alt="" src="${basePath}images/face.jpg"><div class="im-li-text"><div class="nickname">zzw</div><div class="signature">最近爱好js了</div></div></li><li class="im-li"><img class="im-li-img" alt="" src="${basePath}images/face.jpg"><div class="im-li-text"><div class="nickname">kobe</div><div class="signature">牛哄哄</div></div></li></ul></div><div class="friend-group" data-idx="1" data-name="myworker"><span class="iconfont icon-nextpage"></span> 我的同事</div><div class="im-ul-box" data-name="myworker"><ul class="im-group-ul collapse"><li class="im-li"><img class="im-li-img" alt="" src="${basePath}images/face.jpg"><div class="im-li-text"><div class="nickname">zeke</div><div class="signature">每天进步一点</div></div></li><li class="im-li"><img class="im-li-img" alt="" src="${basePath}images/face.jpg"><div class="im-li-text"><div class="nickname">zzw</div><div class="signature">最近爱好js了</div></div></li><li class="im-li"><img class="im-li-img" alt="" src="${basePath}images/face.jpg"><div class="im-li-text"><div class="nickname">kobe</div><div class="signature">牛哄哄</div></div></li></ul></div></div><script type="text/javascript">$(function(){$("#nickname").text("${nickname}");var wsMsg = parent.wsMsg;//console.log(wsMsg);var users = wsMsg.users;//console.log(users);/* 更新用户自己的信息 */updateInfo(wsMsg.from);/* 更新好友列表 */updateFirendGroup(users);});/* 更新用户信息方法 */function updateInfo(name){$("#nickname").text(name);}/* 更新好友列表方法 */function updateFirendGroup(users){$(".im-group-ul").html("");var myfriends = '';var myworkers = '';if(users && users.length > 0){for(var i=0; i<users.length; i++){for(u in users[i]){var key = u; var user = FY.strToJson(users[i][u]);if(user && user.group){if(user.group == "myfriend"){myfriends += friendTempate(key,user);}else if(user.group == "myworker"){myworkers +=friendTempate(key,user);}}}}//更新列表var $uls = $(".im-ul-box");for(var g=0; g<$uls.length ; g++){var $ul = $uls.eq(g);var gname = $ul.data("name");if(gname == "myfriend"){$ul.find("ul").html(myfriends).fadeIn();}else if(gname == "myworder"){$ul.find("ul").html(myworkers).fadeIn();}}//绑定事件$(".im-li").each(function(){$(this).bind("dblclick",function(evt){var nickname = $(this).find(".nickname").text().trim();var signature = $(this).find(".signature").text().trim();var user = {nickname: nickname,signature: signature};parent.showMsgWindow(user);});});}}//好友列表模板function friendTempate(key,user){return "<li class='im-li'>"+ "<img class='im-li-img' alt='' src='${basePath}images/face.jpg'>"+ "<div class='im-li-text'>"+ "<div class='nickname'>"+key+"</div>"+ "<div class='signature'>"+user.signature+"</div>"+ "</div>"+ "</li>";}/* 折叠分组 */$(".friend-group").on("click",function(evt){var name = $(this).data("name"); var idx=0;$(".friend-group").each(function(){if($(this).data("name") == name){return false;}idx++;});firendsCollapse(idx);});/* 统一折叠好友分组的方法 */function firendsCollapse(idx){var $uls = $(".im-ul-box");var $groups = $(".friend-group");var clsName = "group-collapse";var $group = $groups.eq(idx);var $group_ul = $uls.eq(idx).find("ul");$group.toggleClass(clsName);if($group.hasClass(clsName)){$group.children("span").removeClass("iconfont icon-nextpage").addClass("iconfont icon-xla");$uls.eq(idx).css({"display":"block"});$group_ul.slideDown("fast");}else{$group.children("span").removeClass("iconfont icon-xla").addClass("iconfont icon-nextpage");$uls.eq(idx).css({"display":"block"});$group_ul.slideUp("fast");}}</script>
chat/chat-msg-template.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";pageContext.setAttribute("basePath", basePath);%><link rel="stylesheet" type="text/css" href="${basePath}css/bootstrap/bootstrap.css"><link rel="stylesheet" type="text/css" href="${basePath}css/bootstrap/bootstrap-theme.css"><link rel="stylesheet" type="text/css" href="${basePath}css/bootstrap/fileinput.min.css"><link rel="stylesheet" type="text/css" href="${basePath}js/layer.2.4/layui.css"><script type="text/javascript" src='${basePath}js/jquery.min.js'></script><script type="text/javascript" src='${basePath}js/bootstrap/bootstrap.min.js'></script><script type="text/javascript" src='${basePath}js/layer.2.4/layer.js'></script><script type="text/javascript" src='${basePath}js/fy.utils.js'></script><style>body,html {padding: 0;margin: 0;}.im-header {width:100%;height: 65px;background: #F9f9f9;border-bottom:1px solid #eee;}.im-header .im-face-box,.im-info-box {float: left;}.im-header .im-face-box {width: 80px;height: 54px;border-radius: 54px;padding: 5px 5px 5px 20px;}.im-header .im-face-box>img {width: 54px;height: 54px;border-radius: 54px;}.im-header .im-info-box {width:205px;margin-left: 10px;overflow: hidden;}.im-header .im-info-box p {font-size: 12px;line-height: 20px;height: 20px;padding: 2px;margin: 2px;}/* 消息显示框样式 */.im-content {}.im-content #msg-show,#msg-input,#msg-btns {width:100%;}.im-content #msg-show {height:160px;padding:5px;overflow-y: auto;}.im-content #msg-show .msg-item {height:auto;}#msg-show .msg-item .msg-title,.msg-content {min-height:40px;}#msg-show .msg-item .msg-content {padding:5px;margin-bottom:10px;}#msg-show .msg-title .mt-face {width:32px;height:32px;border-radius:32px;margin-right:5px;}#msg-show .msg-title .mt-face,.mt-name {float:left;}#msg-show .msg-title .mt-name {line-height:35px;font-size:14px;}#msg-show .msg-title .mt-name span {padding-left:5px;}/* 消息输入框格式 */.im-content #msg-input {height:60px;position: absolute;bottom:40px;padding:5px;border-top:5px solid #eee;overflow-y: auto;word-wrap: break-word;outline:none;}.im-content #msg-btns {height:40px;position: absolute;bottom:0;padding-right:5px;padding-top:2px;}.im-content #msg-btns button {font-size:12px !important;}</style><div class="im-header"><div class="im-face-box"><img alt="" src="${basePath}images/face.jpg" width="100%"></div><div class="im-info-box"><p id="nickname">zeke</p><p id="signature">PQ 实验田,来搞一个自己的聊天工具</p></div></div><div class="im-content"><div id="msg-show"></div><div id="msg-input" contenteditable="true"> </div><div id="msg-btns" ><button type="button" id="msg-send" class="btn btn-success btn-xs pull-right"><i class="iconfont icon-qtsfkuan"></i> 发 送 </button></div></div><script type="text/javascript">$(function(){/* 打开窗口光标设置在输入框 */$("#msg-input").focus();});</script>
0 0
- socket 内聊工具另一个版本
- 大纲――另一个版本
- openGL另一个版本学习笔记
- 另一个持续集成工具Jenkins
- socket版本协商
- 另一个版本的linux下nfs配置
- c语言文件操作(另一个版本)
- hql(转载)(另一个版本)
- 在限定期限内索取一套专属于您的免费Delphi 10.1 Berlin Starter版本软件开发工具
- Expression Blend 3 - 另一个原型设计工具
- Socket 转发工具
- sokit socket调试工具
- android socket工具类
- socket通讯工具类
- Spring + Websocket 搭建的仿QQ内聊工具
- 企业级发布内测版本
- 实现一个程序在另一个程序内运行
- 框架内一个页面调用另一个页面的方法
- Partical System
- ORACLE游标概念讲解
- Crontab: command not found
- MD5算法原理
- 昨天的问题解决
- socket 内聊工具另一个版本
- html+jsp(表单示例)
- QT5下vs2013中利用tinyXML解析XML文件
- yii2利用mpdf创建pdf文件
- hdu5094
- 配置tomcat虚拟目录映射
- Java中equals()和==的区别
- httpclient 多线程高并发Get请求
- TensorFlow学习笔记(四)——TensorFlow运作方式入门、可视化