servlet异步调用

来源:互联网 发布:以色列巴勒斯坦知乎 编辑:程序博客网 时间:2024/05/29 12:39

compile group: 'org.apache.activemq', name: 'activemq-all', version: '5.13.3'
compile group: 'javax.jms', name: 'jms', version: '1.1'



package servlet;



import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;


import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
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 subscriber.ReceiptListener;
import subscriber.ReceiptSubscriber;


@WebServlet(urlPatterns = { "/WebLogServlet" }, asyncSupported = true)
public class WebLogServlet extends HttpServlet {


/**

*/
private static final long serialVersionUID = 1L;
public  static final Queue<AsyncContext> ASYNC_CONTEXT_QUEUE = new ConcurrentLinkedQueue<AsyncContext>();
private static AsyncContextQueueWriter writer = new AsyncContextQueueWriter(ASYNC_CONTEXT_QUEUE);


public static String meg = "error";


static {


new Thread(new Runnable() {


ReceiptSubscriber receiptSubscriber = new ReceiptSubscriber("receiptSubscriber", "publisher", "password",
"tcp://smart.fdauto.com:61616", "smartApproveQueue1", new ReceiptListener());


@Override
public void run() {
receiptSubscriber.start();
while (true) {
try {
if (!WebLogServlet.meg.equals("error")) {
writer.sendMessage(WebLogServlet.meg);
WebLogServlet.meg = "error";
}


Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
}


/**
* 将客户端注册到监听 Logger 的消息队列中
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
res.setContentType("text/html;charset=UTF-8");
res.setHeader("Cache-Control", "private");
res.setHeader("Pragma", "no-cache");
req.setCharacterEncoding("UTF-8");


final AsyncContext ac = req.startAsync();    //开始异步调用
ac.setTimeout(60 * 1000);
ac.addListener(new AsyncListener() {
public void onComplete(AsyncEvent event) throws IOException {
ASYNC_CONTEXT_QUEUE.remove(ac);
}


public void onTimeout(AsyncEvent event) throws IOException {
ASYNC_CONTEXT_QUEUE.remove(ac);
}


public void onError(AsyncEvent event) throws IOException {
ASYNC_CONTEXT_QUEUE.remove(ac);
}


public void onStartAsync(AsyncEvent event) throws IOException {
}
});
ASYNC_CONTEXT_QUEUE.add(ac);
}

}






package servlet;


import javax.servlet.AsyncContext;  
import java.io.IOException;  
import java.io.PrintWriter;  
import java.util.Queue;  
import java.util.concurrent.BlockingQueue;  
import java.util.concurrent.LinkedBlockingQueue;  
  
/**  
 * 向一个 Queue<AsyncContext> 中每个 Context 的 Writer 进行输出  
 */  
public class AsyncContextQueueWriter {  
    private Queue<AsyncContext> queue;  
    private static final BlockingQueue<String> MESSAGE_QUEUE = new LinkedBlockingQueue<String>();  
  
    AsyncContextQueueWriter(Queue<AsyncContext> queue) {  
        this.queue = queue;  
        Thread notifierThread = new Thread(notifierRunnable);  
        notifierThread.start();  
    }  
  
    public void sendMessage(String msg) throws IOException {  
        try {  
            MESSAGE_QUEUE.put(msg);  
        } catch (Exception ex) {  
            IOException t = new IOException();  
            t.initCause(ex);  
            throw t;  
        }  
    }  
  
    /**  
     * 异步线程,当消息队列中被放入数据,将释放 take 方法的阻塞,将数据发送到 http response 流上  
     */  
    private Runnable notifierRunnable = new Runnable() {  
        public void run() {  
            boolean done = false;  
            while (!done) {  
                String message = null;  
                try {  
                    message = MESSAGE_QUEUE.take();  
                    for (AsyncContext ac : queue) {  
                        try {  
                            PrintWriter acWriter = ac.getResponse().getWriter();  
                            acWriter.println(/*htmlEscape(message)*/message);   
                            acWriter.flush();  
                        } catch (IOException ex) {  
                            System.out.println(ex);  
                            queue.remove(ac);  
                        }  
                    }  
                } catch (InterruptedException iex) {  
                    done = true;  
                    System.out.println(iex);  
                }  
            }  
        }  
    };  
  
    // 因为浏览器的iframe相对于主页面是一个子页面,这里使用了 window.parent,调用其 update 方法,将数据闯入进去  
    private String htmlEscape(String message) {  
        return "<script type='text/javascript'>\nwindow.parent.update(\""  
                + message.replaceAll("\n", "").replaceAll("\r", "") + "\");</script>\n";  
    }  
  
    public void close() throws IOException {  
        for (AsyncContext ac : queue) {  
            ac.getResponse().getWriter().close();  
        }  
    }  
}  

0 0