[猫爪--综合] 由weblogic.servlet.FutureResponseServlet引发的思考

apolloty 2007-11-08
FutureResponseServlet 和 FutureServletResponse 的特性令人咂舌.

Look!
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Stack;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import weblogic.servlet.FutureResponseServlet;
import weblogic.servlet.FutureServletResponse;

// An AsynchronousServlet that handles HTTP requests from a "separate" thread and
// not the execute thread used to invoke this servlet.
public class AsynchronousServerResponseServlet extends FutureResponseServlet {
	private final Notifier notifier;
	private static Stack clients = new Stack();

	public AsynchronousServerResponseServlet () {
		this.notifier = new Notifier();
		this.notifier.start();
	}

	public void service(HttpServletRequest request, FutureServletResponse response)
		throws IOException, ServletException {

		// push this client's request to a buffer and return immediately.
		// asynchronous processing occurs in the run method of the Notifier Thread
		notifier.poll(request, response);
	}

	class Notifier extends Thread {

		void poll (HttpServletRequest request, FutureServletResponse response) {
			clients.push(new Client(request, response));
		}

		public void run() {
			while (!clients.empty()) {
				Client client = null;
				try
				{
					client = (Client) clients.pop();
					PrintWriter pw = client.response.getWriter();
					for(int j = 0; j < 10; j++) {
						pw.println("Time is:" + new Date() + "");
						pw.flush();

					}
					pw.close();
				} catch(Throwable t) {
					t.printStackTrace();
				} finally {
					try {
					client.response.send();

					} catch(IOException ioe) {
					ioe.printStackTrace();
					}
				}
			}
		}
	}

	// inner class that holds on to the clients http request and response
	class Client {
		private HttpServletRequest request;
		private FutureServletResponse response;

		private Client(HttpServletRequest request, FutureServletResponse response) {
			this.request = request;
			this.response = response;
		}
	}
} 

此特性将一次请求丢进任意容器即完成操作,释放资源。而通过后台轮询处理后居然可以client.response.send();到客户端!不可思议。

此特性让我无限YY,我能想到好多应用,
比如:
页面渲染分成多次,而且不需要前台AJAX的请求,纯后台push。
页面及时信息提示,不需要AJAX轮询,或者后台多线程阻塞队列。
在线及时通讯,甚至传非文本数据等等。

对与把YY变成现实的追求,我开始了探索之路,首先再google,baidu狂搜FutureServletResponse无果,没人提供此类源码,另外weblogic的对此的实现我也没有找到,于是乎我自己来尝试实现这种特殊的response。
我从最干净的ServerSocket着手试图突破这些谜团

……
//localSocket为接受的浏览器socket
from = new BufferedReader( new InputStreamReader( localSocket.getInputStream() ) );
to = new PrintWriter( new OutputStreamWriter( localSocket.getOutputStream() ), true );
toBin = localSocket.getOutputStream();

do
{
	httpText = from.readLine();
}
while ( httpText.length() != 0 );
sendHeader( toBin );//写正常状态的头,比如"HTTP/1.0 200 OK\n"

int i=0;
while(i<50)
{
	try
	{
		Thread.sleep(500);
	}
	catch (InterruptedException e){}
	to.write("this is Response"+i);
			
	to.write("\n");
	to.flush();
	i++;
} 


然后在页面上写个请求


Function doAjaxRequest()
{
	Var xmlhttp;
	if(window.ActiveXObject)
	{
		xmlhttp =new ActiveXObject("Microsoft.XMLHTTP");
	}
	else if(window.XMLHttpRequest)
	{
		xmlhttp =new XMLHttpRequest();
	}
	xmlhttp.onreadystatechange= t_callback;
	xmlhttp.open("GET","http://127.0.0.1/",true);
	xmlhttp.send(null);
}
function t_callback()
{
	//展现
	var ret=this.xmlhttp.responseText;
	document.write(ret);
}



执行,在一次通信间能够由后台像前台刷50次屏幕,但是到这里问题就出现了,浏览器上点击X后,断掉了socket,后台理所当然的无法push信息到页面,而且FutureServletServerlet主要是单线程就能处理多条response,很不理解FutureServletResponse的实现。

所以写到这里:我向看到此贴的朋友提问:
1. 莫非一个socket未必要绑定一个线程?
2. 莫非FutureServletResponse的实现就是将所有socket都缓存起来?
3. 莫非FutureServletResponse提交已经无视请求,无视socket想提就提!@#$%^&*?

本人还停留在定势思维上,请大家发表自己的想法!急切寻求解答!
Global site tag (gtag.js) - Google Analytics