springboot中使用websocket

一、什么是WebSocket?

WebSocket是一个应用层协议,他依赖于http协议完成一次握手,建立服务端和和客户端之间的联系,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

二、WebSocket握手请求

Websocket 使用 ws 或 wss 的统一资源标志符,类似于 HTTPS,其中 wss 表示在 TLS 之上的 Websocket
1.1 客户端请求

GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: http://localhost:8080
Sec-WebSocket-Key: sN9csFrP/n5NdDdcy2VJFS==
Sec-WebSocket-Version: 13

1.2 服务端响应

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fFBooB7FAJyBsdsf4hq5s=
Sec-WebSocket-Location: ws://localhost:8080

Connection 必须设置 Upgrade,表示客户端希望连接升级。
Upgrade 字段必须设置 Websocket,表示希望升级到 Websocket 协议。
Sec-WebSocket-Key 是随机的字符串,服务器端会用这些数据来构造出一个 SHA-1 的信息摘要。把 “Sec-WebSocket-Key” 加上一个特殊字符串 “258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,然后计算 SHA-1 摘要,之后进行 BASE-64 编码,将结果做为 “Sec-WebSocket-Accept” 头的值,返回给客户端。如此操作,可以尽量避免普通 HTTP 请求被误认为 Websocket 协议。
Sec-WebSocket-Version 表示支持的 Websocket 版本。RFC6455 要求使用的版本是 13,之前草案的版本均应当弃用。
Origin 字段是可选的,通常用来表示在浏览器中发起此 Websocket 连接所在的页面,类似于 Referer。但是,与 Referer 不同的是,Origin 只包含了协议和主机名称。

三、SpringBoot中使用WebSocket教程(参考springboot-websocket官网)

3.1 创建maven项目,引入依赖

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.0.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>webjars-locator-core</artifactId>
        </dependency>
        <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>bootstrap</artifactId>
            <version>3.3.7</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.0</version>
        </dependency>
    </dependencies>

3.2 配置webscoket服务端

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");//配置目标地址前缀,broker代理,可以看作一个频道,订阅地址前缀
        config.setApplicationDestinationPrefixes("/app");//配置应用的地址前缀
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/gs-guide-websocket")//服务端站点,客户端链接服务端的端点
        .setAllowedOrigins("*")//设置允许的的请求源
                .withSockJS()//设置服务端websocket的类型
        ;
    }
}

3.3 websocket接口的开发
websocket是基于http协议的升级版,和restful接口开发类似

@Controller
public class GreetingController {
	//自定义消息类HelloMessage,Greeting
    @MessageMapping("/hello")//api的地址
    @SendTo("/topic/greetings")//发送到指定的频道
    public Greeting greeting(HelloMessage message) throws Exception {
        Thread.sleep(1000); // simulated delay
        System.out.println(message);
        return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
    }
}

3.4 websocket的客户端
客户端可以是支持socketjs的各种编程语言
3.4.1 java客户端

//创建websocket处理器
public class MyWebSocketHandler extends StompSessionHandlerAdapter {
    public MyWebSocketHandler() {
        super();
    }

    @Override
    public Type getPayloadType(StompHeaders headers) {
        return Greeting.class;//设置订阅频道收到消息的类型
    }

    @Override
    public void handleFrame(StompHeaders headers, Object payload) {//此方法处理收到订阅频道的消息
        Greeting greeting = (Greeting) payload;
        System.out.println("来自服务器得到消息 : " + greeting.getContent());
    }

    @Override
    public void afterConnected(StompSession session, StompHeaders connectedHeaders) {//链接服务端后处理
        super.afterConnected(session, connectedHeaders);
    }

    @Override
    public void handleException(StompSession session, StompCommand command, StompHeaders headers, byte[] payload, Throwable exception) {//处理器异常的处理
        exception.printStackTrace();
    }

    @Override
    public void handleTransportError(StompSession session, Throwable exception) {//通信过程中出现错误的处理,注意上上一个方法是有区别的
        super.handleTransportError(session, exception);
    }
}

//创建java版的websocket客户端
public class MsgWebSocketClient {
    public static void main(String[] args) throws ExecutionException, InterruptedException, JsonProcessingException {

        Transport webSocketTransport = new WebSocketTransport(new StandardWebSocketClient());//websocket client类型
        List<Transport> transports = Collections.singletonList(webSocketTransport);

        SockJsClient sockJsClient = new SockJsClient(transports);//创建socketjs类型的webclient
        sockJsClient.setMessageCodec(new Jackson2SockJsMessageCodec());//设置消息编码和解码类型,这里传递的json格式数据

        WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);//创建stomp websocket 客户端,对标准的websocket 又进一步封装
        stompClient.setMessageConverter(new MappingJackson2MessageConverter());//设置通信消息使用jackson来转换,还有多种消息转换器提供配置
        String url = "ws://127.0.0.1:8080/gs-guide-websocket";//websocket的服务端地址
        TaskScheduler taskScheduler = new ConcurrentTaskScheduler();//设置任务调度方式为并发的方式,不会阻塞
        stompClient.setTaskScheduler(taskScheduler);

        StompSessionHandler stompFrameHandler = new MyWebSocketHandler();//自定义的消息处理器
        ListenableFuture<StompSession> f = stompClient.connect(url, stompFrameHandler, "localhost", 8080);//链接服务器,
		//f.cancel() 取消链接,如果任务已经完成、被取消、不能链接会返回false,取消失败 ,任务未开始或者任务正在执行会取消任务,返回true;
		
        StompSession stompSession = f.get();//客户端和服务端通过StompSession完成通信
        stompSession.setAutoReceipt(true);//设置自动接收消息

        HelloMessage helloMessage = new HelloMessage();//编辑一个消息
        helloMessage.setName("cc");

        System.out.println("Subscribing to greeting topic using session " + stompSession);

        stompSession.send("/app/hello",helloMessage);//调用api发送消息

        stompSession.subscribe("/topic/greetings", stompFrameHandler);//订阅频道接收消息
    }

}

3.4.2 js客户端

function connect() {
    var socket = new SockJS('/gs-guide-websocket');//链接服务端
    stompClient = Stomp.over(socket);//创建socket客户端
    stompClient.connect({}, function (frame) {//frame是链接socket的框架socketJs
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function (greeting) {//订阅频道,将服务端的消息显示到网页
            showGreeting(JSON.parse(greeting.body).content);
        });
    });
}

function sendName() {//同过websocket的api向服务端发送消息
    stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()}));
}

3.5 程序结果
3.5.1html中js客户端发送消息与接收消息:
在这里插入图片描述
3.5.2 java 客户端结果
在这里插入图片描述

一个频道可被多个客户端订阅,使用websocket实现聊天,替换常规前端轮询,以及实时股票等方面又很好的应用

四、资料

1、socketjs:https://github.com/sockjs/sockjs-client
2、spring-websoket:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web.html#websocket-fallback-sockjs-client
3、教程源码:https://github.com/NapWells/java_framework_learn/tree/master/websocketDemo

如有问题,欢迎指正,qq:425154211

猜你喜欢

转载自blog.csdn.net/qq_36027670/article/details/83009586