使用Java实现Comet风格的Web应用(四)

2014-11-24 01:40:16 · 作者: · 浏览: 1
log("Message added #messages=" + messages.size());

messages.notify();

}

}

public void run() {

while (running) {

if (messages.size() == 0) {

try {

synchronized (messages) {

messages.wait();

}

} catch (InterruptedException e) {

// Ignore

}

}

String[] pendingMessages = null;

synchronized (messages) {

pendingMessages = messages.toArray(new String[0]);

messages.clear();

}

try {

if (connection == null){

try{

synchronized(this){

wait();

}

} catch (InterruptedException e){

// Ignore

}

}

PrintWriter writer = connection.getWriter();

for (int j = 0; j < pendingMessages.length; j++) {

final String forecast = pendingMessages[j] + "
";

writer.println(forecast);

log("Writing:" + forecast);

}

writer.flush();

writer.close();

connection = null;

log("Closing connection");

} catch (IOException e) {

log("IOExeption sending message", e);

}

}

}

}

这个类基本上是样板代码,与Comet 没有直接的关系。但是,有两点要注意。这个类含有一个ServletResponse 对象。回头看看清单2 中的event 方法,当事件为BEGIN 时,response 对象被传入到MessageSender 中。在MessageSender 的run 方法中,它使用ServletResponse 将数据发送回客户机。注意,一旦发送完所有排队等待的消息后,它将关闭连接。这样就实现了长轮询。如果要实现流风格的Comet,那么需要使连接保持开启,但是仍然刷新数据。

回头看清单2 可以发现,其中创建了一个Weatherman 类。正是这个类使用MessageSender 将数据发送回客户机。这个类使用Yahoo RSS feed 获得不同地区的天气信息,并将该信息发送到客户机。这是一个特别设计的例子,用于模拟以异步方式发送数据的数据源。清单4 显示了它的代码。

清单4. Weatherman

private class Weatherman implements Runnable{

private final List zipCodes;

private final String YAHOO_WEATHER = "http://weather.yahooapis.com/forecastrss p=";

public Weatherman(Integer... zips) {

zipCodes = new ArrayList(zips.length);

for (Integer zip : zips) {

try {

zipCodes.add(new URL(YAHOO_WEATHER + zip));

} catch (Exception e) {

// dont add it if it sucks

}

}

}

public void run() {

int i = 0;

while (i >= 0) {

int j = i % zipCodes.size();

SyndFeedInput input = new SyndFeedInput();

try {

SyndFeed feed = input.build(new InputStreamReader(zipCodes.get(j)

.openStream()));

SyndEntry entry = (SyndEntry) feed.getEntries().get(0);

messageSender.send(entryToHtml(entry));

Thread.sleep(30000L);

} catch (Exception e) {

// just eat it, eat it

}

i++;

}

}

private String entryToHtml(SyndEntry entry){

StringBuilder html = new StringBuilder("

");

html.append(entry.getTitle());

html.append("

");

html.append(entry.getDescription().getValue());

return html.toString();

}

}

这个类使用Project Rome 库解析来自Yahoo Weather 的RSS fee