Erweiterungen
This commit is contained in:
@@ -32,14 +32,70 @@ Das System bietet folgende STOMP-Funktionalitäten:
|
||||
|
||||
```javascript
|
||||
// Mit SockJS
|
||||
const socket = new SockJS('http://localhost:8080/ws');
|
||||
const socket = new SockJS('http://192.168.180.196:8080/ws');
|
||||
const stompClient = Stomp.over(socket);
|
||||
|
||||
// Oder mit nativem WebSocket
|
||||
const socket = new WebSocket('ws://localhost:8080/websocket');
|
||||
// Oder mit nativem WebSocket (WICHTIG: ws:// verwenden, nicht http://)
|
||||
const socket = new WebSocket('ws://192.168.180.196:8080/websocket');
|
||||
const stompClient = Stomp.over(socket);
|
||||
```
|
||||
|
||||
### Flutter/Dart STOMP Client
|
||||
|
||||
**Für Flutter-Apps verwenden Sie diese Konfiguration:**
|
||||
|
||||
```dart
|
||||
import 'package:stomp_dart_client/stomp.dart';
|
||||
import 'package:stomp_dart_client/stomp_config.dart';
|
||||
import 'package:stomp_dart_client/stomp_frame.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
// WICHTIG: Verwenden Sie ws:// für WebSocket-Verbindungen, NICHT http://
|
||||
final stompClient = StompClient(
|
||||
config: StompConfig(
|
||||
url: 'ws://192.168.180.196:8080/websocket', // Beachten Sie ws:// statt http://
|
||||
onConnect: onConnectCallback,
|
||||
onWebSocketError: (dynamic error) => print('WebSocket Error: $error'),
|
||||
onStompError: (StompFrame frame) => print('Stomp Error: ${frame.body}'),
|
||||
onDisconnect: (StompFrame frame) => print('Disconnected'),
|
||||
// Heartbeat-Konfiguration
|
||||
heartbeatIncoming: Duration(seconds: 20),
|
||||
heartbeatOutgoing: Duration(seconds: 20),
|
||||
),
|
||||
);
|
||||
|
||||
void onConnectCallback(StompFrame frame) {
|
||||
print('Connected to STOMP server');
|
||||
|
||||
// Nachrichten abonnieren
|
||||
stompClient.subscribe(
|
||||
destination: '/topic/messages',
|
||||
callback: (StompFrame frame) {
|
||||
print('Received message: ${frame.body}');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Verbindung herstellen
|
||||
stompClient.activate();
|
||||
|
||||
// Nachricht senden
|
||||
void sendMessage(String content) {
|
||||
stompClient.send(
|
||||
destination: '/app/message',
|
||||
body: jsonEncode({
|
||||
'content': content,
|
||||
'sender': 'FlutterApp',
|
||||
}),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**Alternative Endpunkte für Flutter:**
|
||||
Falls Probleme mit `/websocket` auftreten, versuchen Sie:
|
||||
- `ws://192.168.180.196:8080/stomp` (zusätzlicher Endpunkt)
|
||||
- `ws://192.168.180.196:8080/ws` (SockJS-Endpunkt ohne SockJS-Protokoll)
|
||||
|
||||
### 2. Verbindung herstellen
|
||||
|
||||
```javascript
|
||||
|
||||
159
flutter_websocket_test.html
Normal file
159
flutter_websocket_test.html
Normal file
@@ -0,0 +1,159 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Flutter WebSocket Test</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@stomp/stompjs@7.0.0/bundles/stomp.umd.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Flutter WebSocket STOMP Test</h1>
|
||||
<div id="status">Nicht verbunden</div>
|
||||
<button onclick="connectWebSocket()">WebSocket Verbinden</button>
|
||||
<button onclick="connectSockJS()">SockJS Verbinden</button>
|
||||
<button onclick="disconnect()">Trennen</button>
|
||||
<br><br>
|
||||
<input type="text" id="messageInput" placeholder="Nachricht eingeben" />
|
||||
<button onclick="sendMessage()">Nachricht senden</button>
|
||||
<br><br>
|
||||
<div id="messages"></div>
|
||||
|
||||
<script>
|
||||
let stompClient = null;
|
||||
|
||||
function connectWebSocket() {
|
||||
// WICHTIG: Für native WebSocket MUSS ws:// verwendet werden, NICHT http://
|
||||
const socket = new WebSocket('ws://192.168.180.196:8080/websocket');
|
||||
stompClient = Stomp.over(socket);
|
||||
|
||||
stompClient.debug = function(str) {
|
||||
console.log('STOMP Debug: ' + str);
|
||||
addMessage('DEBUG: ' + str);
|
||||
};
|
||||
|
||||
stompClient.connect({}, function(frame) {
|
||||
console.log('WebSocket Connected: ' + frame);
|
||||
document.getElementById('status').innerHTML = 'WebSocket Verbunden';
|
||||
addMessage('WebSocket erfolgreich verbunden');
|
||||
|
||||
// Nachrichten abonnieren
|
||||
stompClient.subscribe('/topic/messages', function(message) {
|
||||
addMessage('Empfangen: ' + message.body);
|
||||
});
|
||||
}, function(error) {
|
||||
console.error('WebSocket Connection Error:', error);
|
||||
document.getElementById('status').innerHTML = 'WebSocket Fehler: ' + error;
|
||||
addMessage('WebSocket Fehler: ' + error);
|
||||
});
|
||||
}
|
||||
|
||||
function connectSockJS() {
|
||||
// Für SockJS kann http:// verwendet werden
|
||||
const socket = new SockJS('http://192.168.180.196:8080/ws');
|
||||
stompClient = Stomp.over(socket);
|
||||
|
||||
stompClient.debug = function(str) {
|
||||
console.log('STOMP Debug: ' + str);
|
||||
addMessage('DEBUG: ' + str);
|
||||
};
|
||||
|
||||
stompClient.connect({}, function(frame) {
|
||||
console.log('SockJS Connected: ' + frame);
|
||||
document.getElementById('status').innerHTML = 'SockJS Verbunden';
|
||||
addMessage('SockJS erfolgreich verbunden');
|
||||
|
||||
// Nachrichten abonnieren
|
||||
stompClient.subscribe('/topic/messages', function(message) {
|
||||
addMessage('Empfangen: ' + message.body);
|
||||
});
|
||||
}, function(error) {
|
||||
console.error('SockJS Connection Error:', error);
|
||||
document.getElementById('status').innerHTML = 'SockJS Fehler: ' + error;
|
||||
addMessage('SockJS Fehler: ' + error);
|
||||
});
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
if (stompClient !== null) {
|
||||
stompClient.disconnect();
|
||||
document.getElementById('status').innerHTML = 'Getrennt';
|
||||
addMessage('Verbindung getrennt');
|
||||
}
|
||||
}
|
||||
|
||||
function sendMessage() {
|
||||
const messageInput = document.getElementById('messageInput');
|
||||
if (stompClient && messageInput.value) {
|
||||
stompClient.send('/app/message', {}, JSON.stringify({
|
||||
'content': messageInput.value,
|
||||
'sender': 'WebTest'
|
||||
}));
|
||||
addMessage('Gesendet: ' + messageInput.value);
|
||||
messageInput.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
function addMessage(message) {
|
||||
const messagesDiv = document.getElementById('messages');
|
||||
const messageElement = document.createElement('div');
|
||||
messageElement.innerHTML = new Date().toLocaleTimeString() + ': ' + message;
|
||||
messagesDiv.appendChild(messageElement);
|
||||
messagesDiv.scrollTop = messagesDiv.scrollHeight;
|
||||
}
|
||||
</script>
|
||||
|
||||
<h2>Flutter Dart Code Beispiel:</h2>
|
||||
<pre><code>
|
||||
import 'package:stomp_dart_client/stomp.dart';
|
||||
import 'package:stomp_dart_client/stomp_config.dart';
|
||||
import 'package:stomp_dart_client/stomp_frame.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
// RICHTIG: ws:// für WebSocket verwenden
|
||||
final stompClient = StompClient(
|
||||
config: StompConfig(
|
||||
url: 'ws://192.168.180.196:8080/websocket', // ws:// NICHT http://
|
||||
onConnect: (StompFrame frame) {
|
||||
print('Connected to STOMP server');
|
||||
|
||||
// Nachrichten abonnieren
|
||||
stompClient.subscribe(
|
||||
destination: '/topic/messages',
|
||||
callback: (StompFrame frame) {
|
||||
print('Received: ${frame.body}');
|
||||
},
|
||||
);
|
||||
},
|
||||
onWebSocketError: (dynamic error) => print('WebSocket Error: $error'),
|
||||
onStompError: (StompFrame frame) => print('Stomp Error: ${frame.body}'),
|
||||
onDisconnect: (StompFrame frame) => print('Disconnected'),
|
||||
),
|
||||
);
|
||||
|
||||
// Verbindung aktivieren
|
||||
stompClient.activate();
|
||||
|
||||
// Nachricht senden
|
||||
void sendMessage(String content) {
|
||||
stompClient.send(
|
||||
destination: '/app/message',
|
||||
body: jsonEncode({
|
||||
'content': content,
|
||||
'sender': 'FlutterApp',
|
||||
}),
|
||||
);
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<h2>Verfügbare Endpunkte:</h2>
|
||||
<ul>
|
||||
<li><strong>ws://192.168.180.196:8080/websocket</strong> - Native WebSocket (empfohlen für Flutter)</li>
|
||||
<li><strong>ws://192.168.180.196:8080/stomp</strong> - Alternative WebSocket Endpunkt</li>
|
||||
<li><strong>http://192.168.180.196:8080/ws</strong> - SockJS Endpunkt (nur für Browser)</li>
|
||||
</ul>
|
||||
|
||||
<h2>Häufiger Fehler:</h2>
|
||||
<p><strong>FALSCH:</strong> <code>http://192.168.180.196:8080/websocket</code></p>
|
||||
<p><strong>RICHTIG:</strong> <code>ws://192.168.180.196:8080/websocket</code></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -5,6 +5,7 @@ import org.springframework.messaging.simp.config.MessageBrokerRegistry;
|
||||
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
|
||||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
|
||||
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
|
||||
|
||||
/**
|
||||
* WebSocket configuration for STOMP messaging.
|
||||
@@ -23,15 +24,32 @@ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
|
||||
// Designate the "/app" prefix for messages that are bound to methods
|
||||
// annotated with @MessageMapping
|
||||
config.setApplicationDestinationPrefixes("/app");
|
||||
|
||||
// Set user destination prefix for user-specific messages
|
||||
config.setUserDestinationPrefix("/user");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
// Register the "/ws" endpoint for WebSocket connections
|
||||
// withSockJS() enables SockJS fallback options for browsers that don't support WebSocket
|
||||
registry.addEndpoint("/ws").withSockJS();
|
||||
// Register the "/ws" endpoint for WebSocket connections with SockJS fallback
|
||||
registry.addEndpoint("/ws")
|
||||
.setAllowedOriginPatterns("*")
|
||||
.addInterceptors(new HttpSessionHandshakeInterceptor())
|
||||
.withSockJS()
|
||||
.setHeartbeatTime(25000) // Set heartbeat interval
|
||||
.setDisconnectDelay(5000) // Set disconnect delay
|
||||
.setStreamBytesLimit(128 * 1024) // Set stream bytes limit
|
||||
.setHttpMessageCacheSize(1000) // Set HTTP message cache size
|
||||
.setSessionCookieNeeded(false); // Disable session cookie requirement
|
||||
|
||||
// Also add a plain WebSocket endpoint without SockJS for native WebSocket clients
|
||||
registry.addEndpoint("/websocket");
|
||||
// Plain WebSocket endpoint without SockJS for native WebSocket clients (Flutter, mobile apps)
|
||||
registry.addEndpoint("/websocket")
|
||||
.setAllowedOriginPatterns("*")
|
||||
.addInterceptors(new HttpSessionHandshakeInterceptor());
|
||||
|
||||
// Additional endpoint specifically for mobile/Flutter clients that might have URL issues
|
||||
registry.addEndpoint("/stomp")
|
||||
.setAllowedOriginPatterns("*")
|
||||
.addInterceptors(new HttpSessionHandshakeInterceptor());
|
||||
}
|
||||
}
|
||||
@@ -37,10 +37,26 @@ public class SecurityConfig extends VaadinWebSecurity {
|
||||
new AntPathRequestMatcher("/frontend/**"),
|
||||
new AntPathRequestMatcher("/webjars/**"),
|
||||
new AntPathRequestMatcher("/h2-console/**"),
|
||||
new AntPathRequestMatcher("/frontend-es5/**", "/frontend-es6/**")
|
||||
new AntPathRequestMatcher("/frontend-es5/**", "/frontend-es6/**"),
|
||||
// WebSocket und STOMP Endpunkte
|
||||
new AntPathRequestMatcher("/ws/**"),
|
||||
new AntPathRequestMatcher("/websocket/**"),
|
||||
new AntPathRequestMatcher("/stomp/**"),
|
||||
new AntPathRequestMatcher("/app/**"),
|
||||
new AntPathRequestMatcher("/topic/**"),
|
||||
new AntPathRequestMatcher("/queue/**")
|
||||
).permitAll()
|
||||
);
|
||||
|
||||
// CSRF für WebSocket-Endpunkte deaktivieren
|
||||
http.csrf(csrf -> csrf
|
||||
.ignoringRequestMatchers(
|
||||
new AntPathRequestMatcher("/ws/**"),
|
||||
new AntPathRequestMatcher("/websocket/**"),
|
||||
new AntPathRequestMatcher("/stomp/**")
|
||||
)
|
||||
);
|
||||
|
||||
// Delegiere die Basis-Konfiguration an VaadinWebSecurity
|
||||
// Dies fügt automatisch .anyRequest().authenticated() hinzu
|
||||
super.configure(http);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
server.port=${PORT:8080}
|
||||
server.address=0.0.0.0
|
||||
logging.level.org.atmosphere=warn
|
||||
spring.mustache.check-template-location=false
|
||||
|
||||
|
||||
Reference in New Issue
Block a user