测试环境Tomcat7
Servlet3以后才支持异步Servlet, Tomcat7中才支持. 其他jsp服务器没有测试.
1. Servlet
import java.io.IOException;
import java.util.Enumeration;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
public class CometServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("CometServlet" + req);
Object UserId = req.getSession().getAttribute("UserId");
if (UserId == null) {
UserId = UUID.randomUUID().toString();
req.getSession().setAttribute("UserId", UserId);
}
System.out.println("Userid=" + UserId);
if (!req.isAsyncStarted()) {
req.startAsync();
}
resp.addHeader("Connection", "keep-alive");
resp.addHeader("Content-Type", "text/html; charset=utf-8");
Enumeration<String> names = req.getParameterNames();
JSONObject json = new JSONObject();
String key;
while (names.hasMoreElements()) {
key = names.nextElement();
json.put(key, req.getParameter(key));
}
AsynResult asynResult = new AsynResult(req.getAsyncContext(), json,
UserId.toString());
AsynMsg.getInstance().AddClient(asynResult);
}
}
2. 同步消息缓存
import javax.servlet.AsyncContext;
import javax.servlet.ServletResponse;
import net.sf.json.JSONObject;
public class AsynResult {
private AsyncContext context;
private JSONObject json;
private String userId;
public AsyncContext getContext() {
return context;
}
public JSONObject getJson() {
return json;
}
public String getUserId() {
return userId;
}
public AsynResult(AsyncContext context, JSONObject json, String userId) {
this.context = context;
this.json = json;
this.userId = userId;
}
public void send(JSONObject json) {
try {
ServletResponse rep = context.getResponse();
rep.setContentType("application/json;charset=UTF-8");
rep.setCharacterEncoding("UTF-8");
rep.getWriter().write(json.toString());
} catch (Exception e) {
}
}
}
3. 消息处理
import java.util.HashMap;
import java.util.Map;
import net.sf.json.JSONObject;
public class AsynMsg {
// List<AsynResult> clients = new ArrayList<AsynResult>();
private Map<String, AsynResult> clients = new HashMap<String, AsynResult>();
// region 实现该类的单例
private static final AsynMsg _Instance = new AsynMsg();
private static final String KEY = "msg";
private AsynMsg() {
}
public static AsynMsg getInstance() {
return _Instance;
}
public void AddClient(AsynResult result) {
String type = result.getJson().optString("type", "data");
String to = result.getJson().optString("to", null);
String user = result.getUserId();
String from = user;
if (type.equals("wait")) {
if("lott".equals(result.getJson().optString("msgType",""))){
user = "lott";
}
clients.put(user, result);
try {
synchronized (clients) {
clients.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
if("".equals(type)){
to = "lott";
}
JSONObject json = new JSONObject();
json.put(KEY, user + ":" + result.getJson().getString("asynMsg"));
// 将当前请求的内容输出到客户端
result.send(json);
// 否则将遍历所有已缓存的client,并将当前内容输出到客户端
sendMsg(user + ":" + result.getJson().getString("asynMsg"), from,
to,type);
}
}
public void sendMsg(String content) {
sendMsg(content, "系统", null, "data");
}
// / <summary>
// / 遍歷所有客戶端, 將消息傳送給客戶端
// / </summary>
// / <param name="orderType"></param>
public void sendMsg(String content, String from, String to, String type) {
synchronized (clients) {
clients.notifyAll();
}
JSONObject json = new JSONObject();
json.put(KEY, content);
json.put("from", from);
json.put("to", to);
json.put("type", type);
System.out.println(json);
if (to == null || to.toUpperCase().equals("ALL")) {
for (AsynResult value : clients.values()) {
value.send(json);
value.getContext().complete();
}
// 清空所有缓存
clients.clear();
} else {
AsynResult value = clients.get(to);
value.send(json);
System.out.println(value.getContext().getRequest().isAsyncStarted());
if(value.getContext().getRequest().isAsyncStarted()){
value.getContext().complete();
}
}
}
}
4. 通过jsp建立长链接
http://localhost:8080/Comet/CometServlet?content=&type=wait
5. 通过jsp响应长链接
http://localhost:8080/Comet/json/home!SendMsg.do
6. 通过java程式模拟http建立长链接
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.ResourceBundle;
import net.sf.json.JSONObject;
public class HttpCometUtils {
// private static String host = "http://localhost:8080/Comet/";
private static String action = "json/home!SendMsg.do?msgType=ALL";
protected static ResourceBundle projectBundle = ResourceBundle
.getBundle("DataBaseServer");
public static Thread CometThread = null;
private static String host = projectBundle.getString("web_server");
public static boolean isLogin = false;
static {
if (!host.endsWith("/")) {
host += "/";
}
}
public HttpCometUtils() {
// host = "http://localhost:8080/Comet/";
if (!host.endsWith("/")) {
host += "/";
}
}
/**
* @param urlString
* @param method
* @param type
* @param msg
* @throws IOException
*/
public static void connectServer() {
new Thread() {
@Override
public void run() {
int errorCount = 0;
while (isLogin) {
if (errorCount >= 10) {
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
break;
}
}
URL url = null;
HttpURLConnection urlConnection = null;
try {
String serverURL = host
+ "CometServlet?content=&type=wait&msgType=lott";
System.out.println(serverURL);
url = new URL(serverURL);
urlConnection = (HttpURLConnection) url
.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setUseCaches(false);
InputStream is = urlConnection.getInputStream();
byte[] b = new byte[is.available()];
is.read(b);
String jsmsg = new String(b, "utf-8");
System.out.println(jsmsg);
if(jsmsg.equals("")){
jsmsg = "{}";
}
JSONObject json = JSONObject.fromObject(jsmsg);
Object obj = null;
if (json.containsKey("type")) {
obj = json.get("type");
if (obj != null && "lott".equals(obj)) {
json = (JSONObject) json.get("msg");
if (json.containsKey("chatMsg")) {
System.out.println(json.get("chatMsg"));
}
}
}
errorCount = 0;
} catch (MalformedURLException e) {
errorCount++;
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
errorCount++;
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
errorCount++;
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
}
}.start();
}
public static void main(String[] args) {
int x = new Random(System.currentTimeMillis()).nextInt(100);
HttpCometUtils.isLogin = true;
HttpCometUtils.connectServer();
}
}
7. 通过java程式模拟http响应长链接
import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.Random; import java.util.ResourceBundle; public class HttpUtils { // private static String host = "http://localhost:8080/Comet/"; private static String action = "json/home!SendMsg.do?msgType=ALL"; protected static ResourceBundle projectBundle = ResourceBundle .getBundle("DataBaseServer"); private static String host = "http://localhost:8080/Comet";//projectBundle.getString("web_server"); static { if (!host.endsWith("/")) { host += "/"; } } public HttpUtils() { if (!host.endsWith("/")) { host += "/"; } } /** * @param urlString * @param method * @param type * @param msg * @throws IOException */ public static void send(final String type, final String asynMsg) { new Thread() { @Override public void run() { URL url = null; HttpURLConnection urlConnection = null; try { StringBuffer param = new StringBuffer(); param.append("&type=").append(type); param.append("&asynMsg=").append(URLEncoder.encode(asynMsg, "UTF-8")); String urlString = param.toString(); String serverURL = host + action + urlString; System.out.println(serverURL); url = new URL(serverURL); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setRequestMethod("GET"); // urlConnection.setDoOutput(true); // urlConnection.setDoInput(true); urlConnection.setUseCaches(false); System.out.println(urlConnection.getResponseMessage()); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { if (urlConnection != null) { urlConnection.disconnect(); } } } }.start(); } public static void main(String[] args) { int x = new Random(System.currentTimeMillis()).nextInt(100); HttpUtils.send("chat", "恭喜您中奖了."); } }