You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot向AngularJS 1.4推送STOMP事件异常问题求助

Hey there! Let's work through why your Spring Boot server isn't pushing STOMP messages to your AngularJS 1.4 client, even though the connection and subscription seem to work. I'll also walk you through the correct setup for both sides.

Common Troubleshooting Steps First

Before diving into full implementations, let's rule out the most common issues:

  • Destination Path Mismatch: Double-check that the topic/queue path your server sends messages to exactly matches what your client subscribes to (case sensitivity and slashes matter!).
  • Spring Container Context Issue: If you're manually instantiating your service class (instead of letting Spring manage it), the SimpMessagingTemplate won't have access to the WebSocket context—always use constructor injection for this bean.
  • Broker Configuration: Ensure your Spring WebSocket config enables the message broker for the paths you're using (e.g., /topic or /queue).
  • Security Blocking: If you're using Spring Security, verify that it allows STOMP messages to your target destinations (add rules for "/topic/**" or your specific path).
  • Angular Digest Cycle: STOMP callbacks run outside Angular's digest loop—you need to use $scope.$apply() to update the UI with incoming messages.

Correct Spring Boot STOMP Implementation

1. WebSocket Configuration

First, set up the WebSocket message broker:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // Enable simple in-memory broker for topic/queue destinations
        config.enableSimpleBroker("/topic", "/queue");
        // Prefix for messages sent from client to server-side controllers
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // Register the STOMP endpoint with SockJS fallback (for older browsers)
        registry.addEndpoint("/ws-stomp")
                .setAllowedOriginPatterns("*") // Adjust CORS as needed for your environment
                .withSockJS();
    }
}

2. Service to Process Files & Send Notifications

Use SimpMessagingTemplate (injected by Spring) to send messages once file processing completes:

@Service
public class FileProcessingService {

    private final SimpMessagingTemplate messagingTemplate;

    // Constructor injection ensures we get the Spring-managed template instance
    public FileProcessingService(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    public void processFileList(List<File> files) {
        // Run file processing asynchronously to avoid blocking the HTTP request
        CompletableFuture.runAsync(() -> {
            try {
                // Your actual file processing logic here
                Thread.sleep(3000); // Simulate processing time

                // Send completion notification to the target topic
                String notification = "文件列表已处理完成,以下为结果文件";
                messagingTemplate.convertAndSend("/topic/file-process-complete", notification);

                // Optional: Send result file details if needed
                // messagingTemplate.convertAndSend("/topic/file-process-complete", resultFileData);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                // Send error notification if processing fails
                messagingTemplate.convertAndSend("/topic/file-process-error", "文件处理被中断");
            }
        });
    }
}

3. REST Controller to Trigger Processing

Expose a REST endpoint to start the file processing:

@RestController
@RequestMapping("/api/files")
public class FileController {

    private final FileProcessingService fileProcessingService;

    public FileController(FileProcessingService fileProcessingService) {
        this.fileProcessingService = fileProcessingService;
    }

    @PostMapping("/process")
    public ResponseEntity<String> triggerProcessing(@RequestBody List<File> files) {
        fileProcessingService.processFileList(files);
        return ResponseEntity.ok("文件处理已启动,完成后将收到通知");
    }
}

AngularJS 1.4 Client Setup

Make sure you have sockjs.min.js and stomp.min.js included in your project (use local copies, not external links). Then set up the client:

angular.module('fileProcessingApp', [])
.controller('FileCtrl', function($scope, $http) {
    var stompClient = null;

    // Initialize STOMP connection
    function connect() {
        var socket = new SockJS('/ws-stomp');
        stompClient = Stomp.over(socket);

        stompClient.connect({}, function(frame) {
            console.log('Connected to STOMP: ' + frame);
            
            // Subscribe to the completion notification topic
            stompClient.subscribe('/topic/file-process-complete', function(message) {
                // Wrap the update in $scope.$apply() to trigger Angular's digest loop
                $scope.$apply(function() {
                    $scope.notification = message.body;
                    // Add logic here to display result files
                });
            });

            // Optional: Subscribe to error notifications
            stompClient.subscribe('/topic/file-process-error', function(errorMsg) {
                $scope.$apply(function() {
                    $scope.error = errorMsg.body;
                });
            });
        }, function(error) {
            console.error('STOMP connection failed: ' + error);
            // Reconnect on failure (optional)
            setTimeout(connect, 5000);
        });
    }

    // Trigger file processing via REST API
    $scope.startProcessing = function() {
        $http.post('/api/files/process', $scope.fileList)
            .then(function(response) {
                console.log(response.data);
            })
            .catch(function(error) {
                console.error('Failed to start processing: ' + error);
            });
    };

    // Start connection on controller load
    connect();
});

Key Takeaways

  • Path Consistency: The topic path used in messagingTemplate.convertAndSend() must exactly match what the client subscribes to.
  • Spring Managed Beans: Never manually create instances of services that use SimpMessagingTemplate—let Spring handle injection.
  • Angular Digest Loop: Always wrap STOMP callback logic in $scope.$apply() to update the UI.
  • Async Processing: Run file processing in a separate thread to avoid blocking the HTTP request thread.

内容的提问来源于stack exchange,提问作者Dharita Chokshi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:38:04