Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何过滤Jersey SSE中的事件?_Java_Jersey_Server Sent Events - Fatal编程技术网

Java 如何过滤Jersey SSE中的事件?

Java 如何过滤Jersey SSE中的事件?,java,jersey,server-sent-events,Java,Jersey,Server Sent Events,在查看jersey sse示例时,我在jersey示例文件夹中找到了一个示例sse item store webapp。这是一个非常简单的应用程序,有一个输入和一个按钮。您键入一些文本,单击按钮,其他人将得到更改 @Path("items") public class ItemStoreResource { private static final ReentrantReadWriteLock storeLock = new ReentrantReadWriteLock();

在查看jersey sse示例时,我在jersey示例文件夹中找到了一个示例sse item store webapp。这是一个非常简单的应用程序,有一个输入和一个按钮。您键入一些文本,单击按钮,其他人将得到更改

@Path("items")
public class ItemStoreResource {

    private static final ReentrantReadWriteLock storeLock = new ReentrantReadWriteLock();
    private static final LinkedList<String> itemStore = new LinkedList<String>();
    private static final SseBroadcaster broadcaster = new SseBroadcaster();

    private static volatile long reconnectDelay = 0;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String listItems() {
        try {
            storeLock.readLock().lock();
            return itemStore.toString();
        } finally {
            storeLock.readLock().unlock();
        }
    }

    @GET
    @Path("events")
    @Produces(SseFeature.SERVER_SENT_EVENTS)
    public EventOutput itemEvents(@HeaderParam(SseFeature.LAST_EVENT_ID_HEADER) @DefaultValue("-1") int lastEventId) {
        final EventOutput eventOutput = new EventOutput();


        if (lastEventId >= 0) {
            LOGGER.info("Received last event id :" + lastEventId);

            // decide the reconnect handling strategy based on current reconnect delay value.
            final long delay = reconnectDelay;
            if (delay > 0) {
                LOGGER.info("Non-zero reconnect delay [" + delay + "] - responding with HTTP 503.");
                throw new ServiceUnavailableException(delay);
            } else {
                LOGGER.info("Zero reconnect delay - reconnecting.");
                replayMissedEvents(lastEventId, eventOutput);
            }
        }


        if (!broadcaster.add(eventOutput)) {
            LOGGER.severe("!!! Unable to add new event output to the broadcaster !!!");
            // let's try to force a 5s delayed client reconnect attempt
            throw new ServiceUnavailableException(5L);
        }

        return eventOutput;
    }

    private void replayMissedEvents(final int lastEventId, final EventOutput eventOutput) {
        try {
            storeLock.readLock().lock();
            final int firstUnreceived = lastEventId + 1;
            final int missingCount = itemStore.size() - firstUnreceived;
            if (missingCount > 0) {
                LOGGER.info("Replaying events - starting with id " + firstUnreceived);
                final ListIterator<String> it = itemStore.subList(firstUnreceived, itemStore.size()).listIterator();
                while (it.hasNext()) {
                    eventOutput.write(createItemEvent(it.nextIndex() + firstUnreceived, it.next()));
                }
            } else {
                LOGGER.info("No events to replay.");
            }
        } catch (IOException ex) {
            throw new InternalServerErrorException("Error replaying missed events", ex);
        } finally {
            storeLock.readLock().unlock();
        }
    }

    @POST
    public void addItem(@FormParam("name") String name) {
        // Ignore if the request was sent without name parameter.
        if (name == null) {
            return;
        }

        final int eventId;
        try {
            storeLock.writeLock().lock();
            eventId = itemStore.size();
            itemStore.add(name);

            // Broadcasting an un-named event with the name of the newly added item in data
            broadcaster.broadcast(createItemEvent(eventId, name));
            // Broadcasting a named "size" event with the current size of the items collection in data
            broadcaster.broadcast(new OutboundEvent.Builder().name("size").data(Integer.class, eventId + 1).build());

        } finally {
            storeLock.writeLock().unlock();
        }
    }

    private OutboundEvent createItemEvent(final int eventId, final String name) {
        Logger.getLogger(ItemStoreResource.class.getName()).info("Creating event id [" + eventId + "] name [" + name + "]");
        return new OutboundEvent.Builder().id("" + eventId).data(String.class, name).build();
    }
}
@Path(“项目”)
公共类ItemStoreResource{
私有静态最终ReentrantReadWriteLock storeLock=new ReentrantReadWriteLock();
私有静态最终LinkedList itemStore=新LinkedList();
专用静态最终SSE广播电台=新SSE广播电台();
专用静态易失性长重连延迟=0;
@得到
@生成(MediaType.TEXT\u PLAIN)
公共字符串listItems(){
试一试{
storeLock.readLock().lock();
返回itemStore.toString();
}最后{
storeLock.readLock().unlock();
}
}
@得到
@路径(“事件”)
@产生(SseFeature.SERVER\u SENT\u事件)
public EventOutput itemEvents(@HeaderParam(SseFeature.LAST_EVENT_ID_HEADER)@DefaultValue(“-1”)int-lastEventId){
final EventOutput EventOutput=新的EventOutput();
如果(lastEventId>=0){
LOGGER.info(“收到的上一个事件id:+lastEventId”);
//根据当前重新连接延迟值确定重新连接处理策略。
最终长延迟=重新连接延迟;
如果(延迟>0){
info(“非零重新连接延迟[“+延迟+”]-用HTTP503响应”);
抛出新的ServiceUnavailableException(延迟);
}否则{
info(“零重新连接延迟-重新连接”);
replayMissedEvents(lastEventId、eventOutput);
}
}
如果(!broadcaster.add(eventOutput)){
LOGGER.severe(!!!无法将新事件输出添加到广播程序!!!);
//让我们尝试强制5s延迟的客户端重新连接尝试
抛出新的ServiceUnavailableException(5L);
}
返回事件输出;
}
私有void replayMissedEvents(final int lastEventId,final EventOutput EventOutput){
试一试{
storeLock.readLock().lock();
final int firstUnreceived=lastEventId+1;
final int missingCount=itemStore.size()-firstUnreceived;
如果(丢失计数>0){
info(“重放事件-从id开始”+firstUnreceived);
final ListIterator it=itemStore.subList(firstUnreceived,itemStore.size()).ListIterator();
while(it.hasNext()){
write(createItemEvent(it.nextIndex()+firstUnreceived,it.next());
}
}否则{
info(“没有要重播的事件”);
}
}捕获(IOEX异常){
抛出新的InternalServerErrorException(“错误重放错过的事件”,ex);
}最后{
storeLock.readLock().unlock();
}
}
@职位
public void addItem(@FormParam(“name”)字符串名){
//如果发送的请求没有name参数,则忽略。
if(name==null){
返回;
}
最终int事件ID;
试一试{
storeLock.writeLock().lock();
eventId=itemStore.size();
itemStore.add(名称);
//使用数据中新添加项的名称广播未命名事件
广播(createItemEvent(eventId,名称));
//使用数据中项集合的当前大小广播命名的“大小”事件
broadcast.broadcast(新的OutboundEvent.Builder().name(“size”).data(Integer.class,eventId+1.build());
}最后{
storeLock.writeLock().unlock();
}
}
私有OutboundEvent createItemEvent(最终int eventId,最终字符串名称){
Logger.getLogger(ItemStoreResource.class.getName()).info(“创建事件id[“+eventId+”]name[“+name+”]);
返回新的OutboundEvent.Builder().id(“+eventId).data(String.class,name).build();
}
}
例如,如果我有一个聊天室,我不知道如何使用SSE实现这一点,因为每个客户端都连接到
/items/events
,如果有人将新消息发布到某个聊天室
播音员
将此消息广播到所有已签名的事件,但我只希望广播某些聊天室的事件


谁与Jersey SSE合作?你能建议如何实现这一点吗?

试着使用smth,就像一个带有聊天室ID的地图,将SseBroadcast对象映射到SseBroadcast对象,然后你可以将某个房间的所有用户订阅给广播公司。您可以将其用作tet-a-tet对话或团队对话

样本如下:

private static final Map<Long, SseBroadcaster> ROOM_SSE_BROADCASTER = new ConcurrentHashMap<>();

@GET
@Path("/updatestate/{roomId}/{userId}")
@Produces(SseFeature.SERVER_SENT_EVENTS)
public EventOutput updateState(@PathParam("roomId") Long roomId, @PathParam("userId") Long userId) {
    EventOutput eo = new EventOutput();
    ROOM_SSE_BROADCASTER.get(roomId).add(eo);

    return eo;
}

public static void updateRoom(Long roomId) {
    ROOM_SSE_BROADCASTER.get(roomId).broadcast(buildEvent());
}

public static void registerRoom(Long roomId) {
    ROOM_SSE_BROADCASTER.put(roomId, new SseBroadcaster());
}

private static OutboundEvent buildEvent() {
    OutboundEvent.Builder builder = new OutboundEvent.Builder();
    OutboundEvent event = builder.data(String.class, "update").build();

    return event;
}
private static final Map ROOM_SSE_BROADCASTER=new ConcurrentHashMap();
@得到
@路径(“/updatestate/{roomId}/{userId}”)
@产生(SseFeature.SERVER\u SENT\u事件)
public EventOutput updateState(@PathParam(“roomId”)Long roomId,@PathParam(“userId”)Long userId){
EventOutput eo=新的EventOutput();
ROOM_SSE_播音员。获取(roomId)。添加(eo);
返回eo;
}
公共静态无效更新eRoom(长roomId){
ROOM_SSE_BROADCASTER.get(roomId.broadcast)(buildEvent());
}
公共静态无效注册表项(长roomId){
ROOM_SSE_播音员.put(roomId,新SSE播音员());
}
私有静态OutboundEvent buildEvent(){
OutboundEvent.Builder=新建OutboundEvent.Builder();
OutboundEvent=builder.data(String.class,“update”).build();
返回事件;
}