美文网首页
JAVA 整合websocket

JAVA 整合websocket

作者: 不二不二熊 | 来源:发表于2019-10-28 16:19 被阅读0次

SSM整合websocket

一、maven配置
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>4.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.3.0</version>
        </dependency>
二、ContextXML配置
  1. contextXML添加约束
xmlns:websocket="http://www.springframework.org/schema/websocket"

 xsi:schemaLocation="
                http://www.springframework.org/schema/websocket
                http://www.springframework.org/schema/websocket/spring-websocket-4.0.xsd"
  1. 配置拦截器
<!-- =============== websocket CONFIG BEGIN ================ -->
    <!-- 配置处理器 -->
    <bean id="websocket" class="xxx.MyWebSocketHander" />
    <!-- 配置拦截器 -->
    <websocket:handlers>
        <!-- 跟前端请求的url相关 -->
        <websocket:mapping path="/webSocket" handler="websocket" />
        <websocket:handshake-interceptors>
            <bean class="xxx.HandshakeInterceptor" />
        </websocket:handshake-interceptors>
    </websocket:handlers>
    <!-- =============== websocket CONFIG END ================ -->
三、java配置

拦截器

public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {

    /**
     * 系统日志
     */
    private transient static final Logger logger = LoggerFactory.getLogger(HandshakeInterceptor.class);

    /***
     * 创建握手(handshake)接口/拦截器
     * 这个的主要作用是可以在握手前做一些事,把所需要的东西放入到attributes里面,
     * @param request 请求
     * @param response 响应
     * @param wsHandler 处理函数
     * @param attributes 属性
     * @return boolean 操作结果
     * @exception/throws 无
     */
    @Override
    public boolean beforeHandshake(
            ServerHttpRequest request,
            ServerHttpResponse response,
            WebSocketHandler wsHandler,
            Map<String, Object> attributes
    ) throws Exception {
        /**
         *   获取请求参数,首先我们要获取HttpServletRequest对象才能获取请求参数;
         *   当ServerHttpRequset的层次结构打开后其子类可以获取到我们想要的http对象,那么就简单了。
            我这里是把获取的请求数据绑定到session的map对象中(attributes)
         */
        logger.info(" HandshakeInterceptor: beforeHandshake, attributes is : " + attributes);
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }

    /**
     * 握手后
     * 握手后所做的操作
     * @param request 请求
     * @param response 响应
     * @param wsHandler 操作拦截器
     * @param ex 异常
     * @return void 无
     * @exception/throws 无
     */
    @Override
    public void afterHandshake(
            ServerHttpRequest request,
            ServerHttpResponse response, WebSocketHandler wsHandler,
            Exception ex
    ) {
        logger.info(" HandshakeInterceptor: afterHandshake ");
        super.afterHandshake(request, response, wsHandler, ex);
    }
}

处理器

public class MyWebSocketHander implements WebSocketHandler {

    /**
     * 保存所有的用户session
     */
    private static final ArrayList<WebSocketSession> users = new ArrayList<WebSocketSession>();

    /**
     * 系统日志
     */
    private transient static final Logger logger = LoggerFactory.getLogger(MyWebSocketHander.class);


    /**
     * 连接就绪时
     * 连接就绪时所做操作
     * @param webSocketSession 用户会话
     * @return void 无
     * @exception/throws 无
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        logger.info("connection success ...... ");
        users.add(webSocketSession);
    }


    /**
     * 处理信息
     * 处理信息
     * @param webSocketSession 用户会话
     * @param webSocketMessage 用户消息
     * @return void 无
     * @exception/throws 无
     */
    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
        Gson gson = new Gson();
        Map<String, Object> msg = gson.fromJson(webSocketMessage.getPayload().toString(),
                new TypeToken<Map<String, Object>>() {}.getType());
        // 处理消息 msgContent消息内容
        TextMessage textMessage = new TextMessage(msg.get("msgContent").toString(), true);
        logger.info("页面传递的消息为: "+ msg.get("msgContent").toString());
        // 调用方法(发送消息给所有人)
        sendMsgToAllUsers(textMessage);
    }

    /**
     * 向所有用户发送消息
     * 向所有用户发送消息
     * @param textMessage 消息
     * @return void 无
     * @exception/throws IOException 发送消息异常
     */
    public void sendMsgToAllUsers(TextMessage textMessage) {
        for (WebSocketSession user : users) {
            try {
                synchronized(user){
                    user.sendMessage(textMessage);
                }
            } catch (IOException e) {
                e.printStackTrace();
                logger.error(",",e);
                //异常掉线移除
                users.remove(user);
            }
        }
    }


    /**
     * 处理传输时异常
     * 处理传输时异常
     * @param webSocketSession 用户会话
     * @param throwable 异常
     * @return void 无
     * @exception/throws 无
     */
    @Override
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
        logger.info(" Transport occur error ......");

    }

    /**
     * 关闭连接时
     * 关闭连接时所做操作
     * @param webSocketSession 用户会话
     * @param closeStatus 关闭状态
     * @return void 无
     * @exception/throws 无
     */
    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        logger.info("connection close ......");
        users.remove(webSocketSession);
    }

    /**
     * 重写信息
     * 重写信息
     * @param  无
     * @return boolean 无
     * @exception/throws 无
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}

配置类

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

    /**
     * 系统日志
     */
    private transient static final Logger logger = LoggerFactory.getLogger(MyWebSocketConfig.class);

    /**
     * websocket注册
     * websocket注册
     * @param registry 注册处理器
     * @return void 无
     * @exception/throws 无
     */
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        // 这里的url要与页面的url一致
        // 前台 可以使用websocket环境
        registry.addHandler(myWebSocketHandler(),"/webSocket.do").addInterceptors(new HandshakeInterceptor());
        //至于这里为什么要加info,我遇见的情况是,当我使用sockjs来代替websocket时,连接的后面会自动加上info
        //前台 不可以使用websocket环境,则使用sockjs进行模拟连接
        registry.addHandler(myWebSocketHandler(), "/sockjs/webSocket/info").addInterceptors(new HandshakeInterceptor())
                .withSockJS();
    }


    /***
     * websocket 处理类
     * websocket 处理类
     * @param  无
     * @return org.springframework.web.socket.WebSocketHandler websocket处理器
     * @author 邱仁
     * @exception/throws 无
     */
    @Bean
    public WebSocketHandler myWebSocketHandler(){
        return new MyWebSocketHander();
    }
}
四、前端页面
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
    <meta charset="UTF-8">
    <script src="https://cdn.bootcss.com/sockjs-client/1.4.0/sockjs.min.js"></script>
    <script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
    <title>webSocket-用户66</title>
</head>

<body onbeforeunload="closeWebSocket()">
<div class="page-header" id="tou">
    webSocket测试
</div>
<div class="well" id="msg"></div>
<div class="col-lg">
    <div class="input-group">
        <input type="text" class="form-control" placeholder="发送信息..." id="message">
        <span class="input-group-btn">
                    <button class="btn btn-default" type="button" id="send">发送</button>
                </span>
    </div>
</div>
</body>
    <script type="text/javascript">
        var websocket;
        // 首先判断是否 支持 WebSocket
        if('WebSocket' in window) {
            websocket = new WebSocket("ws://localhost:8080/websocket");
        } else if('MozWebSocket' in window) {
            websocket = new MozWebSocket("ws://localhost:8080/websocket");
        } else {
            websocket = new SockJS("http://localhost:8080/itmb-event/sockjs/webSocket");
        }
        // 打开时
        websocket.onopen = function(evnt) {
            console.log("websocket.onopen  ");
        };
        // 处理消息时
        websocket.onmessage = function(evnt) {
            $("#msg").append("<p>(<font color='red'>" + evnt.data + "</font>)</p>");
            console.log("  websocket.onmessage   ");
        };
        websocket.onerror = function(evnt) {
            console.log("  websocket.onerror  ");
        };
        websocket.onclose = function(evnt) {
            console.log("  websocket.onclose  ");
        };


        //点击了发送消息按钮的响应事件
        $("#send").click(function(){
            alert("ddd")
            // 获取消息内容
            var text = $("#message").val();
            // 判断
            if(text == null || text == ""){
                alert(" content  can not empty!!");
                return false;
            }
            var msg = {
                msgContent: text,
                postsId: 1
            };
            // 发送消息
            websocket.send(JSON.stringify(msg));
        });


        function closeWebSocket() {
            console.log("关闭WebSocket连接!");
            websocket.close();
        }

    </script>
</html>

springboot整合websocket

一、maven配置
          <!-- webSocket -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-websocket</artifactId>
                <version>2.1.8.RELEASE</version>
            </dependency>

二、配置类

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
@Slf4j
@ServerEndpoint(value = "/websocket")
@Component
public class WebSocketServer {
    /**
     * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    private static int onlineCount = 0;
    /**
     * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
     */
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();

    /**
     * 与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    private Session session;

    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        //加入set中
        webSocketSet.add(this);
        //在线数加1
        addOnlineCount();
        log.info("有新连接加入!当前在线人数为" + getOnlineCount());
        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            log.error("webSocket IO异常");
        }
    }
    //  //连接打开时执行
    //  @OnOpen
    //  public void onOpen(@PathParam("user") String user, Session session) {
    //      currentUser = user;
    //      System.out.println("Connected ... " + session.getId());
    //  }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        //从set中删除
        webSocketSet.remove(this);
        //在线数减1
        subOnlineCount();
        log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("来自客户端的消息:" + message);

        //群发消息
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }


    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }


    /**
     * 群发自定义消息
     * */
    public static void sendInfo(String message) throws IOException {
        log.info(message);
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                continue;
            }
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
}
三、后台推送给前端
@Controller
@RequestMapping("/socketSend")
@Slf4j
public class SendMsg {
    @GetMapping("/send/{msg}")
    @ResponseBody
    public void pushVideoListToWeb(@PathVariable(name = "msg") String msg) {
        try {
            WebSocketServer.sendInfo(msg);
        } catch (IOException e) {
        }
    }
}

相关文章

网友评论

      本文标题:JAVA 整合websocket

      本文链接:https://www.haomeiwen.com/subject/wplbvctx.html