在服务器端配置中,我们将使用AbstractWebSocketMessageBrokerConfigurer
配置我们的websocket协议来使用STOMP作为消息代理和常见注释,例如由@MessageMapping,@SendTo和@MessageExceptionHandler提供spring-boot-starter-websocket
。此示例使用STOMP作为消息代理,但它是可选的,这是一个spring boot websocket的示例,不使用STOMP。
在客户端,我们将有一个角色应用程序运行并通过websocket协议连接到服务器。为了与websocket集成,我们将使用stompjs库和sockJs库。您可以轻松扩展此示例应用程序以创建聊天应用程序。
与http一样,websocket也是一种通信协议,它提供了服务器和客户端之间的双向全双工通信通道。一旦在客户端和服务器之间建立了websocket连接,双方就可以无休止地交换信息,直到连接完成由任何一方关闭,这是为什么websocket优于HTTP的主要原因,因为客户端和服务器需要以高频率和低延迟交换信息,因为一旦服务器提供请求,HTTP连接就会关闭,一个时间限制来再次打开HTTP连接。
此外,websocket协议是双向的,即客户端可以订阅某个事件,并且服务器可以基于服务器中事件的可用性将事件发布到客户端。
WebSocketConfig.java
拥有所有websocket和sockJS相关配置。
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic/", "/queue/");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/greeting")
.setAllowedOrigins("*");
//.withSockJS();
}
}
@EnableWebSocketMessageBroker启用消息代理,默认情况下spring使用STOMP作为消息代理。因此,此应用程序将使用STOMP作为websocket通信的消息代理,但您可以自由使用其他消息传递协议,如RabbitMQ或ActiveMQ。
同样,该方法configureMessageBroker()
使简单的基于内存的消息代理能够将消息带回以“/ topic”和“/ queue”为前缀的客户端。因此,从我们的服务器端websocket响应将发送到以这些端点为前缀的端点,并且角客户端将订阅以这些前缀开头的url,例如“/ topic / reply”
类似地,registerStompEndpoints()启用STOMP支持,并在“/greeting"处注册stomp结果。这样,所有websocket消息将通过STOMP进行信道化,这也为websocket端点增加了额外的安全层。请记住,在从javascipt创建websocket连接时,我们将使用这个特定的stomp端点,即让socket = new WebSocket(“ws:// localhost:8080 / greeting”); 只要。
现在让我们定义我们的控制器来映射要通过websocket协议接收的消息。
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageExceptionHandler;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.stereotype.Controller;
import com.google.gson.Gson;
@Controller
public class WebSocketController {
@Autowired
private SimpMessageSendingOperations messagingTemplate;
@MessageMapping("/message")
@SendTo("/topic/reply")
public String processMessageFromClient(@Payload String message) throws Exception {
String name = new Gson().fromJson(message, Map.class).get("name").toString();
return name;
}
@MessageExceptionHandler
public String handleException(Throwable exception) {
messagingTemplate.convertAndSend("/errors", exception.getMessage());
return exception.getMessage();
}
}
@MessageMapping:这是映射消息的URL /消息。因此,客户端应该按照我们的/ app / message发送消息WebSocketCOnfig.java
。
同样,@SendTo用于广播消息。因此,返回的对象processMessageFromClient()
将被广播到这个主题。为了发送这个消息给特定的用户,Spring提供了@SendToUser
让我们首先使用角度cli生成我们的angular 5项目。确保你的机器上安装了Node JS。在这里可以找到关于Angular的一步一步的配置和教程。
ng new angular-websocket
cd angular-websocket
ng serve
现在您可以在任何IDE中导入项目。项目结构应如下所示npm install stompjs --save
npm install sockjs-client --save
这将增加依赖关系package.json
。现在,让我们定义我们的html代码。我们拥有的html有两个用于连接和断开websocket连接的按钮。同样,发送按钮将通过websocket协议以JSON格式将名称发送给服务器,服务器将从中提取名称并发送回客户端订阅的主题。
<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="button" [disabled]="disabled" (click)="connect()">Connect</button>
<button id="disconnect" class="btn btn-default" type="button" [disabled]="!disabled" (click)="disconnect()">Disconnect
</button>
</div>
</form>
</div>
<div class="col-md-6">
<form class="form-inline" name="test-form">
<div class="form-group">
<label for="name">What is your name?</label>
<input type="text" id="name" name="name" class="form-control" placeholder="Your name here..." [(ngModel)]="name">
</div>
<button id="send" class="btn btn-default" type="button" (click)="sendName()">Send</button>
</form>
</div>
</div>
<div class="row">
<div class="col-md-12" *ngIf="showConversation">
<table id="conversation" class="table table-striped">
<thead>
<tr>
<th>Greetings</th>
</tr>
</thead>
<tbody *ngFor="let greeting of greetings" >
<tr><td> </td></tr>
</tbody>
</table>
</div>
</div>
</div>
同样,我们有以下打字稿代码。
connect()将创建一个web套接字连接。请记住我们在WebSocketConfig.java类中为/ greeting做的映射。
showGreeting()将只显示服务器广播收到的消息。
send()函数将构造一个JSON消息并将消息发送到服务器。
app.component.ts:
import { Component } from '@angular/core';
import * as Stomp from 'stompjs';
import * as SockJS from 'sockjs-client';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
greetings: string[] = [];
showConversation: boolean = false;
ws: any;
name: string;
disabled: boolean;
constructor(){}
connect() {
//connect to stomp where stomp endpoint is exposed
//let ws = new SockJS(http://localhost:8080/greeting);
let socket = new WebSocket("ws://localhost:8080/greeting");
this.ws = Stomp.over(socket);
let that = this;
this.ws.connect({}, function(frame) {
that.ws.subscribe("/errors", function(message) {
alert("Error " + message.body);
});
that.ws.subscribe("/topic/reply", function(message) {
console.log(message)
that.showGreeting(message.body);
});
that.disabled = true;
}, function(error) {
alert("STOMP error " + error);
});
}
disconnect() {
if (this.ws != null) {
this.ws.ws.close();
}
this.setConnected(false);
console.log("Disconnected");
}
sendName() {
let data = JSON.stringify({
'name' : this.name
})
this.ws.send("/app/message", {}, data);
}
showGreeting(message) {
this.showConversation = true;
this.greetings.push(message)
}
setConnected(connected) {
this.disabled = connected;
this.showConversation = connected;
this.greetings = [];
}
}
.withSockJS()
var socket = new SockJS('ws://localhost:8080/greeting');
ws = Stomp.over(socket);
//rest of the code as usual as above
运行Application.java作为Java应用程序,并在控制台输入命令,ng serve
然后点击http:// localhost:4200
https://www.leftso.com/article/450.html