我编写了一个基本的Java应用程序来使用Jersey SSE客户端来消费从Node.js服务器流式传输的SSE(服务器发送的事件)。但是,我无法收到这些活动。为了验证服务器组件是否按预期工作,我使用了curl
,如下所示:
curl -v -H "Accept: text/event-stream" http://localhost:8080/events/
我收到以下回复:
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /events/ HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: text/event-stream
>
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: text/event-stream
< Cache-Control: no-cache
< Connection: keep-alive
< Date: Wed, 26 Apr 2017 17:12:00 GMT
< Transfer-Encoding: chunked
<
event: ping
data: 0.6637400726922664
event: ping
data: 0.8538157046725585
我的SSE客户端在Java中的代码如下(Java 8,Jersey Client 1.19.3,Jersey Media SSE 2.25.1):
import org.glassfish.jersey.media.sse.EventListener;
import org.glassfish.jersey.media.sse.EventSource;
import org.glassfish.jersey.media.sse.InboundEvent;
import org.glassfish.jersey.media.sse.SseFeature;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
public class NodeCaptureSSE {
public static void main(String[] args) {
Client client = ClientBuilder.newBuilder().register(SseFeature.class).build();
WebTarget target = client.target("http://localhost:8080/events/");
EventSource eventSource = EventSource.target(target).build();
EventListener listener = new EventListener() {
@Override
public void onEvent(InboundEvent inboundEvent) {
System.out.println(inboundEvent.getName() + "; " + inboundEvent.readData(String.class));
}
};
eventSource.register(listener, "ping");
eventSource.open();
System.out.println("Connected to SSE source...");
try {
Thread.sleep(25_000);
}
catch (InterruptedException ie) {
System.err.println("Exception: " + ie.getMessage());
}
eventSource.close();
System.out.println("Closed connection to SSE source");
}
}
我在屏幕上看到的唯一输出是:
Connected to SSE source...
然后在25秒后退出。由于服务器是流式命名事件(“ping”),我在将侦听器注册到事件源时指定了该事件。将第二个参数省略到eventSource.register(...);
没有做任何事情,虽然我没想到。我还删除了网址中的结尾/
,但这会产生404 Not Found
(如预期的那样)。我希望能找到正确的方向。
答案 0 :(得分:3)
您的代码对我来说很好。事实上,我正在拼命寻找这个代码所以谢谢^ _ ^ hahaha。无论如何,我有一个SSE事件流输出时间事件,这是我的输出看起来像你的代码(我改变ping到时间事件连接到我的服务器)。
Connected to SSE source...
time-event; Time is Thu Jul 20 10:10:37 CDT 2017
time-event; Time is Thu Jul 20 10:10:41 CDT 2017
问题很可能在于您的事件流和您用来指向它的URL,而不是您的客户端Java代码。我注意到的另一件事是,在你的curl命令中,我没有看到那里的字符集规范。确保您的字符集设置为UTF-8。这是我的cmd输出的样子:
以下是我用来制作流的代码。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.http.HTTPException;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.PasswordAuthentication;
import java.util.Calendar;
@SuppressWarnings("java.io.IOException")
@WebServlet("/SSEServlet")
public class SSEServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private boolean cancel;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {
System.out.println("You just entered the doGetMethod");
response.setContentType("text/event-stream");
response.setCharacterEncoding("UTF-8");
PrintWriter printWriter = null;
response.getBufferSize();
while(true){
try{
System.out.println("You just entered the while loop");
double randomNumber = Math.random()*10000;
printWriter = response.getWriter();
printWriter.print("event: time-event" + "\n");
printWriter.print("data: " + "Time is " + Calendar.getInstance().getTime() + "\n\n");
response.flushBuffer();
Thread.sleep((long)randomNumber);
} catch (IOException | InterruptedException e){
e.printStackTrace();
break;
}
}
System.out.println("Connection was aborted");
}
}
答案 1 :(得分:0)
如果您的应用程序是Spring Boot应用程序,则存在Jersey的兼容性问题。您需要添加另一个依赖项org.glassfish.jersey.inject:jersey-hk2:2.26来解决此问题。
请参阅 https://github.com/bmuschko/gradle-docker-plugin/issues/534 https://github.com/jersey/jersey/issues/3664
似乎不仅与Gradle有关。就我而言,我的项目是Maven和Spring Boot应用程序,添加此依赖项后,我立即收到事件。