Spring Websockets无法在自定义应用程序上下文路径下工作

时间:2017-02-14 20:49:33

标签: java spring jsp spring-mvc spring-websocket

我有使用Spring 4.3.5和spring mvc - apache tiles的应用程序。

我根据这篇文章https://spring.io/guides/gs/messaging-stomp-websocket/

写了聊天

如果我的整个应用程序上下文路径都是root,那么一切都正常工作,例如:http://example.com/我收到websocket中的以下框架

["SUBSCRIBE\nid:sub-0\ndestination:/chat-messages/TST\n\n\u0000"]
["SEND\ndestination:/chat/message/TST\ncontent-length:52\n\n{\"message\":\"\",\"username\":\"USER\",\"event\":\"ONLINE\"}\u0000"]
["MESSAGE\ndestination:/chat-messages/TST\ncontent-type:application/json;charset=UTF-8\nsubscription:sub-0\nmessage-id:x1jpjyes-1\ncontent-length:230\n\n{..SOME JSON CONTENT....}\u0000"]

问题是它停止工作,如果我添加一些应用程序上下文(我需要在我的服务器上这样做) 例如:http://example.com/my-app 没有收到消息,也没有发送

UPDATE:通过将servletContext.getContextPath()添加到目标前缀来修复发送。

在上下文中,我只有这个:

["SUBSCRIBE\nid:sub-0\ndestination:/my-app/chat-messages/TST\n\n\u0000"]
["SEND\ndestination:/my-app/chat/message/TST\ncontent-length:52\n\n{\"message\":\"\",\"username\":\"USER\",\"event\":\"ONLINE\"}\u0000"]

以下是我的配置:

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
    private static final String TILES = "/WEB-INF/tiles/tiles.xml";
    private static final String VIEWS = "/WEB-INF/views/**/views.xml";
    private static final String RESOURCES_HANDLER = "/resources/";
    private static final String RESOURCES_LOCATION = RESOURCES_HANDLER + "**";

    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping requestMappingHandlerMapping = super
            .requestMappingHandlerMapping();
        requestMappingHandlerMapping.setUseSuffixPatternMatch(false);
        requestMappingHandlerMapping.setUseTrailingSlashMatch(false);
        return requestMappingHandlerMapping;
        }

    @Bean
    public TilesViewResolver configureTilesViewResolver() {
        return new TilesViewResolver();
    }

    @Bean
    public TilesConfigurer configureTilesConfigurer() {
        TilesConfigurer configurer = new TilesConfigurer();
        configurer.setDefinitions(TILES, VIEWS);
        return configurer;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(RESOURCES_HANDLER).addResourceLocations(
                RESOURCES_LOCATION);
    }

    @Override
    public void configureDefaultServletHandling(
        DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

WebSocketMesssageBroker

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{

    @Autowired
    private ServletContext servletContext;

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/chat-messages");
        config.setApplicationDestinationPrefixes(servletContext.getContextPath() + "/chat");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/chat-websocket").withSockJS();
    }
}

我有一个控制器来处理所有事情

@MessageMapping("/message/{projectId}")
@SendTo("/chat-messages/{projectId}")
public ChatResponse sendMessage(@DestinationVariable String projectId, MessageSent message) throw InterruptedException {

//Send reponse back like user online/offline or message posted 
return new ChatResponse(chatMessage);

}

在JSP文件中,我有一个名为

的JS
var socket = new SockJS('<c:url value="/chat-websocket/"/>');

stompClient.subscribe('<c:url value="/chat-messages/${chatProject.projectId}"/>', function (data) { ....SOME RESPONSE PROCESSING... });

stompClient.send("<c:url value="/chat/message/${chatProject.projectId}"/>", {}, JSON.stringify({.....PAYLOAD TO SEND ---}));

和web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <error-page>
        <exception-type>org.springframework.security.web.authentication.rememberme.CookieTheftException</exception-type>
        <location>/signin</location>
    </error-page>
    <error-page>
        <location>/generalError</location>
    </error-page>
    <error-page>
        <error-code>404</error-code>
        <location>/404</location>
    </error-page>
    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <trim-directive-whitespaces>true</trim-directive-whitespaces>
        </jsp-property-group>
    </jsp-config>
</web-app>

我怀疑这可能是在web.xml中配置tile或整个调度程序的东西,或者类似这样的东西:/

提示非常棒

1 个答案:

答案 0 :(得分:0)

我完全有能力解决这个问题。事实证明,每当我创建SockJS订阅者时,我都应该将相对路径作为参数传递,而不需要任何上下文

(我假设基础websocket打开的url已经有正确的url)

因此,为了正确接收订阅活动,我所要做的就是改变

 stompClient.subscribe('<c:url value="/chat-messages/${chatProject.projectId}"/>', function (data) { ....SOME RESPONSE PROCESSING... });

到此:

 stompClient.subscribe('/chat-messages/${chatProject.projectId}', function (data) { ....SOME RESPONSE PROCESSING... });

(没有始终返回上下文路径的&lt; c:url&gt;

因此,每当我尝试使用

<c:url value="chat-messages/ID">
订阅聊天消息时,实际上我订阅了:
my-app/chat-messages/ID
我的控制器和配置期待普通的相对聊天消息

这就是为什么在将contextPath添加到WebSocketController setApplicationDestinationPrefixes之后,app开始发送正确的消息

那些几个小时我都没有回来:)