Java 使用SSE触发和输出事件

Java 使用SSE触发和输出事件,java,jersey-2.0,server-sent-events,Java,Jersey 2.0,Server Sent Events,我是新来使用SSE与泽西,并有以下情况 我有一个JAXB注释类,它表示并作用于Raspberry Pi(类GpioRepresentation)的I/O 客户机类通过返回XML对象的getUpdate()方法访问I/O的状态 类的表示 @XmlRootElement public class GpioRepresentation implements GpioSubject { ... /** * Returns an object of this class wi

我是新来使用SSE与泽西,并有以下情况

我有一个JAXB注释类,它表示并作用于Raspberry Pi(类GpioRepresentation)的I/O 客户机类通过返回XML对象的getUpdate()方法访问I/O的状态 类的表示

@XmlRootElement
public class GpioRepresentation implements GpioSubject
{

...

    /**
         * Returns an object of this class with the current
         * representation of the I/O states
         * @return this
         */
        public synchronized GpioRepresentation getUpdate() 
        {
            this.getGarageDoorInputState();
            this.getZoneOneFeedback();
            this.getZoneTwoFeedback();
            this.getZoneThreeFeedback();
            this.getGarageDoorRelayState();
            this.getZoneOneRelayState();
            this.getZoneTwoRelayState();
            this.getZoneThreeRelayState();
            return this;
        }
...

}
使用getUpdate()的客户端是HomeResource类,方法getPiStatusStream()。这是一个JAX-RS注释的方法, 并提供远程客户端服务器发送的事件。目前,这个方法是用一个连续循环编写的,如图所示 在一个单独的线程中轮询更新

@Path("/homeservice")
@RolesAllowed({"ADMIN", "USER"})
@Produces(MediaType.APPLICATION_XML)
@Consumes(MediaType.APPLICATION_XML)
public class HomeResource 
{
    private static final Logger LOGGER = LoggerFactory.getLogger(HomeResource.class);

    private GpioRepresentation piService;

    ...

    /**
         * gets status information on the Raspberry Pi's
         * I/O and returns it to the client on a continuous basis
         * and only if it changes.
         * @return EventOutput 
         */
        @GET
        @Path("/iostatus")
        @Produces(SseFeature.SERVER_SENT_EVENTS)
        public EventOutput getPiStatusStream() 
        {
            final EventOutput eventOutput = new EventOutput();

            new Thread(new Runnable() 
            {
                public void run()
                {

                    try {
                         String gdState = null;
                         String zOneState = null;
                         String zTwoState = null;
                         String zThreeState = null;
                         String gdRState = null;
                         String zOneRState = null;
                         String zTwoRState = null;
                         String zThreeRState = null;
                         String lastgdState = null;
                         String lastzOneState = null;
                         String lastzTwoState = null;
                         String lastzThreeState = null;
                         String lastgdRState = null;
                         String lastzOneRState = null;
                         String lastzTwoRState = null;
                         String lastzThreeRState = null;


                        while(true) {

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

                            final GpioRepresentation iostatus = piService.getUpdate();

                            gdState = piService.getGarageDoorInputState();
                            zOneState = piService.getZoneOneFeedback();
                            zTwoState = piService.getZoneTwoFeedback();
                            zThreeState = piService.getZoneThreeFeedback();
                            gdRState = piService.getGarageDoorRelayState();
                            zOneRState = piService.getZoneOneRelayState();
                            zTwoRState = piService.getZoneTwoRelayState();
                            zThreeRState = piService.getZoneThreeRelayState();

                            if (!(gdState.equals(lastgdState) && zOneState.equals(lastzOneState) && zTwoState.equals(lastzTwoState) && zThreeState.equals(lastzThreeState)
                                    && gdRState.equals(lastgdRState) && zOneRState.equals(lastzOneRState) && zTwoRState.equals(lastzTwoRState) && zThreeRState.equals(lastzThreeRState)))
                            {
                                OutboundEvent event = eventBuilder.data(GpioRepresentation.class, iostatus)
                                        .mediaType(MediaType.APPLICATION_XML_TYPE)
                                        .build();

                                eventOutput.write(event);

                                lastgdState = gdState;
                                lastzOneState = zOneState;
                                lastzTwoState = zTwoState;
                                lastzThreeState = zThreeState;
                                lastgdRState = gdRState;
                                lastzOneRState = zOneRState;
                                lastzTwoRState = zTwoRState;
                                lastzThreeRState = zThreeRState;

                            }

                            Thread.sleep(100);
                        }
                    } 
                    catch (Exception exeption) 
                        {
                            System.err.println("Error: " + exeption);
                        } 
                    finally 
                        {
                            try 
                                {
                                    eventOutput.close();
                                } 
                            catch (IOException ioClose) 
                                {
                                    throw new RuntimeException("Error when closing the event output.", ioClose);
                                }
                        }
                    }
            }).start();

            return eventOutput;
        }

        ...

}
我所看到的问题是,它的伸缩性不好。为来自远程客户端的每个GET创建线程 需要时间,消耗CPU资源。另外,我认为这不是一个优雅的解决方案。我想做什么 将事件代码封装到一个单独的类中,并使用某种可以触发 创建事件……但是,如何将其绑定到资源方法中,以便将其返回到 远程客户端


有人能给我举一些例子,或者提供一些关于设计解决方案的建议吗?

解决方案是利用SSETradiator类。我让HomeService类成为GpioRepresentation类的观察者,然后调用一个新方法(broadcastIOUpdateMessage()),然后将我的事件输出到远程客户端

public void broadcastIOUpdateMessage()
{
    GpioRepresentation iostatus = piService.getUpdate();
    OutboundEvent.Builder eventBuilder = new OutboundEvent.Builder();
    OutboundEvent event = eventBuilder.data(GpioRepresentation.class, iostatus)
            .mediaType(MediaType.APPLICATION_XML_TYPE)
            .build();

    broadcaster.broadcast(event);
}

@GET
@Path("/iostatus")
@Produces(SseFeature.SERVER_SENT_EVENTS)
public EventOutput getPiStatusStream() 
{
    final EventOutput eventOutput = new EventOutput();
    this.broadcaster.add(eventOutput);
    return eventOutput;
}