SSM(五) 基于 webSocket 的聊天室(上)

简介: 不知大家在平时的需求中有没有遇到需要实时处理信息的情况,如站内信,订阅,聊天之类的。在这之前我们通常想到的方法一般都是采用轮训的方式每隔一定的时间向服务器发送请求从而获得最新的数据,但这样会浪费掉很多的资源并且也不是实时的,于是随着HTML5的推出带来了websocket可以根本的解决以上问题实现真正的实时传输。

websocket是什么?


至于websocket是什么、有什么用这样的问题一Google一大把,这里我就简要的说些websocket再本次实例中的作用吧。


由于在本次实例中需要实现的是一个聊天室,一个实时的聊天室。如下图:



采用websocket之后可以让前端和和后端像C/S模式一样实时通信,不再需要每次单独发送请求。由于是基于H5的所以对于老的浏览器如IE7、IE8之类的就没办法了,不过H5是大势所趋这点不用担心。


后端


既然推出了websocket,作为现在主流的Java肯定也有相应的支持,所以在JavaEE7之后也对websocket做出了规范,所以本次的代码理论上是要运行在Java1.7+和Tomcat7.0+之上的。


看过我前面几篇文章的朋友应该都知道本次实例也是运行在之前的SSM之上的,所以这里就不再赘述了。


首先第一步需要加入websocket的依赖:


< dependency>
    < groupid>javax.websocket< /groupid>
    < artifactid>javax.websocket-api< /artifactid>
    < version>1.1< /version>
< /dependency>
< dependency>
    < groupid>org.springframework< /groupid>
    < artifactid>spring-websocket
    < version>${spring.version}< /version>
< /dependency>


以上就是使用websocket所需要用到的包。spring-websocket这个主要是在之后需要在websocket的后端注入service所需要的。


之后再看一下后端的核心代码MyWebSocket.java


package com.crossoverJie.controller;
/**
 * Created by Administrator on 2016/8/7.
 */
import com.crossoverJie.pojo.Content;
import com.crossoverJie.service.ContentService;
import org.apache.camel.BeanInject;
import org.apache.camel.EndpointInject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import org.springframework.web.socket.server.standard.SpringConfigurator;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.annotation.PostConstruct;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
//该注解用来指定一个URI,客户端可以通过这个URI来连接到WebSocket。
/**
  类似Servlet的注解mapping。无需在web.xml中配置。
 * configurator = SpringConfigurator.class是为了使该类可以通过Spring注入。
 */
@ServerEndpoint(value = "/websocket",configurator = SpringConfigurator.class)
public class MyWebSocket {
    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    public MyWebSocket() {
    }
    @Autowired
    private ContentService contentService ;
    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    // 若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
    private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet();
    //与客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    /**
     * 连接建立成功调用的方法
     * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(Session session){
        this.session = session;
        webSocketSet.add(this);     //加入set中
        addOnlineCount();           //在线数加1
        System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
    }
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(){
        webSocketSet.remove(this);  //从set中删除
        subOnlineCount();           //在线数减1
        System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
    }
    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("来自客户端的消息:" + message);
        //群发消息
        for(MyWebSocket item: webSocketSet){
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
                continue;
            }
        }
    }
    /**
     * 发生错误时调用
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error){
        System.out.println("发生错误");
        error.printStackTrace();
    }
    /**
     * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException{
        //保存数据到数据库
        Content content = new Content() ;
        content.setContent(message);
        SimpleDateFormat sm = new SimpleDateFormat("yyyy-MM-dd HH:mm:dd") ;
        content.setCreateDate(sm.format(new Date()));
        contentService.insertSelective(content) ;
        this.session.getBasicRemote().sendText(message);
        //this.session.getAsyncRemote().sendText(message);
    }
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }
    public static synchronized void addOnlineCount() {
        MyWebSocket.onlineCount++;
    }
    public static synchronized void subOnlineCount() {
        MyWebSocket.onlineCount--;
    }
}


这就是整个websocket的后端代码。看起来也比较简单主要就是使用那几个注解。每当有一个客户端连入、关闭、发送消息都会调用各自注解的方法。这里我讲一下sendMessage()这个方法。



相关文章
|
5月前
|
JavaScript 网络协议 前端开发
【Nodejs】WebSocket 全面解析+实战演练——(Nodejs实现简易聊天室)
【Nodejs】WebSocket 全面解析+实战演练——(Nodejs实现简易聊天室)
576 0
|
4月前
|
存储 前端开发 Go
golang怎么搭建Websocket聊天室服务端
连接的添加和移除 添加连接: 当一个新的WebSocket连接建立时,服务器需要将这个连接添加到全局的连接列表中。多个连接可能同时建立,从而导致多个并发操作试图修改连接列表。 移除连接: 当一个WebSocket连接断开时,服务器需要将这个连接从全局的连接列表中移除。如果多个连接同时断开,可能会导致并发修改连接列表。
|
5月前
|
移动开发 安全 前端开发
技术心得记录:基于webSocket的聊天室
技术心得记录:基于webSocket的聊天室
|
6月前
|
存储 JavaScript Java
基于 WebSocket 打造聊天室
基于 WebSocket 打造聊天室
|
6月前
|
前端开发 JavaScript Java
【十五】springboot整合WebSocket实现聊天室
【十五】springboot整合WebSocket实现聊天室
123 0
|
Web App开发 存储 缓存
HTTP,WebSocket 和 聊天室
HTTP,WebSocket 和 聊天室
216 0
|
JSON 前端开发 安全
【Java Web项目】基于WebSocket的Web聊天室
本项目的名称为Web聊天室,即类QQ群组聊天,多个用户可以在同一个群组收发消息进行聊天
【Java Web项目】基于WebSocket的Web聊天室
|
移动开发 前端开发 网络协议
WebSocket网页聊天室
WebSocket网页聊天室
173 0
|
JavaScript 前端开发 Java
SpringBoot+Vue搭建一个WebSocket的实时聊天室
SpringBoot+Vue搭建一个WebSocket的实时聊天室
235 0
|
存储
Netty入门到超神系列-基于WebSocket开发聊天室
在很多的网站中都嵌入有聊天功能,最理想的方式就是使用WebSocket来开发,屏幕面前的你如果不清楚WebSocket的作用可以自己去百度一下,Netty提供了WebSocket支持,这篇文章将使用Netty作为服务器,使用WebSocket开发一个简易的聊天室系统。
255 0