WebSocket实现前后端消息推送

环境

jdk8 tomcat7 谷歌浏览器和火狐浏览器(浏览器得支持websocket)
本文用webSocket建立一个简单的聊天室,直接上代码。。。
websocket 用到jar包:

<dependency>  
        <groupId>org.springframework</groupId>  
        <artifactId>spring-websocket</artifactId>  
        <version>${spring-framework.version}</version>  
    </dependency>  
    <dependency>  
        <groupId>org.springframework</groupId>  
        <artifactId>spring-messaging</artifactId>  
        <version>${spring-framework.version}</version>  
    </dependency> 
先准备一个普通的maven工程 springMVC框架

后台代码:

主要是建立拦截器拦截webSocket请求并交于handler进行处理。
webSocket配置如下:
1.MySocketConfig:注册拦截器+handler

import org.springframework.beans.factory.annotation.Autowired;
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.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

import com.zzm.test.websocket.socket.WebSocketInterceptor;


@Configuration
@EnableWebMvc
@EnableWebSocket
public class MySocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer{

    @Autowired
    private MySocketHandle mySocketHandle;//自己的handler

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        //注册处理拦截器,拦截url为socketServer的请求
        registry.addHandler(mySocketHandle, "/socketChatroom.do").addInterceptors(new WebSocketInterceptor());//拦截的请求,(注意首先得被servlet拦截到,即要注意web-inf0中的配置)
    }

}

拦截器:拦截请求将httpSession用户保存到WebSocketSession里,用于区别webSocketSession是哪个用户的

import java.util.Map;

import javax.servlet.http.HttpSession;

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.HandshakeInterceptor;

public class MySocketInterceptor implements HandshakeInterceptor{
    /**
     * 握手后报存用户信息到webSocketSession
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request,
            ServerHttpResponse response, WebSocketHandler wsHandler,
            Map<String, Object> attributes) throws Exception {
        if(request instanceof ServerHttpRequest){
              ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
              HttpSession session = servletRequest.getServletRequest().getSession();
              if(session!=null){
                  attributes.put("user", session.getAttribute("user"));
              }
            }
        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest request,
            ServerHttpResponse response, WebSocketHandler wsHandler,
            Exception exception) {

    }

}

handler处理类:定义各连接状态的处理,保存连接上的用户,及自定义发送方法

import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

@Service
public class MySocketHandle implements WebSocketHandler{
    private Logger logger = LoggerFactory.getLogger(MySocketHandle.class);
    private Map<String,WebSocketSession> users = new ConcurrentHashMap<String,WebSocketSession>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session)
            throws Exception {
        logger.info("建立socket连接");
        String userName = session.getAttributes().get("user").toString();
        if(null!=userName&&!"".equals(userName)){
            users.put(userName, session);
            session.sendMessage(new TextMessage("system:"+userName+"连接成功。。。"));
        }
    }

    @Override
    public void handleMessage(WebSocketSession session,
            WebSocketMessage<?> message) throws Exception {

    }

    @Override
    public void handleTransportError(WebSocketSession session,
            Throwable exception) throws Exception {
        if(session.isOpen()){
            session.close();
        }
        logger.error("连接出现错误",exception);
        users.remove(session.getAttributes().get("user").toString());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session,
            CloseStatus closeStatus) throws Exception {
        logger.info("连接关闭");
        users.remove(session.getAttributes().get("user").toString());
    }

    @Override
    public boolean supportsPartialMessages() {

        return false;
    }

    public void sendMessageToUsers(String sender,TextMessage message){
        Set<Map.Entry<String, WebSocketSession>> entrySet = users.entrySet();
        for(Map.Entry<String, WebSocketSession> entry : entrySet){
            String userName = "";
            try{
            userName = entry.getKey();
            if(userName==null||userName.equals(sender)){
                continue;
            }
            WebSocketSession session = entry.getValue();
            session.sendMessage(message);
            }catch(Exception e){
                logger.error("发送信息给"+userName+"失败",e);
            }
        }
    }

    public void sendMessageToUser(String userName,TextMessage message){
        try{
            WebSocketSession session = users.get(userName);
            session.sendMessage(message);
        }catch(Exception e){
            logger.error("发送消息给"+userName+"失败",e);
        }

    }
}

controller类:

import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.socket.TextMessage;

import com.zzm.test.websocket.controller.SocketController;
import com.zzm.test.websocket.service.MySocketHandle;

@Controller
@RequestMapping("socketPushController")
public class SocketPushController {
     private static final Logger logger = LoggerFactory.getLogger(SocketController.class);

      @Autowired
      private MySocketHandle mySocketHandler;

      @RequestMapping("login")
      public String login(HttpSession session,String name){
        logger.info(name+"登录了");

        session.setAttribute("user", name);

        return "../socketPush/chatroom";
      }

      @RequestMapping("sendMessage")
      @ResponseBody
      public String sendMessage(HttpSession session,String message){
          String name = (String) session.getAttribute("user");
          mySocketHandler.sendMessageToUsers( name,new TextMessage(name+" : "+message));
          return "success";
      }
}

前端页面:

登录:用户用姓名登录

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录</title>
<script type="text/javascript">
</script>
</head>
<body>
    <form action="http://localhost:8080/AllStudy/socketPushController/login.do" method="post">
        <span>姓名:</span><input type="text" name="name"><br/>
        <input type="submit" value="登录">
    </form>
</body>
</html>

发送页面:可以发送和接收信息。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="../js/jquery-1.7.2.min.js"></script>
<script type="text/javascript"></script>
<script type="text/javascript">
$(function(){
    //建立socket连接
    var sock;
    if ('WebSocket' in window) {//判断当前浏览器是否支持webSocket
        sock = new WebSocket("ws://localhost:8080/AllStudy/socketChatroom.do");//建立连接
    }
    sock.onopen = function (e) {//成功建立连接
        console.log(e);
    };
    sock.onmessage = function (e) {//接收到消息
        console.log(e)
        $("#messages").append("<p><font color='red'>"+e.data+"</font>")
    };
    sock.onerror = function (e) {//连接发生错误
        console.log(e);
    };
    sock.onclose = function (e) {//连接关闭
        console.log(e);
    };
    监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function(){  
        websocket.close();  
    };

});


function mysend(){
    var message = $("#message").val();
    $("#messages").append("<p><font color='blue'>"+"我:"+message+"</font>");
    $.post('http://localhost:8080/AllStudy/socketPushController/sendMessage.do',{message:message},function(){
        $("message").val("");
    },'text');
}
</script>
</head>
<body>
    <div id="messages">

    </div>
    <div><input type="text" id="message" ><button onclick="mysend()">发送</button></div>
</body>
</html>

结果图:
这里写图片描述

这里写图片描述

这里写图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值