WebSocket之原生使用、Spring使用(无理论)

github-demo(idea):https://github.com/bbwangbb/csnd-WebSocket-demo

1.原生使用(Maven)

1)导入jar包,javax.websocket-api,如果使用jar导入tomcat/lib下的tomcat-websocket.jar和websocket-api.jar

 

<dependency>
    <groupId>javax.websocket</groupId>
    <artifactId>javax.websocket-api</artifactId>
    <version>1.1</version>
    <scope>provided</scope>
</dependency>

2)配置类

package cn.mb.websocket;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.CopyOnWriteArraySet;

//该注解用来指定连接的 url,类似请求的url -> ws://主机:端口/websocket 即为连接地址
@ServerEndpoint("/websocket")
public class WebsocketConfig {
    //可以通过此来记录在线人数
    public static int onlineCount = 0;

    //可以用通过静态集合的方式存储session对象,在别处可以直接调用来逐个发送消息
    public static CopyOnWriteArraySet<Session> sessions = new CopyOnWriteArraySet<>();

    public WebsocketConfig() {
        System.out.println("init...");
    }

    @OnOpen//连接打开时调用
    public void open(Session session) {
        sessions.add(session);
        System.out.println("open...");
    }

    @OnClose//连接关闭时调用
    public void close(Session session) {
        sessions.remove(session);
        System.out.println("close...");
    }

    @OnMessage//客户端发送消息时调用
    public void send(String message, Session session) {
        System.out.println("客户端信息:" + message);
        System.out.println("send...");
        //给用户发送信息
    }

    @OnError//发生错误时调用
    public void error(Session session, Throwable error) {
        System.out.println("error...");
    }

}

3)前端页面

<!DOCTYPE html>
<html>
<head>
    <title>My WebSocket</title>
    <script src="jquery-2.1.0.js"></script>
</head>
<body>
<button id="open">Open</button>
<br/>
<input type="text" id="text">
<button id="send">Send</button>
<br/>
<button id="close">Close</button>
<div id="message">
</div>
</body>

<script type="text/javascript">
    $(function () {
        var websocket = null;

        //开起连接
        $("#open").click(function () {
            //判断当前浏览器是否支持WebSocket
            if ('WebSocket' in window) {
                websocket = new WebSocket("ws://localhost:8080/websocket");
            } else {
                alert('Not support websocket')
            }

            //连接发生错误的回调方法
            websocket.onerror = function (event) {
                $("#message").html("Connect error!")
            };

            //连接成功建立的回调方法
            websocket.onopen = function (event) {
                $("#message").html("Connect successfully!");
            }

            //接收到消息的回调方法
            websocket.onmessage = function (event) {
                $("#message").html("服务端消息:" + event.data);
            }
        })

        //关闭连接
        $("#close").click(function () {
            websocket.close();
            $("#message").html("Connect closing!")
        })

        //发送消息
        $("#send").click(function () {
            var message = $("#text").val();
            websocket.send(message);
            $("#message").html("Send successfully!");
        })
    })
</script>
</html>

 

2.Spring使用

1)导入jar

        <!--Spring Boot 的websocket方式-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

        <!--Spring集成-->
<!--        <dependency>-->
<!--            <groupId>org.springframework</groupId>-->
<!--            <artifactId>spring-messaging</artifactId>-->
<!--            <version>5.0.9.RELEASE</version>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>org.springframework</groupId>-->
<!--            <artifactId>spring-websocket</artifactId>-->
<!--            <version>5.0.9.RELEASE</version>-->
<!--        </dependency>-->

        <!--客户端使用的是sockjs方式,相当于导入前端需要使用的js文件-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>sockjs-client</artifactId>
            <version>1.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>stomp-websocket</artifactId>
            <version>2.3.3</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.1.0</version>
        </dependency>

2)配置类

package cn.mb.websocket;

import cn.mb.interceptor.HttpHandShakeInterceptor;
import cn.mb.listener.STOMPConnectEventListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker//启用websocket注解
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override//配置消息代理
    public void configureMessageBroker(MessageBrokerRegistry config) {
        /**
         * 与 @MessageMapping 中的url拼接后就是 客户端可以发送数据的 url
         *      @MessageMapping("/testWebSocket")
         *      客户端即可向 /app/testWebSocket 发送数据
         */
        config.setApplicationDestinationPrefixes("/app");
        //前端可以订阅 /topic/... 的url
        config.enableSimpleBroker("/topic");
    }

    @Override//注册 Stomp 端点
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //添加一个/spring-websocket端点,客户端就可以通过这个端点来进行连接;
        registry.addEndpoint("/spring-websocket")
                .addInterceptors(new HttpHandShakeInterceptor())//设置握手拦截器
                .setAllowedOrigins("*") // 添加允许跨域访问
                .withSockJS();//添加SockJS支持
    }

    @Bean//注入监听器
    public STOMPConnectEventListener STOMPConnectEventListener(){
        return new STOMPConnectEventListener();
    }

}

3)监听器(可选)

package cn.mb.listener;

import org.springframework.context.ApplicationListener;
import org.springframework.web.socket.messaging.SessionConnectEvent;

public class STOMPConnectEventListener implements ApplicationListener<SessionConnectEvent> {


    @Override
    public void onApplicationEvent(SessionConnectEvent sessionConnectEvent) {

        //打开链接时会触发此方法

    }


}

4)拦截器(可选)

package cn.mb.interceptor;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import java.util.Map;

//声明后需要在配置类中配置
public class HttpHandShakeInterceptor implements HandshakeInterceptor {

    @Override
    public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
        System.out.println("beforeHandshake...");
        return true;//返回false会疯狂请求握手
    }

    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
        System.out.println("afterHandshake...");
    }
}

5)控制层

package cn.mb.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;

@Controller
public class WebSocketController {

    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

    @MessageMapping("/testWebSocket")
    @SendTo("/topic/destination")
    public String testWebSocket(String message) throws Exception {
        /**
         * 单播(私聊):
         *      1.两人订阅相同的 url
         *      2.这样发信息的时候可以互相看到,数据库中可以在存储好友的信息的时候带上一个url(个人想法)
         */
        simpMessagingTemplate.convertAndSend("/topic/bb", "我是bb,你在吗?");
        System.out.println("客户端说:" + message);
        return "Hi, client!";
    }
}

6)前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="webjars/jquery/3.1.0/jquery.min.js"></script>
    <script src="webjars/sockjs-client/1.0.2/sockjs.min.js"></script>
    <script src="webjars/stomp-websocket/2.3.3/stomp.min.js"></script>
</head>
<body>
<button id="open">Open</button>
<br/>
<button id="send">Send</button>
<br/>
<button id="close">Close</button>
<div id="message">
</div>
<script>
    $(function () {
        var socket = null;
        var stompClient = null;
        //开起连接
        $("#open").click(function () {
            //创建 websocket对象
            socket = new SockJS('/spring-websocket');//固定
            stompClient = Stomp.over(socket);

            //连接成功的回调函数
            stompClient.connect({username : 'bb'}, function (frame) {
                //...
                //打印连接状态
                console.log('Connected: ' + frame);
                $("#message").html("连接成功!")
                /*
                    3.连接成功后订阅目标地址
                        client.subscribe(destination, callback)
                            destination:目标地址
                            callback:有人向这个地址发送广播该回调函数就会执行
                 */
                stompClient.subscribe('/topic/bb', function (resp) {//DB读取
                    $("#message").html("服务端回复:" + resp.body)
                });
                //可以订阅多个,每个写一次方法即可
                // stompClient.subscribe('/topic/cc', function (resp) {//DB读取
                //     $("#message").html("服务端回复:" + resp.body)
                // });
            });
        })

        //关闭连接
        $("#close").click(function () {
            if (stompClient !== null) {
                stompClient.disconnect();
                $("#message").html("连接关闭!")
            }
        })

        //发送消息
        $("#send").click(function () {
            /*
                client.send(destination, {}, body);
                destination:目标地址
                {}:请求头
                body:请求信息(JSON格式)
             */
            stompClient.send("/app/testWebSocket", {}, JSON.stringify({message : 'Hi, server!'}));
        })

    })
</script>
</body>
</html>

注意:在Struts中使用要放行该url,在struts.xml中配置以下内容

<constant name="struts.action.excludePattern" value="/你的url"></constant>

个人理解:

       1.连接WebSocket服务端

       2.连接成功后,客户端与服务端之间可以相互发送信息

       3.至于怎么做单播,原生可以使用存储Session方式,Spring中可以使用SimpMessagingTemplate对象发送(订阅同一个url)

 

理论后期弥补。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值