Angularjs WebSocketServerSockJsSession中的传输错误-无法在Spring Stomp websocket上加载平台配置程序

Angularjs WebSocketServerSockJsSession中的传输错误-无法在Spring Stomp websocket上加载平台配置程序,angularjs,spring-websocket,Angularjs,Spring Websocket,我正在尝试向AngularJS应用程序添加web套接字 我在服务器上使用Spring4设置web套接字,在客户端使用StompSockJS 我在http://localhost:9000/#/project/1/bts发出咕噜声发球命令后 但我在进行web套接字握手时得到500响应: WebSocket connection to 'ws://localhost:8080/nitro-project-rest/api/socket/bts/405/bmtcztq4/websocket' fail

我正在尝试向AngularJS应用程序添加web套接字

我在服务器上使用Spring4设置web套接字,在客户端使用StompSockJS

我在
http://localhost:9000/#/project/1/bts
发出
咕噜声发球
命令后

但我在进行web套接字握手时得到500响应:

WebSocket connection to 'ws://localhost:8080/nitro-project-rest/api/socket/bts/405/bmtcztq4/websocket' failed: Error during WebSocket handshake: Unexpected response code: 500
对于每个失败的websocket请求,服务器都会这样说:

SEVERE: Servlet.service() for servlet [NITRo] in context with path [/nitro-project-rest] threw exception [Request processing failed; nested exception is org.springframework.web.socket.sockjs.SockJsException: Uncaught failure in SockJS request, uri=http://localhost:8080/nitro-project-rest/api/socket/bts/970/2xoe6kls/websocket; nested exception is org.springframework.web.socket.sockjs.SockJsTransportFailureException: WebSocket handshake failure; nested exception is java.lang.RuntimeException: Cannot load platform configurator] with root cause
java.lang.RuntimeException: Cannot load platform configurator
有关错误的详细信息:

2017-02-06 10:36:04,241 DEBUG [http-bio-8080-exec-10] o.s.w.s.h.LoggingWebSocketHandlerDecorator Transport error in WebSocketServerSockJsSession[id=nqj286ob]
 java.lang.RuntimeException: Cannot load platform configurator
    at javax.websocket.server.ServerEndpointConfig$Configurator.fetchContainerDefaultConfigurator(ServerEndpointConfig.java:123)
    at javax.websocket.server.ServerEndpointConfig$Configurator.getContainerDefaultConfigurator(ServerEndpointConfig.java:128)
    at javax.websocket.server.ServerEndpointConfig$Configurator.checkOrigin(ServerEndpointConfig.java:192)
有趣的是推送通知工作正常。当预期事件发生时,我可以看到网页正在实时更新。因此,尽管有这个例外,我的websocket工作正常。此异常发生在页面加载时

手动键入url时:

http://localhost:8080/nitro-project-rest/api/socket/bts
在Chromium web浏览器中显示:欢迎使用SockJS

以下是我的web套接字连接服务:

function StompService(endpoint) {
  this.stompClient = Stomp.client(ENV.NITRO_PROJECT_WS_URL + '/socket/' + endpoint);
}

StompService.prototype.connect = function(onConnect, onError) {
  this.stompClient.connect({}, function(frame) {
    $rootScope.$apply(function() {
      onConnect.apply(stompClient, frame);
    });
  }, function(frame) {
    $rootScope.$apply(function() {
      onError.apply(stompClient, frame);
    });
  }, '/');
};
以及控制器:

var stomp = new SocketService(BTS_WS_ENDPOINT);
stomp.connect(function() {
  $scope.client.subscribe('status', function(message) {
    $scope.messages.push(message.body);
  });
}, function() {
});
@Configuration
@EnableWebSocketMessageBroker
@ComponentScan(basePackages = "com.nsn.nitro.project.rest.socket")
public class WebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // Prefix for destinations towards the server
        config.setApplicationDestinationPrefixes("/app");
        // Prefix for destinations towards the client
        config.enableSimpleBroker("/topic");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // All controllers need to be added to the endpoint registry
        registry.addEndpoint("/socket/bts").withSockJS();
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
    }

    @Override
    public void configureClientOutboundChannel(ChannelRegistration registration) {
        registration.taskExecutor().corePoolSize(4).maxPoolSize(10);
    }

}

@Controller
public class BTSSocketController {

    private static Logger logger = LoggerFactory.getLogger(BTSSocketController.class);

    @MessageMapping("/socket/bts")
    @SendTo("/topic/status")
    public BTSMessage status(BTSMessage message) throws Exception {
        logger.debug("==========>> Received the message " + message.getBtsId());
        message.setStatus(BTSStatus.ONAIR);
        return message;
    }

}
使用服务器端配置和控制器:

var stomp = new SocketService(BTS_WS_ENDPOINT);
stomp.connect(function() {
  $scope.client.subscribe('status', function(message) {
    $scope.messages.push(message.body);
  });
}, function() {
});
@Configuration
@EnableWebSocketMessageBroker
@ComponentScan(basePackages = "com.nsn.nitro.project.rest.socket")
public class WebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // Prefix for destinations towards the server
        config.setApplicationDestinationPrefixes("/app");
        // Prefix for destinations towards the client
        config.enableSimpleBroker("/topic");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // All controllers need to be added to the endpoint registry
        registry.addEndpoint("/socket/bts").withSockJS();
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
    }

    @Override
    public void configureClientOutboundChannel(ChannelRegistration registration) {
        registration.taskExecutor().corePoolSize(4).maxPoolSize(10);
    }

}

@Controller
public class BTSSocketController {

    private static Logger logger = LoggerFactory.getLogger(BTSSocketController.class);

    @MessageMapping("/socket/bts")
    @SendTo("/topic/status")
    public BTSMessage status(BTSMessage message) throws Exception {
        logger.debug("==========>> Received the message " + message.getBtsId());
        message.setStatus(BTSStatus.ONAIR);
        return message;
    }

}
我使用基本身份验证和以下配置运行Spring Security:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.addFilterBefore(simpleCORSFilter, ChannelProcessingFilter.class);      

    http
    .csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    .and().httpBasic().authenticationEntryPoint(restAuthenticationEntryPoint)
    .and().authorizeRequests().antMatchers("/socket/**").permitAll()
    .and().authorizeRequests().antMatchers("/resources/**").permitAll()
    .and().authorizeRequests().antMatchers(RESTConstants.SLASH + RESTConstants.ADMINS + RESTConstants.SLASH + RESTConstants.LOGIN).permitAll()
    .and().authorizeRequests().antMatchers("/**").hasRole("ADMIN").anyRequest().authenticated();
}

@Component
public class SimpleCORSFilter implements Filter {

    private static final String ORIGIN = "Origin";
    private static final String OPTIONS = "OPTIONS";
    private static final String OK = "OK";

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;

        if (httpServletRequest.getHeader(ORIGIN) != null) {
            String origin = httpServletRequest.getHeader(ORIGIN);
            httpServletResponse.setHeader("Access-Control-Allow-Origin", origin);
            httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
            httpServletResponse.setHeader("Access-Control-Max-Age", "3600");
            httpServletResponse.setHeader("Access-Control-Allow-Headers", "Accept-Language,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,X-Filename,Content-Disposition,Content-Length");
            // Allow more than the 6 default headers to be returned, as the content length is required for a download file request to get the file size 
            httpServletResponse.setHeader("Access-Control-Expose-Headers", "Accept-Language,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,X-Filename,Content-Disposition,Content-Length");
        }

        if (httpServletRequest.getMethod().equals(OPTIONS)) {
            try {
                httpServletResponse.getWriter().print(OK);
                httpServletResponse.getWriter().flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            filterChain.doFilter(servletRequest, servletResponse);
        }       
    }

    public void init(FilterConfig filterConfig) {
    }

    public void destroy() {
    }

}
我的Java依赖项是:

[INFO] +- javax.websocket:javax.websocket-api:jar:1.1:provided
[INFO] +- org.springframework:spring-web:jar:4.3.6.RELEASE:compile
[INFO] +- org.springframework:spring-webmvc:jar:4.3.6.RELEASE:compile
[INFO] +- org.springframework:spring-test:jar:4.3.6.RELEASE:compile
[INFO] +- org.springframework:spring-messaging:jar:4.3.6.RELEASE:compile
[INFO] +- org.springframework:spring-websocket:jar:4.3.6.RELEASE:compile
"sockjs": "~0.3.4",
"stomp-websocket": "~2.3.4",
我的Js依赖项是:

[INFO] +- javax.websocket:javax.websocket-api:jar:1.1:provided
[INFO] +- org.springframework:spring-web:jar:4.3.6.RELEASE:compile
[INFO] +- org.springframework:spring-webmvc:jar:4.3.6.RELEASE:compile
[INFO] +- org.springframework:spring-test:jar:4.3.6.RELEASE:compile
[INFO] +- org.springframework:spring-messaging:jar:4.3.6.RELEASE:compile
[INFO] +- org.springframework:spring-websocket:jar:4.3.6.RELEASE:compile
"sockjs": "~0.3.4",
"stomp-websocket": "~2.3.4",

为了帮助其他在搜索“欢迎使用SockJS”错误时偶然发现此错误的人:如果您试图使用常规websocket连接连接到SockJS地址,请在url末尾添加/websocket。

调用this.stompClient=Stomp.client(ENV.NITRO_PROJECT_WS_URL+'/socket/'是一个问题,因为它需要一个WS://URL。我将它更改为调用var socket=new SockJS(ENV.NITRO_PROJECT_REST_URL+'/socket/'+endpoint);this.stompClient=Stomp.over(socket);到http://url,现在一切都好了。你会有一个完整url的示例吗?我尝试向url添加
/websocket
后缀,但没有改变错误。我在春季升级后更新了我的问题。现在发送的url显示了框架自动添加的
bmtcztq4/websocket
。不过,我得到了500分。