服务器推送事件在Jersey SSE中无法工作

4
我正在尝试使用Jersey中的JavaScript SSE。 我在我的资源中有以下代码。 我正在Java7和Tomcat 7上托管。 我没有收到任何错误。 但是我也没有在页面上看到数据。
我调用/broadcast来发布数据。 它确实显示消息。 但客户端上没有任何内容。 在Firefox中,我确实看到多次触发/broadcast事件。
这是我使用的参考文献。 https://jersey.java.net/documentation/latest/sse.html
    package net.jigarshah.dse.tracker;

    import javax.inject.Singleton;
    import javax.ws.rs.Consumes;
    import javax.ws.rs.GET;
    import javax.ws.rs.POST;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;

    import org.glassfish.jersey.media.sse.EventOutput;
    import org.glassfish.jersey.media.sse.OutboundEvent;
    import org.glassfish.jersey.media.sse.SseBroadcaster;
    import org.glassfish.jersey.media.sse.SseFeature;


@Singleton
@Path("broadcast")
public class SSEResource {
    private SseBroadcaster broadcaster = new SseBroadcaster();

    @POST
    @Produces(MediaType.TEXT_PLAIN)
    @Consumes(MediaType.TEXT_PLAIN)    
    public String broadcastMessage(String message) {
        OutboundEvent.Builder eventBuilder = new OutboundEvent.Builder();
        message = message + "\n\n";
        OutboundEvent event = eventBuilder.name("message")
            .mediaType(MediaType.TEXT_PLAIN_TYPE)
            .data(String.class, message)
            .build();

        broadcaster.broadcast(event);
        System.out.println("broadcasting listen [" +message+ "]");

        return "Message was '" + message + "' broadcast.";
    }

    @GET
    @Produces(SseFeature.SERVER_SENT_EVENTS)
    public EventOutput listenToBroadcast() {
        System.out.println("will listen");
        final EventOutput eventOutput = new EventOutput();
        this.broadcaster.add(eventOutput);
        return eventOutput;
    }
}

我的Index.html代码如下所示。

<script type="text/javascript">
var url = "webapi/broadcast";
//var url="http://localhost:8080/trackapp/webapi/broadcast/listen";
var source=new EventSource(url);
source.onerror=function(event)
{
console.log("error [" + source.readyState + "]");
};

source.onopen = function(event){
    console.log("eventsource opened!");
    };

source.onmessage=function(event)
  {
    console.log(event.data);

  document.getElementById("result").innerHTML+=event.data + "<br>";
  };
</script>

你可以尝试在命令行上使用curl吗?有时浏览器会缓存响应。 - Salil
@Salil,您能否提供使用curl进行订阅的示例? - Jigar Shah
这是一个命令行实用程序,大多数Unix/Linux(包括Mac OS X)默认提供。http://www.thegeekstuff.com/2012/04/curl-examples/ - Salil
4个回答

9

我曾遇到同样的问题,通过不设置事件名称解决了这个问题(我不知道为什么,但这似乎是解决方案)…下面是代码

OutboundEvent.Builder eventBuilder = new OutboundEvent.Builder();

//WARNING: IF I SET THE NAME OF THE EVENT IT DOES NOT WORK
//eventBuilder.name("message"); 

eventBuilder.mediaType(MediaType.APPLICATION_JSON_TYPE);
eventBuilder.data(EventData.class, data);
OutboundEvent event = eventBuilder.build();

3
客户端在未发送命名事件时,会触发eventSource.onmessage处理程序。当设置了一个命名事件时,就应该设置eventSource.addEventListener('eventnamehere', function(ev){} - badunk

5
OutboundEvent.Builder.name 方法用于设置SSE事件字段的值。因此,它不被视为消息,无法使用 .onmessage 处理程序进行监听。解决方法是使用 addEventListener 方法注册监听器方法。

这段代码应该可以与上面的Jersey示例一起使用。

<script type="text/javascript">
    var url = "webapi/broadcast";
    var source=new EventSource(url);
    source.addEventListener(
        "message",
        function(event){
            console.log(event.data);
            document.getElementById("result").innerHTML+=event.data + "<br>"; },
        false);
</script>

我发现这篇文章很有用,可以帮助你理解浏览器端的SSE工作原理: http://www.sitepoint.com/server-sent-events/


2

第一个链接已失效,第二个链接返回503。 - svarog

1
我必须执行以下操作才能使它与Tomcat 7.0.69、Java 1.8和Jersey 2.22.2一起正常工作。如果有用的话,就分享出来吧。
  1. Add the following dependency in your Pom file :

      <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet-core</artifactId>
        <version>2.22.2</version>
      </dependency>
    
      <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-client</artifactId>
        <version>2.22.2</version>
      </dependency>
    <!-- If you use json -->
      <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-processing</artifactId>
        <version>2.22.2</version>
      </dependency>
    <dependency>
          <groupId>org.glassfish.jersey.containers</groupId>
          <!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core"  -->
          <artifactId>jersey-container-servlet</artifactId>
          <version>2.22.2</version>
        </dependency>
    
        <dependency>
          <groupId>org.glassfish.jersey.media</groupId>
          <artifactId>jersey-media-sse</artifactId>
          <version>2.22.2</version>
        </dependency>
    
  2. Needs to be servlet 3 so Heading of the web.xml should be like this : < ?xml version="1.0" encoding="UTF-8"? > < web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" >

  3. Jersey Servlet Container should be async-supported, so add it in the jersey servlet in the web.xml :

< async-supported>true< /async-supported>

  1. 如果您使用任何过滤器,请确保它也支持异步:

    < async-supported>true< /async-supported>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接