Springboot webSocket(一)

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> Springboot webSocket(一)

在构建Spring boot项目时已经提供webSocket依赖的勾选。webSocket是TCP之上的一个非常薄的轻量级层 ,webSocket主要的应用场景离不开即时通讯与消息推送,但只要应用程序需要在浏览器和服务器之间来回发送消息,就可以使用webSocket来降低客户端流量与服务器的负载。

本文将基于Spring boot实现一个非常简单的HelloWorld程序,用来熟悉项目构建逻辑。

1、导入依赖

主要的webSocket依赖


dependency
    groupIdorg.springframework.boot/groupId
    artifactIdspring-boot-starter-websocket/artifactId
/dependency

一些js库依赖,这里也使用maven方式导入,官网https://www.webjars.org/


        dependency
            groupIdorg.webjars/groupId
            artifactIdwebjars-locator-core/artifactId
        /dependency
        dependency
            groupIdorg.webjars/groupId
            artifactIdsockjs-client/artifactId
            version1.0.2/version
        /dependency
        dependency
            groupIdorg.webjars/groupId
            artifactIdstomp-websocket/artifactId
            version2.3.3/version
        /dependency
        dependency
            groupIdorg.webjars/groupId
            artifactIdbootstrap/artifactId
            version3.3.7/version
        /dependency
        dependency
            groupIdorg.webjars/groupId
            artifactIdjquery/artifactId
            version3.1.0/version
        /dependency

Thymeleaf模板引擎,不用多说了吧


dependency
    groupIdorg.springframework.boot/groupId
    artifactIdspring-boot-starter-thymeleaf/artifactId
/dependency

2、配置开启

接下来开启webSocket并配置一番


@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/gs-guide-websocket").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app"); 
    }

}

这里从上向下说一下,

1)@EnableWebSocketMessageBroker注解用于开启使用STOMP协议来传输基于代理(MessageBroker)的消息,这时候控制器(controller)开始支持@MessageMapping,就像是使用@requestMapping一样。

2)registerStompEndpoints()方法只写了一行代码:


registry.addEndpoint("/gs-guide-websocket").withSockJS();

一是用来注册一个Stomp的节点(endpoint),也就是webSocket的服务端地址,客户端在链接时使用到;

二是withSockJs()方法指定使用SockJS协议。SockJs是一个WebSocket的通信js库,Spring对这个js库进行了后台的自动支持,如果使用它不需要进行过多配置。

3)配置消息代理(MessageBroker),该方法干了两件事,一是启用一个简单的message broker并配置一个或多个前缀来过滤针对代理的目的地(例如以“/topic”为前缀的目的地),该前戳限制了网页客户端设置本地地址时的前戳。 二是设置了一个客户端访问服务端地址的前缀。比如我们设置@MessageMapping(“/hello”),那客户端要发送消息到服务器上的地址是 /app/hello。

3、提供接口


@Controller
public class GreetingController {

    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public Greeting greeting(HelloMessage message) throws Exception {
        System.out.println("收到:" + message.toString() + "消息");
        return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
    }

1)@MessageMapping和@RequestMapping功能类似,用于设置URL映射地址,浏览器向服务器发起请求,需要通过该地址。

需要注意,这里设置路径为/hello,但是客户端需要访问/app/hello,原因前面已经讲述。

2)@SendTo(“/topic/greetings”) 设置目的地,这里的目的地是站在服务端的角度对客户端而言。客户端也需要设置相同的地址,而且必须使用/topic前戳,前面也已经讲述。

本示例中如果服务器接受到了消息,就会对订阅了@SendTo括号中的地址传送消息。

备注:HtmlUtils.htmlEscape()方法会将特殊字符转换为HTML字符引用。

HelloMessage.java


public class HelloMessage {
    private String name;
    ...
}

Greeting.java


public class Greeting {
    private String content;
}

4、客户端

在resources/static目录下:

index.html


!DOCTYPE html
html
head
    titleHello WebSocket/title
    link href="/webjars/bootstrap/css/bootstrap.min.css" rel="stylesheet"
    link href="/main.css" rel="stylesheet"
    link rel="shortcut icon" href="/favicon.ico" /
    script src="/webjars/jquery/jquery.min.js"/script
    script src="/webjars/sockjs-client/sockjs.min.js"/script
    script src="/webjars/stomp-websocket/stomp.min.js"/script
    script src="/app.js"/script
/head
body
noscripth2 style="color: #ff0000"Seems your browser doesn't support Javascript! Websocket relies on Javascript being
    enabled. Please enable
    Javascript and reload this page!/h2/noscript
div id="main-content" class="container"
    div class="row"
        div class="col-md-6"
            form class="form-inline"
                div class="form-group"
                    label for="connect"WebSocket connection:/label
                    button id="connect" class="btn btn-default" type="submit"Connect/button
                    button id="disconnect" class="btn btn-default" type="submit" disabled="disabled"Disconnect
                    /button
                /div
            /form
        /div
        div class="col-md-6"
            form class="form-inline"
                div class="form-group"
                    label for="name"What is your name?/label
                    input type="text" id="name" class="form-control" placeholder="Your name here..."
                /div
                button id="send" class="btn btn-default" type="submit"Send/button
            /form
        /div
    /div
    div class="row"
        div class="col-md-12"
            table id="conversation" class="table table-striped"
                thead
                tr
                    thGreetings/th
                /tr
                /thead
                tbody id="greetings"
                /tbody
            /table
        /div
    /div
/div
/body
/html

main.css


body {
    background-color: #f5f5f5;
}

#main-content {
    max-width: 940px;
    padding: 2em 3em;
    margin: 0 auto 20px;
    background-color: #fff;
    border: 1px solid #e5e5e5;
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    border-radius: 5px;
}

app.js


var stompClient = null;

function setConnected(connected) {
    $("#connect").prop("disabled", connected);
    $("#disconnect").prop("disabled", !connected);
    if (connected) {
        $("#conversation").show();
    }
    else {
        $("#conversation").hide();
    }
    $("#greetings").html("");
}

function connect() {
    var socket = new SockJS('/gs-guide-websocket'); 
    stompClient = Stomp.over(socket);
    stompClient.connect({"id": "header"}, function (frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function (greeting) { 
            showGreeting(JSON.parse(greeting.body).content);
        });
    });
}

function disconnect() {
    if (stompClient !== null) {
        stompClient.disconnect();
    }
    setConnected(false);
    console.log("Disconnected");
}

function sendName() {
    stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()})); 
}

function showGreeting(message) {
    $("#greetings").append("trtd" + message + "/td/tr");
}

$(function () {
    $("form").on('submit', function (e) {
        e.preventDefault();
    });
    $( "#connect" ).click(function() { connect(); });
    $( "#disconnect" ).click(function() { disconnect(); });
    $( "#send" ).click(function() { sendName(); });
});

这部分最值得说的就是JS部分了,比较简单主要就是3个点击事件,包括连接、断开、发送消息。

当我们点击了连接后,会新建SockjS对象,并设置服务端的连接点(/gs-guide-websocket),这里的连接点由服务端提供。

subscribe()方法的第一个参数是注册客户端地址,注意前戳必须是/topic开头,因为在前面服务端已经配置了目的地前戳。与@SendTo中的地址对应。

客户端发送消息只需要调用send()方法,还方法的第一个参数是服务端@MessageMapping地址并且加了指定的/app前戳,第二个参数为header头部信息,第三个是发送的消息内容。

5、运行程序

Springboot webSocket(一)

成功实现Hello World程序。

关注后端技术精选,每天推送优质好文

Springboot webSocket(一)
本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> Springboot webSocket(一)


 上一篇
【加精】Spring全家桶系列–【SpringBoot入门到跑路】 【加精】Spring全家桶系列–【SpringBoot入门到跑路】
//本文作者:cuifuan//本文将收录到菜单栏:《Spring全家桶》专栏中 对于之前的Spring框架的使用,各种配置文件XML、properties一旦出错之后错误难寻,这也是为什么Sprin
下一篇 
SpringBoot快速入门 SpringBoot快速入门
SpringBoot入门 Author:Alan 公众号:阿风的JAVA Spirng boot 入门引导部分 (如果您直接书写案例,您可以跳过此部分) 关于Spring Boot 百度百科是这么介绍的: Spring Boot是由P