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
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 离职前请假不批怎么办 酷派x7无限重启怎么办 钢铁雄心3资源多怎么办 汽车智能钥匙没电了怎么办 辐射3食物有辐射怎么办 辐射3玩起来很卡怎么办 辐射3多余的瓶盖怎么办 辐射4开锁太快怎么办 极度恐慌3没子弹怎么办 辐射3道德值低怎么办 辐射3任务做完了怎么办 极限竞速6闪退怎么办 两个睾丸都碎了怎么办 快递退回去了钱怎么办 想登录老公微信怎么办 养狗家里味道大怎么办 实在不想养狗了怎么办 培训完不想干了怎么办 干了几天想离职怎么办 药流开始流血了怎么办 药流期间同房了怎么办 想学韩语可是没基础怎么办 鞋子多买了一双怎么办 胳膊抻着了怎么办妙招 胳膊抻筋了 很疼怎么办 干活胳膊抻筋了怎么办 胳膊上的筋扭了怎么办 一岁宝宝脖子歪怎么办 3岁宝宝轻微斜颈怎么办 2岁宝宝轻微斜颈怎么办 肩膀劳损痛的厉害怎么办 颈后面有个囊肿怎么办 扭腰了怎么办有偏方吗 跑步机点加油了怎么办 高二了英语30分怎么办 苍蝇往人身上飞怎么办 25岁了写字好丑怎么办 我字写得超难看怎么办 高三体检有纹身怎么办 快高考了有纹身怎么办 艺考身上有纹身怎么办