Java中Spring WebSocket详解

Java中Spring WebSocket详解

WebSockets是一种全双工、持久性的协议,能够在浏览器和服务器之间创建一个互动会话。Spring WebSocket简化了在Spring应用程序中使用WebSockets的流程。

使用Spring WebSocket

以下是使用Spring WebSocket的步骤:

  1. pom.xml文件中添加spring-boot-starter-websocket依赖。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
  1. 创建WebSocket配置类,并注入消息代理和“/endpoint”端点。
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

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

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/endpoint").withSockJS();
    }
}
  1. 创建WebSocket处理程序类,并实现WebSocketHandler接口。
@Component
public class WebSocketHandlerImpl implements WebSocketHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketHandlerImpl.class);
    private List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        LOGGER.info("New session connected {}", session.getId());
        sessions.add(session);
    }

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        LOGGER.info("Message received {}", message.getPayload());
        sendMessageToAll(message.getPayload());
    }

    private void sendMessageToAll(String message) throws IOException {
        for (WebSocketSession session : sessions) {
            session.sendMessage(new TextMessage(message));
        }
    }
}
  1. 创建控制器类,并使用@MessageMapping注解处理消息。
@Controller
public class WebSocketController {

    private final WebSocketHandlerImpl webSocketHandler;

    @Autowired
    public WebSocketController(WebSocketHandlerImpl webSocketHandler) {
        this.webSocketHandler = webSocketHandler;
    }

    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public Greeting greeting(HelloMessage message) throws InterruptedException {
        Thread.sleep(1000); // simulated delay
        return new Greeting("Hello, " + message.getName() + "!");
    }
}
  1. 在客户端JavaScript中创建WebSocket连接,并使用stompClient对象发送和接收消息。
var stompClient = null;

function connect() {
    var socket = new SockJS('/endpoint');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function (frame) {
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function (greeting) {
            showGreeting(JSON.parse(greeting.body).content);
        });
    });
}

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

接下来,详细介绍这个过程中的两个示例:

示例一:简单的Spring WebSocket应用程序

该示例演示了如何在Spring WebSocket应用程序中创建基本的WebSocket连接,并在服务器和客户端之间传输消息。

  1. 创建一个名为Greeting的Java类,表示要发送到客户端的消息。
public class Greeting {

    private String content;

    public Greeting(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }
}
  1. 创建一个名为HelloMessage的Java类,表示从客户端发送到服务器的消息。
public class HelloMessage {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  1. 创建一个名为WebSocketController的Spring控制器类,使用@MessageMapping注解处理消息,并使用@SendTo注解返回响应消息。
@Controller
public class WebSocketController {

    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public Greeting greeting(HelloMessage message) throws InterruptedException {
        Thread.sleep(1000); // simulated delay
        return new Greeting("Hello, " + message.getName() + "!");
    }
}
  1. 创建index.html文件,并在其中向服务器发送消息并显示响应消息。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello WebSocket</title>
</head>
<body>
    <form onsubmit="sendName(); return false;">
        <input type="text" id="name" placeholder="Your name here..."/>
        <button>Send</button>
    </form>
    <div id="greetings"></div>
    <script src="/webjars/sockjs-client/1.0.2/sockjs.min.js"></script>
    <script src="/webjars/stomp-websocket/2.3.3/stomp.min.js"></script>
    <script src="/js/app.js"></script>
</body>
</html>
  1. 创建app.js文件,创建WebSocket连接并发送和接收消息。
var stompClient = null;

function connect() {
    var socket = new SockJS('/endpoint');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function (frame) {
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function (greeting) {
            showGreeting(JSON.parse(greeting.body).content);
        });
    });
}

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

function showGreeting(message) {
    $('#greetings').append("<div>" + message + "</div>");
}

$(function () {
    $('form').on('submit', function (e) {
        e.preventDefault();
    });
    connect();
});
  1. 启动应用程序,并访问http://localhost:8080,向服务器发送消息并显示响应消息。

示例二:使用Spring Security的Spring WebSocket应用程序

该示例演示了如何在Spring WebSocket应用程序中使用Spring Security启用安全WebSocket连接。

  1. 添加spring-boot-starter-security依赖到pom.xml文件中。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. WebSocketConfig配置类中,配置WebSocket拦截器以启用Spring Security。
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Autowired
    private CustomHandshakeHandler customHandshakeHandler;

    @Autowired
    private CustomWebSocketInterceptor customWebSocketInterceptor;

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/chat").setHandshakeHandler(customHandshakeHandler)
                .addInterceptors(customWebSocketInterceptor).withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/queue/", "/topic/");
        config.setApplicationDestinationPrefixes("/app");
    }
}
  1. 创建CustomHandshakeHandler类,继承DefaultHandshakeHandler类,以向用户签发令牌。
@Component
public class CustomHandshakeHandler extends DefaultHandshakeHandler {

    @Autowired
    private TokenUtils tokenUtils;

    @Override
    protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler,
            Map<String, Object> attributes) {
        String token = extractToken(request.getURI().toString());
        return tokenUtils.getTokenOwner(token)::getId;
    }

    private String extractToken(String uri) {
        // parse token from URI
    }
}
  1. 创建CustomWebSocketInterceptor类,实现HandshakeInterceptor接口,检查WebSocket握手请求是否有令牌。
@Component
public class CustomWebSocketInterceptor implements HandshakeInterceptor {

    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Map<String, Object> attributes) throws Exception {
        String uri = request.getURI().toString();
        String token = extractToken(uri);
        if (StringUtils.isEmpty(token)) {
            return false;
        }
        if (tokenIsValid(token)) {
            return true;
        }
        return false;
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Exception exception) {
    }

    private String extractToken(String uri) {
        // parse token from URI
    }

    private boolean tokenIsValid(String token) {
        // validate token
    }
}
  1. 创建TokenUtils类,用于管理令牌。
@Component
public class TokenUtils {

    public TokenUtils() {
        // initialize token management
    }

    public User getTokenOwner(String token) {
        // retrieve user from token
    }
}
  1. 创建WebSocketController类,使用@MessageMapping注解处理消息。
@Controller
public class WebSocketController {

    @MessageMapping("/chat/{roomId}/message")
    @SendTo("/topic/{roomId}")
    public Message sendPrivateMessage(@DestinationVariable String roomId, Message message) throws Exception {
        return message;
    }
}
  1. 创建Message类,表示聊天消息。
public class Message {

    private User from;
    private String text;

    public User getFrom() {
        return from;
    }

    public void setFrom(User from) {
        this.from = from;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}
  1. 创建User类,表示WebSocket用户。
public class User {

    private Long id;
    private String name;

    public User() {
    }

    public User(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  1. 创建index.html文件,并在其中连接WebSocket并使用聊天。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>WebSocket Chat</title>
</head>
<body>
    <script src="/webjars/sockjs-client/1.0.2/sockjs.min.js"></script>
    <script src="/webjars/stomp-websocket/2.3.3/stomp.min.js"></script>
    <form onsubmit="return false;">
        <input type="text" id="message" placeholder="Message..." />
        <input type="button" value="Send" onclick="sendMessage();" />
    </form>
    <div id="chat"></div>
    <script th:inline="javascript">
        var stompClient = null;

        function connect() {
            var socket = new SockJS('/chat');
            stompClient = Stomp.over(socket);
            var token = getTokenFromCookie(); // get user token from cookie
            stompClient.connect({ 'Authorization': 'Bearer ' + token }, function (frame) {
                console.log('Connected: ' + frame);
                stompClient.subscribe('/topic/chat', function (message) {
                    showMessage(JSON.parse(message.body));
                });
            });
        }

        function sendMessage() {
            var message = $('#message').val();
            stompClient.send('/app/chat/message', {}, JSON.stringify({ 'text': message }));
        }

        function showMessage(message) {
            $('#chat').append('<div>' + message.from.name + ': ' + message.text + '</div>');
        }

        function getTokenFromCookie() {
            // parse token from cookie
        }

        $(function () {
            connect();
        });
    </script>
</body>
</html>
  1. 启动应用程序,并访问http://localhost:8080,连接WebSocket并开始聊天。

以上就是在Java中使用Spring WebSocket的完整攻略,以及两个示例的详细说明。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中Spring WebSocket详解 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • jQuery UI Datepicker firstDay选项

    以下是关于 jQuery UI 的 Datepicker firstDay 选项的完整攻略: jQuery UI 的 Datepicker firstDay 选项 在 jQuery UI 中,可以使用 datepicker 方法创建一个日期选择器。firstDay 选项可以指定一周的第一天是哪一天。 语法 $(selector).datepicker({ f…

    jquery 2023年5月11日
    00
  • 为开发者准备的10款最好的jQuery日历插件

    当今,jQuery作为一种广泛使用的JavaScript框架之一,被许多开发者选择来支持他们的Web开发。为了帮助开发人员轻松地为他们的项目添加高质量的日历,下面介绍了10个最好的jQuery日历插件。 1. FullCalendar 简介 FullCalendar是一个开源的jQuery日历插件,它包括了事件、拖放、资源视图和样式定制等特性,其中的某些特性…

    jquery 2023年5月28日
    00
  • jQWidgets jqxBarGauge min属性

    jQWidgets jqxBarGauge min属性 jQWidgets是一个基于jQuery的UI组件库,提供了丰富的UI件和工具,包括表格、图表单、历、菜单等。jqBarGauge是jQWidgets中的一个组件可以用于水平或垂直的条形图。jqBarGauge提供了min属性,用于设置条形图的最小值。 min属性的基本语法 min属性用于设置条形图的最…

    jquery 2023年5月9日
    00
  • 百度前台js笔试题与答案

    百度前台JS笔试题攻略 0. 背景介绍 该题是百度前端技术学院(IFE)啊2017年的提前批笔试题,主要考察前端JavaScript编程能力。该题面分为多个部分,主要要求在限制条件下,用JavaScript实现代码功能。 1. 题目分析 1.1 题目描述 该题面共分为5个部分,包括字符串、数组、对象、ES6、正则表达式等内容。 1.2 题目要求 针对每个部分…

    jquery 2023年5月28日
    00
  • jquery图形密码实现方法

    jQuery 图形密码实现方法 什么是图形密码 图形密码指的是利用图形(如点、线等)作为密码的验证方式。 实现方法 前提条件 在实现图形密码前,需引用jQuery库。 步骤 准备必要的HTML结构和CSS样式,其中包含了一个固定大小的容器<div>,若干个不同的元素作为密码节点,以及相关样式。 “`html “` 在JS中,通过jQuery选…

    jquery 2023年5月28日
    00
  • 手把手教你制作织梦自定义公告模板

    手把手教你制作织梦自定义公告模板 1. 准备工作 在制作自定义公告模板之前,你需要准备以下工作: 熟悉织梦后台模板制作基础知识,了解模板的基本结构和语法; 打开织梦CMS后台,进入“模板管理”,选择一个已有的模板,复制到本地备份(便于回滚操作)。 2. 新建公告模板 在模板管理中新建公告模板,具体步骤如下: 在“模板管理”页面,点击“新建模板”,选择“单页模…

    jquery 2023年5月27日
    00
  • jQuery日期范围选择器附源码下载

    以下是关于”jQuery日期范围选择器附源码下载”的完整攻略: 什么是jQuery日期范围选择器? jQuery日期范围选择器是一个可以让用户方便地选择日期范围的插件。它可以和jQuery结合使用,支持pc端和移动端,提供多种样式和主题,并且支持多语言。用户可以通过单击日历或手动输入日期来选择起始日期和结束日期,同时也可以通过插件提供的API来进行更加丰富的…

    jquery 2023年5月28日
    00
  • jQWidgets jqxGrid enableanimations属性

    以下是关于“jQWidgets jqxGrid enableanimations属性”的完整攻略,包含两个示例说明: 简介 jqxGrid 控件的 enableanimations 属性用于设置表格的动画效果。 完整攻略 以下是 jqxGrid 控件 enableanimations 属性的完整攻略: 定义 enableanimations 在 jqxGri…

    jquery 2023年5月11日
    00
合作推广
合作推广
分享本页
返回顶部