SSM+websocket+二进制数据传输+sharedWorker

注意事项:
1.如果出现握手失败,检查路径之外还可以去查看拦截器是否做了什么处理

WebSocket和sharedWork简介

WebSocket是持久化连接,用于解决浏览器与后台服务器双向通讯的问题
sharedWorker共享工作线程允许多个页面共享使用,每个页面都是链接到该共享工作线程的某个端口号上。页面通过该端口与共享工作线程进行通信

配置所需jar包

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-messaging</artifactId>
    <version>${spring.framework.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>${spring.framework.version}</version>
</dependency>

这里所用的版本最好和项目中所用到的spring其他内容统一,避免出现版本不兼容问题。
对版本的要求是:spring版本为 4.0 版本及以上, Tomcat 7.047 以上版本。

websocket入口

/**
 * Component注解告诉SpringMVC该类是一个SpringIOC容器下管理的类
 * 其实@Controller, @Service, @Repository是@Component的细化
 * @Configuration注解该类,等价于XML中配置beans标签
 */
@Configuration
@EnableWebSocket
public class MyWebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        //一般浏览器都会支持
        registry.addHandler(WebSocketPushHandler(),"/webSocketServer").addInterceptors(new MyHandShakeInterceptor());
        //低版本浏览器使用此路径,等下页面上会讲到
        registry.addHandler(WebSocketPushHandler(), "/sockjs/webSocketServer").addInterceptors(new MyHandShakeInterceptor())
                .withSockJS();
    }
    @Bean
    public WebSocketHandler WebSocketPushHandler(){
        return new MyWebSocketHander();
    }
}
  • 实现WebSocketConfigurer接口,重写registerWebSocketHandlers方法,这是一个核心实现方法,配置websocket入口,允许访问的域、注册Handler、SockJs支持和拦截器。

  • registry.addHandler注册和路由的功能,当客户端发起websocket连接,把/path交给对应的handler处理, 而不实现具体的业务逻辑,可以理解为收集和任务分发中心。

  • setAllowedOrigins(String[] domains),允许指定的域名或IP(含端口号)建立长连接,如果只允许自家域名访问,这里轻松设置。 如果不限时使用”*”号,如果指定了域名,则必须要以http或https开头。

拦截器实现

/**
 * websocket握手拦截器
 * 拦截握手前,握手后的两个切面
 */
public class MyHandShakeInterceptor implements HandshakeInterceptor {
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
                                   Map<String, Object> attributes) throws Exception {
        System.out.println("准备进行握手");
        if (request instanceof ServletServerHttpRequest) {
//            attributes.put("username",userName);
        }
        return true;
    }
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
                               Exception exception) {
        System.out.println("握手成功,进入服务端");
    }
}

1.beforeHandshake,在调用handler前处理方法。常用在注册用户信息,绑定WebSocketSession,在handler里根据用户信息获取WebSocketSession发送消息。

Handler处理类

/**WebSocket处理器
 * Created by qiumeng on 2017/8/7 0007.
 */
public class MyWebSocketHander extends TextWebSocketHandler {


    private static final List<WebSocketSession> users = new ArrayList<>();


    //用户进入系统监听
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("成功进入了系统。。。");
        users.add(session);
    }
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        System.out.println("成功接收到消息");
        // 把客户端的消息解析为JSON对象
        if(message instanceof TextMessage) {


            TextMessage msg = new TextMessage("发送的数据"+message.getPayload());
            //给所有浏览器群发消息
            sendMessagesToUsers(msg);
//            this.handleTextMessage(session, (TextMessage)message);
        } else if(message instanceof BinaryMessage) {
            BinaryMessage msg = new BinaryMessage((byte[]) message.getPayload());
            //给所有浏览器群发消息
            sendMessagesToUsers(msg);
//            this.handleBinaryMessage(session, (BinaryMessage)message);
        } else {
            if(!(message instanceof PongMessage)) {
                throw new IllegalStateException("Unexpected WebSocket message type: " + message);
            }
//            this.handlePongMessage(session, (PongMessage)message);
        }


    }


    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {}
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {System.out.println("安全退出了系统");}
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
    /**
     * 给所有的用户发送消息
     */
    public void sendMessagesToUsers(WebSocketMessage<?>  message){
        for(WebSocketSession user : users){
            try {
                //isOpen()在线就发送
                if(user.isOpen()){
                    user.sendMessage(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    //进行实例化bean可以在其他controller实例化 调用所发送的信息
    @Bean
    public MyWebSocketHander myWebSocketHander(){
        return myWebSocketHander();
    }
}

客户端连接

这里只写出javascript代码

<script type="text/javascript">
    var receive_text = document.getElementById("up");
    var myWorker = new SharedWorker('http://localhost:8081/portal/resources/js/worker.js');
    console.log("创建sharedwork");


    myWorker.onerror = function(e)
    {
        console.log('myWorker.onerror : ' + e.message);
    }
    function myOnMessage(e) {
        receive_text.innerHTML += "<br/>" + e.data;
        receive_text.scrollTop = receive_text.scrollHeight;


    }
    if(1){
        // 4 绑定消息处理函数,仅设置 onmessage
        myWorker.port.onmessage = myOnMessage;
    }
    else{
        // 5 另外一种消息绑定方式, addEventListener 和 start 配合使用
        myWorker.port.addEventListener('message', myOnMessage);
        myWorker.port.start();
    }


    function send(){
        var ret = myWorker.port.postMessage(JSON.stringify($("#message").val()))
    }
    //页面发送消息
    function sendMessage() {


//        var ret = myWorker.port.postMessage(stringToBytes($("#message").val()))
        var file=$("#file")[0].files[0];
        var reader = new FileReader();
        if(""==file){
            alert("请选择文件")
        }
//        reader.readAsBinaryString(file)
        reader.readAsArrayBuffer(file)
        reader.onload = function (e) {
            if (e.target.readyState == FileReader.DONE) {
                var data = new Uint8Array(e.target.result);
                //这里有一个问题,目前没有解决 就是传输二进制数据大小的问题 好像为100万字节左右 
                //在大的话,目前没有找到解决办法
                var jsondata=JSON.stringify(data.slice(0, 100))
                var ret = myWorker.port.postMessage(jsondata);
            }
        }


    }
</script>
下面是创建sharedWorker主线程代码work.js
var count = 0;
var ports = [];
var webSocket = new WebSocket("ws://localhost:8081/portal/webSocketServer");
var websocketMessage=null;


// 唯一的事件处理函数
onconnect = function(e) { 
console.log('onconnect from home');
// 1 网页建立连接获取端口
var port = e.ports[0];

ports.push({
port:port,
lastRecv: new Date()
});


// 2 绑定事件处理函数
port.addEventListener('message', function(e) {
var ret = e.data;
        //因为WebSockets只能通过连接发送纯文本数据,所以对于复杂的数据结构,在通过连接发送之前,必须进行序列化
//发送消息到后台
if(""!=ret){
            console.log("向websocket后台发送消息")
webSocket.send(ret);
}
});
// 3 启动端口
port.start();
}


webSocket.onopen = function(event) {
    console.log("websocket创建");
};


webSocket.onmessage = function(event) {
    console.log("websocket返回消息")
    websocketMessage=event.data
    //data的数据格式也是字符串,如果想得到其他格式的数据,必须手工解析这些数据
    for(var i=0;i<ports.length;i++){
        var p=ports[i];
        p.port.postMessage(websocketMessage)
    }
};
webSocket.onerror = function(event) {


};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值