webSocket实现在线聊天

需要的jar

<!-- start websocket -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-messaging</artifactId>
            <version>4.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>4.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.3.3</version>
        </dependency>
        <!-- end websocket -->

实现具体类:

1、SpringWebSocketHandlerInterceptor类

 

package com.jero.esc.web.webSocket;

import com.jero.esc.common.utils.StringUtil;
import com.jero.esc.po.userinfo.LogInfo;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import javax.servlet.http.HttpSession;
import java.util.Map;

public class SpringWebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor {

    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
                                   Map<String, Object> attributes) throws Exception {
    	/** 在拦截器内强行修改websocket协议,将部分浏览器不支持的 x-webkit-deflate-frame 扩展修改成 permessage-deflate */
    	if(request.getHeaders().containsKey("Sec-WebSocket-Extensions")){
    		request.getHeaders().set("Sec-WebSocket-Extensions", "permessage-deflate");
    	}
        // TODO Auto-generated method stub
        System.out.println("Before Handshake");
        //获取当前Session
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
            HttpSession session = servletRequest.getServletRequest().getSession(false);
            if (session != null) {
                //使用userName区分WebSocketHandler,以便定向发送消息
                LogInfo currentUser=(LogInfo) session.getAttribute("logInfo");
                System.out.println(currentUser.getLogId());
                String userName = currentUser.getLogName();
                System.out.println(userName);
                String infoId = ((ServletServerHttpRequest) request).getServletRequest().getParameter("infoId");
                String receiveLogId = ((ServletServerHttpRequest) request).getServletRequest().getParameter("receiveLogId");
                String userId=currentUser.getLogId();
                String  toId="";
                if(StringUtil.isNotEmptys(infoId,receiveLogId)){
                    userId=currentUser.getLogId()+infoId;//发送者
                    toId=receiveLogId+infoId;//接收者
                }else{
                    receiveLogId="";
                    infoId="";
                }
                if (userName == null) {
                    userName = "default-system";
                }
                attributes.put("WEBSOCKET_USERNAME", userName);
                attributes.put("userId",userId);
                attributes.put("toId",toId);
                attributes.put("receiveLogId",receiveLogId);
                attributes.put("infoId",infoId);
                attributes.put("loginfoId",currentUser.getLogId());
            }else{

            }
        }
        return super.beforeHandshake(request, response, wsHandler, attributes);

    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
                               Exception ex) {
        // TODO Auto-generated method stub
        super.afterHandshake(request, response, wsHandler, ex);
    }

}
2、SystemWebSocketHandler
 
 
package com.jero.esc.web.webSocket;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.jero.esc.common.utils.StringUtil;
import com.jero.esc.mapper.goodsinfo.ChatRecordMapper;
import com.jero.esc.mapper.userinfo.LogInfoMapper;
import com.jero.esc.po.goodsinfo.ChatRecord;
import com.jero.esc.po.userinfo.LogInfo;
import com.jero.esc.service.goodsinfo.IChatService;
import com.jero.esc.vo.goodsinfo.ChatRecordVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class SystemWebSocketHandler implements WebSocketHandler {
    @Autowired
    private IChatService chatService;
    @Autowired
    private ChatRecordMapper chatRecordMapper;
    @Autowired
    private LogInfoMapper logInfoMapper;
    //当MyWebSocketHandler类被加载时就会创建该Map,随类而生
    public static final Map<String, WebSocketSession> userSocketSessionMap;
    static {
        userSocketSessionMap = new HashMap<String, WebSocketSession>();
    }
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.print("连接成功");
        String username= (String) session.getAttributes().get("WEBSOCKET_USERNAME");
        String userId=(String) session.getAttributes().get("userId");
        String toId=(String) session.getAttributes().get("toId");
        userSocketSessionMap.put(userId,session);
        System.out.println("当前用户数量: " + userSocketSessionMap.size());
        System.out.println("用户名 "+username);
        System.out.println("用户ID "+userId);
        if(StringUtil.isNotEmpty(toId)){
            if(userSocketSessionMap.get(toId)!=null){
                Map<String,Object> map=new HashMap<String, Object>();
                map.put("flag",true);
                sendMessageToUser(userId, new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(map)));
                sendMessageToUser(toId, new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(map)));
            }
        }

    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        String schatMessage = (String) message.getPayload();//用户输入
        System.out.println("用户输入" + schatMessage);
        if(message.getPayloadLength()==0)return;

        //得到Socket通道中的数据并转化为Message对象
        ChatRecord msg=new Gson().fromJson(message.getPayload().toString(),ChatRecord.class);

        Timestamp now = new Timestamp(System.currentTimeMillis());
        msg.setCreateTime(now);
        String toId=msg.getReceiveLogId()+msg.getInfoId();
        List<ChatRecordVo> recordVoList=chatRecordMapper.selectChatList((String) session.getAttributes().get("receiveLogId"));
        //将信息保存至数据库
       Map<String,Object> map=chatService.sendChat((String) session.getAttributes().get("loginfoId"),msg.getInfoId(),msg.getInfoType(),msg.getReceiveLogId(),msg.getContent());
       if(!(boolean)map.get("flag")){//如果保存数据库失败抛异常
           throw new RuntimeException(map.get("msg").toString());
       }else{
           msg.setRecordId((String) map.get("recordId"));
           //发送Socket信息
           //判断对方是否在线
           if(userSocketSessionMap.get(toId)==null){
               //判断对方是否在列表页
               if(userSocketSessionMap.get((String) session.getAttributes().get("receiveLogId"))!=null){
                   Map<String,Object> map1=new HashMap<String, Object>();
                   map1.put("flag",false);
                   for(ChatRecordVo recordVo:recordVoList){
                       if(recordVo.getInfoId().equals(msg.getInfoId())){//判断是否是第一次发送消息
                           map1.put("flag",true);//不是则推送未读消息+1
                           map1.put("infoId",msg.getInfoId());
                           map1.put("dateTimeStr",msg.getCreateTimeStr());
                           break;
                       }
                   }
                   if(!(boolean)map1.get("flag")){//如果是第一次发送消息,推送聊天列表信息
                       //聊天列表信息
                       for(ChatRecordVo recordVo: chatRecordMapper.selectChatList((String) session
                                       .getAttributes().get("receiveLogId"))){
                           if(recordVo.getInfoId().equals(msg.getInfoId())){
                               map1.put("record",recordVo);
                               break;
                           }
                       }
                   }
                   sendMessageToUser((String) session.getAttributes().get("receiveLogId"), new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(map1)));
               }
           }else{
               //在线直接推送消息
               sendMessageToUser(toId, new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
           }
       }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        String toId=(String) session.getAttributes().get("toId");
        if(StringUtil.isNotEmpty(toId)){
            if(userSocketSessionMap.get(toId)!=null){
                Map<String,Object> map=new HashMap<String, Object>();
                map.put("infoId",(String) session.getAttributes().get("infoId"));
                sendMessageToUser(toId, new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(map)));
            }
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        System.out.print("关闭连接");
        String userId=(String) webSocketSession.getAttributes().get("userId");
        System.out.println("WebSocket:"+webSocketSession.getAttributes().get("userId")+"close connection");
        Iterator<Map.Entry<String,WebSocketSession>> iterator = userSocketSessionMap.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<String,WebSocketSession> entry = iterator.next();
            if(entry.getValue().getAttributes().get("userId")==webSocketSession.getAttributes().get("userId")){
                userSocketSessionMap.remove(webSocketSession.getAttributes().get("userId"));
                System.out.println("WebSocket in staticMap:" + webSocketSession.getAttributes().get("userId") + "removed");
                break;
            }
        }
        System.out.println("用户数量: " + userSocketSessionMap.size());
        String toId=(String) webSocketSession.getAttributes().get("toId");
        if(StringUtil.isNotEmpty(toId)){
            if(userSocketSessionMap.get(toId)!=null){
                Map<String,Object> map=new HashMap<String, Object>();
                map.put("flag",false);
                sendMessageToUser(toId, new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(map)));
            }
        }
    }
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
    //发送信息的实现
    public void sendMessageToUser(String uid, TextMessage message)
            throws IOException {
        WebSocketSession session = userSocketSessionMap.get(uid);
        if (session != null && session.isOpen()) {
            session.sendMessage(message);
        }
    }

}
3、WebSocketConfig
 
package com.jero.esc.web.webSocket;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.client.standard.WebSocketContainerFactoryBean;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(systemWebSocketHandler(),"webSocket.do").addInterceptors(new SpringWebSocketHandlerInterceptor());

    }
    @Bean
    public WebSocketHandler systemWebSocketHandler(){
        return new SystemWebSocketHandler();
    }
    @Bean
    public WebSocketContainerFactoryBean createWebSocketContainer() {
        WebSocketContainerFactoryBean container = new WebSocketContainerFactoryBean();
        container.setMaxTextMessageBufferSize(8192);
        container.setMaxBinaryMessageBufferSize(8192);
        return container;
    }

}
前端连接webSocket

 

var isConnect=false;
    var webSocket;	 
    //判断当前浏览器是否支持WebSocket
	if('WebSocket' in window){
		webSocket = new WebSocket("ws://www.jindaoj.com:8083/webSocket.do?infoId=${infoId}&receiveLogId=${receiveLogId}");
		//webSocket = new WebSocket("ws://6xtbd9.natappfree.cc/escq/webSocket.do?infoId=${infoId}&receiveLogId=${receiveLogId}");
		console.log("link success");
	}else{
		alert('Not support websocket');
	}    
    webSocket.onopen = function(event){
        console.log("连接成功");
        isConnect=true;
        console.log(event);
    };
    webSocket.onerror = function(event){
        console.log("连接失败");
        isConnect=false;
        alert("对不起,连接失败,请检查您的网络情况");
    };
    webSocket.onclose = function(event){
        isConnect=false;
        console.log("Socket连接断开");
        alert("您已经断开连接,请重新连接");
        $(".btns2,.btns").click(function(){
            location.reload();
        });

    };
    webSocket.onmessage = function(event){
        //接受来自服务器的消息
        var message = JSON.parse(event.data);
        if(message.msg!=undefined){
            alert(message.msg);
        }else if(message.flag!=undefined){
            if(message.flag){
                $("#status").text("在线");
                $(".ChatHeadImg").css('-webkit-filter',"initial");
            }else{
                $(".ChatHeadImg").css("-webkit-filter","grayscale(100%)");
                $("#status").text("离线");
            }
        }else{
            $.ajax({
                url: path + '/wap/chat/updateReadStatusByAjax.html',
                data: {
                    recordId: message.recordId
                },
                dataType: 'json',
                type: 'post',
                success: function (res) {}
            });
            if(/.(gif|jpg|jpeg|png|gif|jpg|png)$/.test(message.content)){
                $(".chatBox-content-demo").append("<div class='clearfloat'>"+
                    "<div class='author-name'><small class='chat-date'>"+message.createTime+"</small></div>"+
                    "<div class='left'>"+
                    "<div class='chat-avatars'><img src='${receiveUserInfo.userPhoto}' alt='头像'/></div>"+
                    "<div class='chat-message' style='background:#fff'>"+
                    "<img src='"+message.content+"' alt='图片'></div></div></div>");
                //聊天框默认最底部
                $(document).ready(function () {
                    $("<img/>").attr("src",message.content).load(function() {//imgSrc是图片地址
                        var realHeight = this.height;
                        $("#chatBox-content-demo").scrollTop($("#chatBox-content-demo")[0].scrollHeight+realHeight);
                    })
                });
            }else{
                $(".chatBox-content-demo").append("<div class='clearfloat'>"+
                    "<div class='author-name'>"+
                    "<small class='chat-date'>"+message.createTime+"</small></div>"+
                    "<div class='left'>"+
                    "<div class='chat-avatars'><img src='${receiveUserInfo.userPhoto}' alt='头像'/></div>"+
                    "<div class='chat-message'>"+message.content+"</div> </div> </div>");
                //聊天框默认最底部
                $(document).ready(function () {
                    $("#chatBox-content-demo").scrollTop($("#chatBox-content-demo")[0].scrollHeight);
                });
            }

        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值