Spring Boot Basic – Tag 8 von 10
Von Elyndra Valen, Senior Entwicklerin bei Java Fleet Systems Consulting


WebSockets in Spring Boot

📍 Deine Position im Kurs

TagThemaStatus
✅ 1Erste REST APIAbgeschlossen
✅ 2Spring Container & DIAbgeschlossen
✅ 3@Controller & Thymeleaf BasicsAbgeschlossen
✅ 4Thymeleaf Forms & MVC-PatternAbgeschlossen
✅ 5Konfiguration & LoggingAbgeschlossen
✅ 6DI & AOP im DetailAbgeschlossen
✅ 7Scopes in SpringAbgeschlossen
→ 8WebSockets in Spring Boot👉 DU BIST HIER!
9JAX-RS in Spring BootNoch nicht freigeschaltet
10Integration & AbschlussNoch nicht freigeschaltet

Modul: Spring Boot Basic (10 Arbeitstage)
Dein Ziel: Real-Time Communication mit WebSockets meistern!


📋 Voraussetzungen

Du brauchst:

  • ✅ Tag 1-7 abgeschlossen
  • ✅ REST APIs verstehen (GET, POST)
  • ✅ @Controller und Model funktionieren
  • ✅ Thymeleaf Templates erstellen können
  • ✅ Scopes verstehen (Session, Request)
  • 💡 Bonus: JavaScript Grundkenntnisse helfen!

Tag 7 verpasst? → Hier geht’s zum Blogbeitrag Tag 7


⚡ Was dich heute erwartet

Bisher: Du hast REST APIs gebaut – aber jeder Request braucht eine Antwort.

Das Problem:

Client fragt: "Gibt es neue Nachrichten?"
Server antwortet: "Nein."

30 Sekunden später...
Client fragt: "Gibt es neue Nachrichten?"
Server antwortet: "Nein."

30 Sekunden später...
Client fragt: "Gibt es neue Nachrichten?"
Server antwortet: "Ja, hier ist eine!"

→ Client muss STÄNDIG fragen (Polling) 😫
→ Verschwendet Bandbreite und Ressourcen!

Die Lösung: WebSockets!

Client verbindet sich mit Server
Server kann JEDERZEIT Nachrichten schicken!

Neue Nachricht kommt an
→ Server schickt SOFORT an Client!
→ Keine ständigen Requests nötig! ✅

🎯 Dein Lernpfad heute

Du arbeitest heute in mehreren aufbauenden Schwierigkeitsstufen. Hier hast du die Anwendung die hier verwendet wird, direkt als Zip Datei. Arbeite in deinem eigenen Tempo durch die Schritte:

🟢 Grundlagen (Schritte 1-3)

Was du lernst:

  • WebSockets verstehen – was ist das?
  • Unterschied HTTP vs WebSocket
  • STOMP Protocol kennenlernen
  • WebSocket Configuration in Spring Boot
  • Dependencies einrichten
  • Zwei Ansätze: Low-Level vs STOMP

Ziel: Du verstehst WebSockets und hast die Basis konfiguriert


🟡 Professional (Schritte 4-6)

Was du lernst:

  • @MessageMapping – der WebSocket-Controller
  • Chat-Application mit STOMP bauen
  • Broadcasting (an alle senden)
  • Live Person-Notifications implementieren
  • Frontend mit JavaScript/SockJS

Ziel: Production-Ready Live-Chat und Real-Time Updates

Dauer: ~3.5 Stunden


🔵 Bonus: Enterprise Features (Schritte 7-8)

Was du lernst:

  • Point-to-Point Messages (an einen User)
  • WebSocket Security implementieren
  • Reconnect-Logik & Heartbeat
  • Rate Limiting für Messages
  • Presence Detection (wer ist online?)

Ziel: Enterprise-Level Real-Time Features beherrschen

Dauer: ~2 Stunden


💻 Los geht’s!

🟢 GRUNDLAGEN (Schritte 1-3)

Schritt 1: WebSockets verstehen (45 Min)

1.1 Das Problem mit klassischem HTTP

Erinnerst du dich an REST APIs von Tag 1?

@RestController
@RequestMapping("/api/persons")
public class PersonApiController {
    
    @GetMapping
    public List<Person> getAllPersons() {
        return personService.getAllPersons();
    }
}

Was passiert:

┌─────────────────────────────────────────┐
│   CLIENT (Browser)                      │
│                                         │
│   GET /api/persons                      │
│   ────────────────────────────►         │
│                                         │
│                        ◄────────────────│
│                        [Person-Liste]   │
│                                         │
│   (30 Sekunden warten...)               │
│                                         │
│   GET /api/persons (erneut!)            │
│   ────────────────────────────►         │
└─────────────────────────────────────────┘

Das Problem:

  • ❌ Client muss aktiv fragen (Polling)
  • ❌ Server kann nicht von sich aus senden
  • ❌ Verschwendet Bandbreite (ständige Requests)
  • ❌ Langsam (30 Sekunden bis neue Daten sichtbar)
  • ❌ Hohe Server-Last (viele unnötige Requests)

1.2 Die Lösung: WebSockets

WebSocket = Dauerhafte Verbindung zwischen Client und Server!

┌─────────────────────────────────────────┐
│   CLIENT                    SERVER      │
│                                         │
│   WebSocket-Verbindung aufbauen         │
│   ════════════════════════►             │
│                                         │
│   ◄══════════════════════►              │
│   (Verbindung bleibt offen!)            │
│                                         │
│   Client sendet Nachricht               │
│   ────────────────────────►             │
│                                         │
│   Server sendet SOFORT zurück           │
│   ◄────────────────────────             │
│                                         │
│   Server sendet neue Daten (von sich!)  │
│   ◄────────────────────────             │
└─────────────────────────────────────────┘

Vorteile:

  • ✅ Bidirektional – beide Seiten senden
  • ✅ Real-Time – Daten sofort da
  • ✅ Effizient – eine Verbindung statt viele Requests
  • ✅ Server-Push – Server kann initiieren
  • ✅ Weniger Overhead – keine HTTP-Headers bei jedem Request

1.3 HTTP vs WebSocket – Der Vergleich

FeatureHTTP (REST)WebSocket
VerbindungPro Request neuDauerhaft offen
RichtungClient → ServerBeide Richtungen
OverheadHoch (Headers)Niedrig (einmal Handshake)
Real-TimeNein (Polling nötig)Ja (sofort)
Use CasesCRUD, FormulareChat, Live-Updates, Gaming
Server-PushNeinJa

Wann was nutzen?

✅ Nutze HTTP/REST für:
- Formulare absenden
- Daten laden (einmalig)
- CRUD-Operationen
- Datei-Downloads
- Statische Inhalte

✅ Nutze WebSockets für:
- Chat-Applications
- Live-Notifications
- Multiplayer-Games
- Live-Dashboards
- Collaborative Editing
- Stock-Ticker

1.4 STOMP – Das Messaging-Protocol

WebSocket alleine = nur „Rohr“ für Daten!

Du brauchst ein Protocol darüber – wie strukturierst du Nachrichten?

STOMP = Simple Text Oriented Messaging Protocol

┌─────────────────────────────────────────┐
│   Application (dein Java-Code)          │
│   ─────────────────────────────────     │
│   STOMP (Messaging-Protocol)            │
│   ─────────────────────────────────     │
│   WebSocket (Transport-Layer)           │
│   ─────────────────────────────────     │
│   TCP/IP                                │
└─────────────────────────────────────────┘

Was macht STOMP:

  • 📨 Destinations – „/topic/chat“ (wie REST-Pfade)
  • 🎯 Subscribe – Client abonniert Topics
  • 📤 Send – Client sendet an Destination
  • 📥 Receive – Server sendet an Subscriber
  • 💬 Frames – Strukturierte Nachrichten

Spring Boot nutzt STOMP standardmäßig! Du musst es nicht manuell implementieren.


Schritt 2: Dependencies hinzufügen (15 Min)

pom.xml:

<dependencies>
    <!-- Existing dependencies -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
    <!-- WebSocket Support -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
    
    <!-- Webjars für Frontend-Libraries -->
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>sockjs-client</artifactId>
        <version>1.5.1</version>
    </dependency>
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>stomp-websocket</artifactId>
        <version>2.3.4</version>
    </dependency>
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>bootstrap</artifactId>
        <version>5.3.0</version>
    </dependency>
</dependencies>

Maven reload nicht vergessen!

mvn clean install

Schritt 3: WebSocket Configuration (1.5 Stunden)

3.1 STOMP-basierte Configuration

config/WebSocketConfig.java:

package com.example.springbootbasic.config;

import org.springframework.context.annotation.Configuration;
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;

@Configuration
@EnableWebSocketMessageBroker  // WebSocket aktivieren!
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // Simple Broker für Broadcasting
        config.enableSimpleBroker("/topic", "/queue");
        
        // Prefix für Messages die an Server gehen
        config.setApplicationDestinationPrefixes("/app");
    }
    
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // WebSocket-Endpoint registrieren
        registry.addEndpoint("/ws")
                .withSockJS();  // Fallback wenn WebSocket nicht verfügbar
    }
}

Was bedeutet das?

/topic/* 
→ Broadcasting-Destinations (alle Subscriber bekommen Nachricht)
→ Beispiel: /topic/notifications (alle User sehen)

/queue/*
→ Point-to-Point-Destinations (nur ein User bekommt Nachricht)
→ Beispiel: /queue/user123/messages (nur User 123 sieht)

/app/*
→ Messages die an Server-Controller gehen
→ Beispiel: /app/chat.send → @MessageMapping("/chat.send")

/ws
→ WebSocket-Endpoint (Client verbindet sich hierhin)
→ Mit SockJS-Fallback wenn Browser kein WebSocket kann

3.2 Message-Models erstellen

dto/ChatMessage.java:

package com.example.springbootbasic.dto;

import java.time.LocalDateTime;

public class ChatMessage {
    
    private String content;
    private String sender;
    private MessageType type;
    private LocalDateTime timestamp;
    
    public enum MessageType {
        CHAT,
        JOIN,
        LEAVE
    }
    
    // Constructors
    public ChatMessage() {
        this.timestamp = LocalDateTime.now();
    }
    
    public ChatMessage(String content, String sender, MessageType type) {
        this.content = content;
        this.sender = sender;
        this.type = type;
        this.timestamp = LocalDateTime.now();
    }
    
    // Getters and Setters
    public String getContent() { return content; }
    public void setContent(String content) { this.content = content; }
    
    public String getSender() { return sender; }
    public void setSender(String sender) { this.sender = sender; }
    
    public MessageType getType() { return type; }
    public void setType(MessageType type) { this.type = type; }
    
    public LocalDateTime getTimestamp() { return timestamp; }
    public void setTimestamp(LocalDateTime timestamp) { this.timestamp = timestamp; }
}

✅ Checkpoint Grundlagen

Kontrolliere:

  • [ ] Du verstehst was WebSockets sind
  • [ ] Du kennst den Unterschied zu REST APIs
  • [ ] Du weißt was STOMP ist
  • [ ] Dependencies sind in pom.xml
  • [ ] WebSocketConfig ist erstellt
  • [ ] Du verstehst /topic vs /queue
  • [ ] ChatMessage DTO ist erstellt

Alles ✅? Weiter zu 🟡 Professional!


🟡 PROFESSIONAL (Schritte 4-6)

Schritt 4: WebSocket-Controller erstellen (1.5 Stunden)

4.1 Chat-Controller mit @MessageMapping

controller/ChatController.java:

package com.example.springbootbasic.controller;

import com.example.springbootbasic.dto.ChatMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.SimpMessageHeaderAccessor;
import org.springframework.stereotype.Controller;

@Controller
public class ChatController {
    
    private static final Logger log = LoggerFactory.getLogger(ChatController.class);
    
    @MessageMapping("/chat.send")  // Client sendet an /app/chat.send
    @SendTo("/topic/public")       // Broadcast an alle die /topic/public abonniert haben
    public ChatMessage sendMessage(@Payload ChatMessage chatMessage) {
        log.info("Received message from {}: {}", 
            chatMessage.getSender(), 
            chatMessage.getContent());
        
        return chatMessage;  // Wird an alle Subscriber gesendet
    }
    
    @MessageMapping("/chat.join")
    @SendTo("/topic/public")
    public ChatMessage addUser(@Payload ChatMessage chatMessage,
                                SimpMessageHeaderAccessor headerAccessor) {
        
        // Username in WebSocket-Session speichern
        headerAccessor.getSessionAttributes().put("username", chatMessage.getSender());
        
        log.info("User joined: {}", chatMessage.getSender());
        
        chatMessage.setType(ChatMessage.MessageType.JOIN);
        chatMessage.setContent(chatMessage.getSender() + " ist dem Chat beigetreten!");
        
        return chatMessage;
    }
}

Was passiert hier?

Client sendet:
POST /app/chat.send
{
  "content": "Hallo Welt!",
  "sender": "Max",
  "type": "CHAT"
}

Server empfängt:
@MessageMapping("/chat.send") wird aufgerufen
→ Verarbeitet Nachricht
→ return chatMessage

Server sendet:
An /topic/public (Broadcasting!)
→ ALLE die /topic/public abonniert haben
→ bekommen die ChatMessage!

4.2 WebSocket Event Listener

listener/WebSocketEventListener.java:

package com.example.springbootbasic.listener;

import com.example.springbootbasic.dto.ChatMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionConnectedEvent;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;

@Component
public class WebSocketEventListener {
    
    private static final Logger log = LoggerFactory.getLogger(WebSocketEventListener.class);
    
    private final SimpMessageSendingOperations messagingTemplate;
    
    public WebSocketEventListener(SimpMessageSendingOperations messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }
    
    @EventListener
    public void handleWebSocketConnectListener(SessionConnectedEvent event) {
        log.info("New WebSocket connection established");
    }
    
    @EventListener
    public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {
        StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
        
        String username = (String) headerAccessor.getSessionAttributes().get("username");
        
        if (username != null) {
            log.info("User disconnected: {}", username);
            
            ChatMessage chatMessage = new ChatMessage();
            chatMessage.setType(ChatMessage.MessageType.LEAVE);
            chatMessage.setSender(username);
            chatMessage.setContent(username + " hat den Chat verlassen!");
            
            messagingTemplate.convertAndSend("/topic/public", chatMessage);
        }
    }
}

Schritt 5: Frontend mit WebSocket (2 Stunden)

5.1 Chat-Template erstellen

templates/chat.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Spring Boot Chat</title>
    <link rel="stylesheet" th:href="@{/webjars/bootstrap/5.3.0/css/bootstrap.min.css}">
    
    <style>
        body {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        
        #chat-page { display: none; }
        
        .chat-container {
            max-width: 700px;
            background: white;
            border-radius: 10px;
            box-shadow: 0 10px 40px rgba(0,0,0,0.2);
        }
        
        .chat-header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 20px;
            border-radius: 10px 10px 0 0;
        }
        
        .chat-messages {
            height: 400px;
            overflow-y: auto;
            padding: 20px;
            background: #f8f9fa;
        }
        
        .message {
            margin-bottom: 15px;
            padding: 10px 15px;
            border-radius: 20px;
            max-width: 70%;
        }
        
        .message.own {
            background: #667eea;
            color: white;
            margin-left: auto;
            text-align: right;
        }
        
        .message.other {
            background: white;
            border: 1px solid #dee2e6;
        }
        
        .message.event {
            background: #fff3cd;
            text-align: center;
            margin: 10px auto;
            font-style: italic;
            max-width: 100%;
        }
    </style>
</head>
<body>

<!-- Username Page -->
<div id="username-page">
    <div class="username-form" style="background: white; padding: 40px; border-radius: 10px;">
        <h2 class="mb-4">🚀 Spring Boot Chat</h2>
        <form id="usernameForm">
            <input type="text" id="username" class="form-control mb-3" placeholder="Dein Name" required>
            <button type="submit" class="btn btn-primary w-100">Chat beitreten</button>
        </form>
    </div>
</div>

<!-- Chat Page -->
<div id="chat-page" class="chat-container">
    <div class="chat-header">
        <h4>💬 Spring Boot Live Chat</h4>
        <small id="connected-user"></small>
    </div>
    
    <div id="chat-messages" class="chat-messages"></div>
    
    <div class="p-3">
        <form id="messageForm">
            <div class="input-group">
                <input type="text" id="message" class="form-control" placeholder="Nachricht...">
                <button type="submit" class="btn btn-primary">Senden</button>
            </div>
        </form>
    </div>
</div>

<script th:src="@{/webjars/sockjs-client/1.5.1/sockjs.min.js}"></script>
<script th:src="@{/webjars/stomp-websocket/2.3.4/stomp.min.js}"></script>

<script>
    let stompClient = null;
    let currentUser = null;
    
    const usernamePage = document.querySelector('#username-page');
    const chatPage = document.querySelector('#chat-page');
    const usernameForm = document.querySelector('#usernameForm');
    const messageForm = document.querySelector('#messageForm');
    const messageInput = document.querySelector('#message');
    const chatMessages = document.querySelector('#chat-messages');
    
    usernameForm.addEventListener('submit', function(e) {
        e.preventDefault();
        currentUser = document.querySelector('#username').value.trim();
        
        if (currentUser) {
            usernamePage.style.display = 'none';
            chatPage.style.display = 'block';
            connect();
        }
    });
    
    function connect() {
        const socket = new SockJS('/ws');
        stompClient = Stomp.over(socket);
        
        stompClient.connect({}, onConnected, onError);
    }
    
    function onConnected() {
        stompClient.subscribe('/topic/public', onMessageReceived);
        
        stompClient.send("/app/chat.join", {},
            JSON.stringify({sender: currentUser, type: 'JOIN'})
        );
    }
    
    function onError(error) {
        console.error('WebSocket Error:', error);
    }
    
    messageForm.addEventListener('submit', function(e) {
        e.preventDefault();
        const content = messageInput.value.trim();
        
        if (content && stompClient) {
            stompClient.send("/app/chat.send", {},
                JSON.stringify({sender: currentUser, content: content, type: 'CHAT'})
            );
            messageInput.value = '';
        }
    });
    
    function onMessageReceived(payload) {
        const message = JSON.parse(payload.body);
        const messageElement = document.createElement('div');
        
        if (message.type === 'JOIN' || message.type === 'LEAVE') {
            messageElement.classList.add('message', 'event');
            messageElement.textContent = message.content;
        } else {
            messageElement.classList.add('message');
            messageElement.classList.add(message.sender === currentUser ? 'own' : 'other');
            messageElement.textContent = message.sender + ': ' + message.content;
        }
        
        chatMessages.appendChild(messageElement);
        chatMessages.scrollTop = chatMessages.scrollHeight;
    }
</script>

</body>
</html>

5.2 Controller für View

@Controller
public class ChatViewController {
    
    @GetMapping("/chat")
    public String chatPage() {
        return "chat";
    }
}

5.3 Testen!

# App starten
mvn spring-boot:run

# Browser 1: http://localhost:8080/chat
Username: Alice
Nachricht: "Hallo Bob!"

# Browser 2: http://localhost:8080/chat
Username: Bob
→ Sieht: "Alice ist dem Chat beigetreten!"
→ Sieht: "Alice: Hallo Bob!"

Real-Time Chat funktioniert! ✅


Schritt 6: Person-Notifications (1.5 Stunden)

6.1 PersonService erweitern

@Service
public class PersonService {
    
    private final SimpMessagingTemplate messagingTemplate;
    
    public PersonService(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }
    
    public Person createPerson(Person person) {
        person.setId(idCounter.getAndIncrement());
        persons.add(person);
        
        // WebSocket Notification senden!
        PersonNotification notification = new PersonNotification(
            "Neue Person: " + person.getFirstname(),
            person,
            NotificationType.PERSON_CREATED
        );
        
        messagingTemplate.convertAndSend("/topic/persons", notification);
        
        return person;
    }
}

ALLE Browser die /topic/persons abonniert haben bekommen sofort die Notification! ✅


✅ Checkpoint Professional

Kontrolliere:

  • [ ] ChatController mit @MessageMapping funktioniert
  • [ ] WebSocketEventListener implementiert
  • [ ] Chat-Frontend mit JavaScript erstellt
  • [ ] SockJS und STOMP.js eingebunden
  • [ ] Live-Chat zwischen zwei Browsern funktioniert
  • [ ] PersonService sendet Notifications
  • [ ] Du verstehst Broadcasting

Alles ✅? Weiter zu 🔵 Enterprise Features!


🔵 BONUS: ENTERPRISE FEATURES (Schritte 7-8)

Schritt 7: Point-to-Point Messages (1 Stunde)

7.1 Private Nachrichten

@Controller
public class PrivateMessageController {
    
    private final SimpMessagingTemplate messagingTemplate;
    
    public PrivateMessageController(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }
    
    @MessageMapping("/chat.private")
    public void sendPrivateMessage(@Payload ChatMessage message) {
        // Nachricht an spezifischen User senden
        messagingTemplate.convertAndSendToUser(
            message.getRecipient(),  // Username
            "/queue/private",        // Destination
            message                  // Payload
        );
    }
}

Was passiert:

  • User „Alice“ sendet private Message an „Bob“
  • NUR Bob empfängt die Nachricht
  • Andere User sehen nichts

Schritt 8: WebSocket Security & Best Practices (1 Stunde)

8.1 Security Configuration

@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
    
    @Override
    protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        messages
            .simpDestMatchers("/app/**").authenticated()
            .simpSubscribeDestMatchers("/topic/**", "/queue/**").authenticated()
            .anyMessage().denyAll();
    }
}

8.2 Reconnect-Logik

let reconnectAttempts = 0;
const maxAttempts = 5;

function connect() {
    const socket = new SockJS('/ws');
    stompClient = Stomp.over(socket);
    
    stompClient.connect({}, onConnected, function(error) {
        if (reconnectAttempts < maxAttempts) {
            reconnectAttempts++;
            const delay = Math.min(1000 * Math.pow(2, reconnectAttempts - 1), 30000);
            setTimeout(() => connect(), delay);
        }
    });
}

✅ Checkpoint Enterprise Features

Kontrolliere:

  • [ ] Point-to-Point Messages funktionieren
  • [ ] WebSocket Security konfiguriert
  • [ ] Reconnect-Logik implementiert
  • [ ] Du verstehst /topic vs /queue
  • [ ] Du kannst Production-Ready WebSockets bauen

Alles ✅? Du bist jetzt ein WebSocket-Profi! 🎉

Hier sind noch einige empfehlenswerte externe Links zum Thema „WebSockets mit Spring Boot / Spring Framework”, die du gut zur Vertiefung verwenden kannst!

  • Offizielle Spring-Guide „Using WebSocket to build an interactive web application“ – zeigt Schritt für Schritt, wie man mit STOMP über WebSocket in Spring eine interaktive Anwendung realisiert. Home
  • Offizielle Dokumentation „WebSockets :: Spring Framework“ – tiefgehende Beschreibung der WebSocket-Unterstützung im Spring Framework inklusive SOCKJS, STOMP und Protokollwechsel. Home
  • Baeldung-Tutorial „Intro to WebSockets with Spring“ – eines der gut strukturierten Tutorials mit Praxisbeispielen und dem typischen Chat-Use-Case. Baeldung on Kotlin
  • Spring Boot eigene Dokumentation „WebSockets :: Spring Boot“ – zeigt, wie Spring Boot WebSockets automatisch unterstützt und wie die Konfiguration aussieht. Home
  • Blogbeitrag „WebSocket + Spring Boot: Build a Real-time, Bidirectional Applications“ – verbindet praktische Umsetzung mit Performance-Hinweisen und Real-Time-Szenarien. Medium

🔥 Elyndras Real Talk:

Nova kam heute zu mir, völlig begeistert: „Elyndra! Ich hab gerade verstanden warum WebSockets so cool sind! Ich muss nicht mehr alle 5 Sekunden den Server fragen ob es was Neues gibt!“

Ich lächelte: „Genau. Das ist der Unterschied zwischen ‚Are we there yet?‘ alle 30 Sekunden fragen und dass der Server einfach sagt ‚We’re here!‘ wenn es soweit ist.“

Die AutoTech Real-Time Dashboard Story

Das war 2020, während meines dritten Jahres bei AutoTech. Wir hatten ein Production-Monitoring Dashboard für unsere Autofabrik.

Das Problem: Polling-Hölle

50 gleichzeitig offene Dashboards
× 1 Request alle 5 Sekunden
× 60 Sekunden × 60 Minuten
= 1,080,000 Requests pro Stunde
= NUR fürs Dashboard! 💥

Die Datenbank war am Limit.

Code Sentinel kam zu mir: „Wir brauchen Real-Time Updates OHNE Polling. Kannst du WebSockets implementieren?“

Die WebSocket-Lösung:

1 Database-Query pro Sekunde
× 1 WebSocket-Broadcast
= 3,600 Queries pro Stunde
(statt 1,080,000!)

CPU-Last: -95%
Database-Load: -99%
Update-Latency: 1 Sekunde (statt 5)
✅ Production-Ready!

Nova war beeindruckt: „Das ist ja 300x weniger Last!“

„Exakt,“ sagte ich. „Das ist der Unterschied zwischen ‚Fragen‘ und ‚Informiert werden‘. WebSockets sind wie Push-Notifications für den Browser.“


🆘 Troubleshooting

Problem 1: WebSocket-Verbindung schlägt fehl

Lösung:

// ✅ Richtig - mit SockJS
const socket = new SockJS('/ws');

Problem 2: Nachrichten kommen nicht an

Lösung:

// Subscribe nicht vergessen!
stompClient.subscribe('/topic/public', function(message) {
    console.log(message);
});

❓ FAQ

Q: Wann WebSockets, wann REST?
A: REST für Request/Response (Formular absenden). WebSockets für Real-Time (Chat, Live-Updates).

Q: Was ist STOMP?
A: Ein Messaging-Protocol über WebSocket. Strukturiert Nachrichten mit Destinations.

Q: Was macht SockJS?
A: Fallback wenn Browser kein WebSocket unterstützt.

Q: Unterschied /topic/ vs /queue/*?*
A: /topic/* = Broadcasting (alle), /queue/* = Point-to-Point (einer).


📅 Nächster Kurstag: Tag 9

Morgen: JAX-RS in Spring Boot – REST mit Java Standards!

👉 Zum Blogbeitrag Tag 9


📚 Deine Fortschritts-Übersicht

TagStatus
✅ 1-7ABGESCHLOSSEN! 🎉
✅ 8ABGESCHLOSSEN! 🎉
→ 9Als nächstes

Du hast 80% geschafft! 💪


📥 Download & Ressourcen

Projekt: SpringBootWebSockets-v1.0.zip

Enthält:

  • Live-Chat Application
  • Person-Notifications
  • WebSocket Security
  • Alle Templates

Du kannst jetzt:

  • ✅ WebSockets verstehen
  • ✅ STOMP nutzen
  • ✅ Live-Chat bauen
  • ✅ Real-Time Updates
  • ✅ Broadcasting
  • ✅ Point-to-Point Messages
  • ✅ Production-Ready WebSockets! 🚀

Keep coding, keep learning!


Tags: #SpringBoot #WebSockets #RealTime #STOMP #LiveChat #Tag8

Autor

  • Elyndra Valen

    28 Jahre alt, wurde kürzlich zur Senior Entwicklerin befördert nach 4 Jahren intensiver Java-Entwicklung. Elyndra kennt die wichtigsten Frameworks und Patterns, beginnt aber gerade erst, die tieferen Zusammenhänge und Architektur-Entscheidungen zu verstehen. Sie ist die Brücke zwischen Junior- und Senior-Welt im Team.