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日

相关文章

  • jQWidgets jqxNavBar orientation属性

    以下是关于 jQWidgets jqxNavBar 组件中 orientation 属性的详细攻略。 jQWidgets jqxNavBar orientation 属性 jQWidgets jqxNavBar 组件的 orientation 属性用于设置导航栏的方向。该属性可以是字符串,可选值为 ‘horizontal’ 或 ‘vertical’。 语法 …

    jquery 2023年5月12日
    00
  • jQuery UI slider start事件

    jQuery UI Slider start事件详解 jQuery UI的Slider是一个滑块插件,它允许用户通过拖动滑块来选择值。在本文中,我们将详细介绍Slider start事件的用法和示例。 start事件 start是Slider件中的事件,它在滑块开始移动时触发。可以使用该事件在块开始移动时执行一些操作。 语法 以下是 start事件的语法: …

    jquery 2023年5月11日
    00
  • 如何使用jQuery加载更多的功能

    使用jQuery可以轻松地为网站添加更多的功能。以下是详细的攻略,演示如何使用jQuery加载更多的功能: 步骤1:引入jQuery库 在使用jQuery之前,需要先在HTML文档中引入jQuery库。可以通过以下方式引入: <script src="https://code.jquery.com/jquery-3.6.0.min.js&qu…

    jquery 2023年5月9日
    00
  • jQuery UI Sortable enable() 方法

    jQuery UI Sortable enable() 方法详解 jQuery UI Sortable是一个排序插件,它允许用户通过拖动元素来重新排序。在本文中,我们将详细介绍Sortable enable() 方法的用法示例。 enable() 方法 enable() 方法是Sortable插件的一个方法,它用于启用或禁用Sortable列表。当列表被禁用…

    jquery 2023年5月11日
    00
  • jQWidgets jqxComboBox enableHover属性

    以下是关于“jQWidgets jqxComboBox enableHover属性”的完整攻略,包含两个示例说明: 简介 jqxComboBox 控件的 enableHover 属性用于启用或禁用鼠标悬停效果。 完整攻略 以下是 jqxComboBox 控件 enableHover 属性的完整攻略: 定义 enableHover 属性 在 jqxComboB…

    jquery 2023年5月11日
    00
  • jQuery中最快/最慢的选择器是什么

    在jQuery中,选择器的性能是非常重要的,因为它们可以直接影响网页的加载速度和响应时间。以下是jQuery中最快和最慢的选择器以及如何使用它的完整攻略: 最快的选择器:ID选择器 ID选择器是jQuery中最快的选择器之一,因为它使用了浏览器原生的getElementById()方法。以下是一个示例: // Select an element by ID …

    jquery 2023年5月9日
    00
  • jQWidgets jqxDateTimeInput allowKeyboardDelete属性

    以下是关于“jQWidgets jqxDateTimeInput allowKeyboardDelete属性”的完整攻略,包含两个示例说明: 简介 jqxDateTimeInput 控件的 allowKeyboardDelete 属性用于设置是否允许使用键盘删除键删除日期时间输入框中的内容。 完整攻略 以下是 jqxDateTimeInput 控件 allo…

    jquery 2023年5月11日
    00
  • jQuery实现可兼容IE6的滚动监听功能

    为了实现可兼容IE6的滚动监听功能,我们需要使用jQuery。以下是实现此功能的步骤: 第一步:引入jQuery 首先,我们需要在HTML文件中引入jQuery的库文件。可以使用CDN方式引入jQuery,也可以将其下载到本地并使用相对路径进行引入(以下示例采用CDN方式): <script src="https://cdn.bootcdn.…

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