0

我正在尝试以一种通用方式实现服务器发送事件的服务器代码,即我的应用程序的任何对象都可以向客户端发送消息,因此我决定仅为 SSE 实现一个特定的 Servlet。最初的测试代码就像一个魅力,但不够灵活,无法从我的应用程序的不同部分发送消息。因此,我重写了代码,使所有引用 Servlet 对象的对象都可以向客户端发送消息:

public class PushServlet extends HttpServlet {

    private Thread threadServlet;
    private boolean processando=true;
    private MensagemSSEBean mensagem;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        threadServlet=Thread.currentThread();
        response.setContentType("text/event-stream; charset=utf-8");
        while (processando){
            if(!pausarThread())
                break;
            enviarMensagemParaOCliente(response.getWriter());
        }
        enviarMensagemDeFechamento(response.getWriter());
    }

    private void enviarMensagemParaOCliente(PrintWriter saida) {
        ConversorMensagemSSE conversor = new ConversorMensagemSSE();
        saida.print(conversor.converter(mensagem));
        saida.flush();
    }

    private synchronized void enviarMensagemDeFechamento(PrintWriter saida) {
        mensagem.setMensagem("#FECHAR_CONEXAO#");
        enviarMensagemParaOCliente(saida);
        saida.close();
    }

    public synchronized void enviarMensagem(MensagemSSEBean mensagem) throws IOException {
        this.mensagem=mensagem;
        threadServlet.notifyAll();
    }

    public synchronized void finalizar(){
        processando=false;
    }

    private boolean pausarThread() {
        try {
            threadServlet.wait();
            return true;
        } catch (InterruptedException e) {
            e.printStackTrace();  
        }
        return false;
    }
}

如您所见,我暂停了 Servlet 线程,直到调用“enviarMensagem”为止。我没有测试这段代码,基本上是因为我不知道如何获得这个 Servlet 对象。有人可以解释一下我如何从任何对象中获取这个 Servlet 对象吗?另一个重要问题,这是解决此类问题的理想方法吗?

4

1 回答 1

0

最后我以一种通用的方式实现了它。servlet 类现在每十秒发送一次 keep-alive 或共享队列中的消息:

public class PushServlet extends HttpServlet {

    private boolean processing = true;
    private HttpServletResponse response;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.response = response;
        configureAndStart();
        while (processing) {
            try {
                sendMessages();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void configureAndStart() throws IOException {
        processing = true;
        response.setContentType("text/event-stream; charset=utf-8");
        sendMessage(new SSEMessageBean(SSEEventType.START));
    }

    private void sendMessages() throws IOException, InterruptedException {
        SSEMessageBean message = MessageQueueController.getInstance().getNextMessage();
        while (message != null) {
            sendMessage(message);
            message = MessageQueueController.getInstance().getNextMessage();
            if (message.getEventType() != SSEEventType.END)
                return;
        }
        Thread.sleep(10000);
        sendMessage(new SSEMessageBean(SSEEventType.KEEP_ALIVE));
    }

    public void sendMessage(SSEMessageBean message) throws IOException {
        SSEMessageConverter converter = new SSEMessageConverter();
        PrintWriter out = response.getWriter();
        out.print(converter.convert(message));
        out.flush();
        if (message.getEventType() == SSEEventType.END) {
            processing = false;
            out.close();
        }
    }
}

想要向客户端发送事件的对象只需写入共享队列。

于 2012-10-09T20:01:07.247 回答