部署在Tomcat8服务器上时,WebSocket应用程序无法正常工作

时间:2016-04-21 20:53:49

标签: javascript java eclipse spring maven

问题

我尝试使用源代码中的最小更改来运行此示例:https://spring.io/guides/gs/messaging-stomp-websocket/

我已经设法使用Eclipse和Maven以及终端窗口再次使用maven运行它。我还设法将其打包成.war文件并使用java -jar myfile.war在终端中运行它在这些情况下按预期工作,即localhost:8080显示简单界面并连接并返回问候语同一个窗口。当我将.war文件部署到我在RaspberryPi上运行的tomcat8服务器时出现问题。在这种情况下,index.html会显示,但是" Connect"按钮什么都不做,这让我相信这是某种与javascript相关的问题。服务器工作正常,顺便说一句,我还有其他部署的东西。

我尝试的事情

  • 编辑.war存档,以便index.html和.js文件位于WEB-INF目录之外,以便外部世界可以访问它们。问题仍然存在。
  • 将index.html中的.js文件的脚本引用更改为



<script src="http://cdn.sockjs.org/sockjs-0.3.4.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.js"></script>
&#13;
&#13;
&#13;

以便它们可以通过CDN传递,以防.war文件出现任何问题。问题依然存在。

  • 为servlet添加了额外的功能,以便它在不同的目录中显示一些数据,以确保它有效,这不是.war文件的问题。看起来很好,但上述问题显然仍然存在。

代码

入口点

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

将回复问候语。

public class Greeting {

    private String content;

    public Greeting(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }
}

控制器

@Controller
public class GreetingController {


    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public Greeting greeting(HelloMessage message) throws Exception {
        Thread.sleep(3000); // simulated delay
        return new Greeting("Hello, " + message.getName() + "!");
    }

}

要发送的消息

public class HelloMessage {

    private String name;

    public String getName() {
        return name;
    }

}

WebSocket配置

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/hello").withSockJS();
    }

}

的index.html

&#13;
&#13;
<!DOCTYPE html>
<html>
<head>
    <title>Hello WebSocket</title>
    <script src="sockjs-0.3.4.js"></script>
    <script src="stomp.js"></script>
    <script>
        var stompClient = null;
        
        function setConnected(connected) {
            document.getElementById('connect').disabled = connected;
            document.getElementById('disconnect').disabled = !connected;
            document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
            document.getElementById('response').innerHTML = '';
        }
        
        function connect() {
            var socket = new SockJS('/hello');
            stompClient = Stomp.over(socket);            
            stompClient.connect({}, function(frame) {
                setConnected(true);
                console.log('Connected: ' + frame);
                stompClient.subscribe('/topic/greetings', function(greeting){
                    showGreeting(JSON.parse(greeting.body).content);
                });
            });
        }
        
        function disconnect() {
            if (stompClient != null) {
                stompClient.disconnect();
            }
            setConnected(false);
            console.log("Disconnected");
        }
        
        function sendName() {
            var name = document.getElementById('name').value;
            stompClient.send("/app/hello", {}, JSON.stringify({ 'name': name }));
        }
        
        function showGreeting(message) {
            var response = document.getElementById('response');
            var p = document.createElement('p');
            p.style.wordWrap = 'break-word';
            p.appendChild(document.createTextNode(message));
            response.appendChild(p);
        }
    </script>
</head>
<body onload="disconnect()">
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websocket relies on Javascript being enabled. Please enable
    Javascript and reload this page!</h2></noscript>
<div>
    <div>
        <button id="connect" onclick="connect();">Connect</button>
        <button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
    </div>
    <div id="conversationDiv">
        <label>What is your name?</label><input type="text" id="name" />
        <button id="sendName" onclick="sendName();">Send</button>
        <p id="response"></p>
    </div>
</div>
</body>
</html>
&#13;
&#13;
&#13;

的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>gs-messaging-stomp-websocket</artifactId>
    <version>0.1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-messaging</artifactId>
        </dependency>
    </dependencies>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <packaging>war</packaging>
</project>

从上次部署中记录

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.3.3.RELEASE)

2016-04-21 22:39:51.727  INFO 18022 --- [o-8080-exec-129] hello.Application                        : Starting Application on raspberrypi with PID 18022 (/var/lib/tomcat8/webapps/gs-messaging-stomp-websocket-0.1.0/WEB-INF/classes/hello/Application.class started by tomcat8 in /var/lib/tomcat8)
2016-04-21 22:39:51.800  INFO 18022 --- [o-8080-exec-129] hello.Application                        : No active profile set, falling back to default profiles: default
2016-04-21 22:39:52.752  INFO 18022 --- [o-8080-exec-129] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@167fc4: startup date [Thu Apr 21 22:39:52 EEST 2016]; root of context hierarchy
2016-04-21 22:40:09.630  INFO 18022 --- [o-8080-exec-129] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2016-04-21 22:40:16.208  INFO 18022 --- [o-8080-exec-129] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 23468 ms
2016-04-21 22:40:30.525  INFO 18022 --- [o-8080-exec-129] b.a.w.TomcatWebSocketContainerCustomizer : NonEmbeddedServletContainerFactory detected. Websockets support should be native so this normally is not a problem.
2016-04-21 22:40:40.343  INFO 18022 --- [o-8080-exec-129] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2016-04-21 22:40:40.360  INFO 18022 --- [o-8080-exec-129] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'errorPageFilter' to: [/*]
2016-04-21 22:40:40.363  INFO 18022 --- [o-8080-exec-129] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'characterEncodingFilter' to: [/*]
2016-04-21 22:40:40.366  INFO 18022 --- [o-8080-exec-129] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2016-04-21 22:40:40.369  INFO 18022 --- [o-8080-exec-129] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2016-04-21 22:40:40.372  INFO 18022 --- [o-8080-exec-129] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'requestContextFilter' to: [/*]
2016-04-21 22:40:41.904  INFO 18022 --- [o-8080-exec-129] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService  'clientInboundChannelExecutor'
2016-04-21 22:40:42.137  INFO 18022 --- [o-8080-exec-129] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService  'clientOutboundChannelExecutor'
2016-04-21 22:40:42.743  INFO 18022 --- [o-8080-exec-129] o.s.s.c.ThreadPoolTaskScheduler          : Initializing ExecutorService  'messageBrokerTaskScheduler'
2016-04-21 22:40:44.228  INFO 18022 --- [o-8080-exec-129] o.s.w.s.s.s.WebSocketHandlerMapping      : Mapped URL path [/hello/**] onto handler of type [class org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler]
2016-04-21 22:40:44.635  INFO 18022 --- [o-8080-exec-129] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService  'brokerChannelExecutor'
2016-04-21 22:40:49.712  INFO 18022 --- [o-8080-exec-129] .WebSocketAnnotationMethodMessageHandler : Mapped "{[/hello],messageType=[MESSAGE]}" onto public hello.Greeting hello.GreetingController.greeting(hello.HelloMessage) throws java.lang.Exception
2016-04-21 22:40:57.059  INFO 18022 --- [o-8080-exec-129] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@167fc4: startup date [Thu Apr 21 22:39:52 EEST 2016]; root of context hierarchy
2016-04-21 22:40:58.966  INFO 18022 --- [o-8080-exec-129] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2016-04-21 22:40:58.993  INFO 18022 --- [o-8080-exec-129] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2016-04-21 22:40:59.092  INFO 18022 --- [o-8080-exec-129] o.s.w.s.c.a.WebMvcConfigurerAdapter      : Adding welcome page: ServletContext resource [/index.html]
2016-04-21 22:40:59.622  INFO 18022 --- [o-8080-exec-129] o.s.w.s.handler.SimpleUrlHandlerMapping  : Root mapping to handler of type [class org.springframework.web.servlet.mvc.ParameterizableViewController]
2016-04-21 22:40:59.948  INFO 18022 --- [o-8080-exec-129] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-04-21 22:40:59.950  INFO 18022 --- [o-8080-exec-129] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-04-21 22:41:01.167  INFO 18022 --- [o-8080-exec-129] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-04-21 22:41:06.289  INFO 18022 --- [o-8080-exec-129] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2016-04-21 22:41:06.561  INFO 18022 --- [o-8080-exec-129] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147483647
2016-04-21 22:41:06.570  INFO 18022 --- [o-8080-exec-129] o.s.m.s.b.SimpleBrokerMessageHandler     : Starting...
2016-04-21 22:41:06.578  INFO 18022 --- [o-8080-exec-129] o.s.m.s.b.SimpleBrokerMessageHandler     : BrokerAvailabilityEvent[available=true, SimpleBrokerMessageHandler [DefaultSubscriptionRegistry[cache[0 destination(s)], registry[0 sessions]]]]
2016-04-21 22:41:06.597  INFO 18022 --- [o-8080-exec-129] o.s.m.s.b.SimpleBrokerMessageHandler     : Started.
2016-04-21 22:41:06.830  INFO 18022 --- [o-8080-exec-129] hello.Application                        : Started Application in 93.812 seconds (JVM running for 2602144.954)
Apr 21, 2016 10:41:07 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deployment of web application archive /var/lib/tomcat8/webapps/gs-messaging-stomp-websocket-0.1.0.war has finished in 137,294 ms
2016-04-21 22:41:31.098  INFO 18022 --- [o-8080-exec-131] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2016-04-21 22:41:31.455  INFO 18022 --- [o-8080-exec-131] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 355 ms
2016-04-21 22:41:44.554  INFO 18022 --- [MessageBroker-1] o.s.w.s.c.WebSocketMessageBrokerStats    : WebSocketSession[0 current WS(0)-HttpStream(0)-HttpPoll(0), 0 total, 0 closed abnormally (0 connect failure, 0 send limit, 0 transport error)], stompSubProtocol[processed CONNECT(0)-CONNECTED(0)-DISCONNECT(0)], stompBrokerRelay[null], inboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], outboundChannelpool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], sockJsScheduler[pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]
2016-04-21 23:11:44.549  INFO 18022 --- [MessageBroker-1] o.s.w.s.c.WebSocketMessageBrokerStats    : WebSocketSession[0 current WS(0)-HttpStream(0)-HttpPoll(0), 0 total, 0 closed abnormally (0 connect failure, 0 send limit, 0 transport error)], stompSubProtocol[processed CONNECT(0)-CONNECTED(0)-DISCONNECT(0)], stompBrokerRelay[null], inboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], outboundChannelpool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], sockJsScheduler[pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 1]
2016-04-21 23:41:44.549  INFO 18022 --- [MessageBroker-1] o.s.w.s.c.WebSocketMessageBrokerStats    : WebSocketSession[0 current WS(0)-HttpStream(0)-HttpPoll(0), 0 total, 0 closed abnormally (0 connect failure, 0 send limit, 0 transport error)], stompSubProtocol[processed CONNECT(0)-CONNECTED(0)-DISCONNECT(0)], stompBrokerRelay[null], inboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], outboundChannelpool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], sockJsScheduler[pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 2]

链接到我的.war文件

http://s000.tinyupload.com/index.php?file_id=67742984079178858914

最后的想法

同样,通过消除过程,.js库不能正确导入,或者我的服务器的WebSocket支持有问题。我真的坚持这个,任何和所有的帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

所以基本上可能发生的事情是,一旦你部署到服务,你的所有路径都有点偏离,所以假设你有链接说 <a href="/home" > home </a>它可以在本地工作,但不能在服务器上运行,因为您的应用程序URL现在是主机:8080 / appName /当您使用/ home引用任何内容而不是将您带到主机时:8080 / appName / home it将带你去主持:8080 / home,此时它是一个破碎的网址。所以我认为你可以通过改变这里的/你好来解决你的问题

 function connect() {
            var socket = new SockJS('hello');
            stompClient = Stomp.over(socket);            
            stompClient.connect({}, function(frame) {
                setConnected(true);
                console.log('Connected: ' + frame);
                stompClient.subscribe('/topic/greetings', function(greeting){
                    showGreeting(JSON.parse(greeting.body).content);
                });
            });
        }

答案 1 :(得分:0)

我试过弹簧指南示例,它与Google Chrome版本54.0.2840.100(64位)完美搭配

链接:https://github.com/spring-guides/gs-messaging-stomp-websocket/tree/master/complete

当我很快看到时,我发现你错过了下面的依赖

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>webjars-locator</artifactId>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>sockjs-client</artifactId>
    <version>1.0.2</version>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>stomp-websocket</artifactId>
    <version>2.3.3</version>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>bootstrap</artifactId>
    <version>3.3.7</version>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.1.0</version>
</dependency>