facebook 很火,那条能聊天的底部工具条更惹眼,似乎也容易抄袭,好象还很受用,决定抄一把。
(1)基础框架就选 DWR,为什么,因为我讨厌写太多 JS 脚本。还有更重要的原因是 DWR3 支持多种 WEB 容器的 comet 特性。我喜欢这句话“Asynchronous servlet support for Tomcat and Glassfish”。
那么多的 web 容器,每个都有自己的 Comet 长连接实现,自己去实现每个容器的特殊接口,不如交给 dwr 去搞定。
从零开始写也是不可能的,幸好 dwr.war 的包中已经有了个基础的聊天 demo,所以功能上是不成问题。
(2)外观要长得象 facebook 的底条,开源的一两个,拼凑一下。
-http://www.sohtanaka.com/web-design/examples/footer-panel/
-http://anantgarg.com/2009/05/13/gmail-facebook-style-jquery-chat/
-http://www.cometchat.com/ 这个抄得神似一些,可惜需要美刀。
(4)如果能配上代码,就完美许多了。coming soon.
(5)还是直接拿来用比较好,这个站点几乎是最佳了,极力推荐一下下:http://code.google.com/p/ijab/
======================================================================
选择 ijab , 接下来是集成 ijab 的功能了。
一般来说,拥有注册用户的网站都有自己的用户和群组,无需要再另外注册和管理了,后台 xmpp 服务器首选 OpenFire,如何无缝集成 OpenFire+iJab+自己网站会员管理?
(1)OpenFire + iJab 比较容易, http://code.google.com/p/ijab/wiki/iJabWithOpenfire
(2)搞了许久才测试成功,版本的选择很重要
. Openfire3.6.4
. iJab1.03
. 主系统页面和 http-bind 必须相同域名,有两种方法一是用 apache 代理,二是在 tomcat Web应用中加入代理 servlet,都测试通过
(3)apache 代理
<VirtualHost 192.168.1.100:80> ServerAdmin webmaster@plusweb.com DocumentRoot /D/WORK/SAND/JAVA/workspace/sns/ijab <Directory /D/WORK/SAND/JAVA/workspace/sns/ijab> Options +Indexes +Multiviews </Directory> ServerName ideall01.gicp.net AddDefaultCharset UTF-8 RewriteEngine on RewriteRule http-bind/ http://localhost:7070/http-bind/ [P] </VirtualHost> AddDefaultCharset UTF-8 Options +MultiViews <IfModule mod_rewrite.c> RewriteEngine On RewriteRule http-bind/ http://localhost:7070/http-bind/ [P] </IfModule>
这个单独ijab可以使用,无法和我的应用集成一起。
(4)加入 servlet 的方法很好,我很喜欢。
<servlet> <servlet-name>HttpBindServlet</servlet-name> <servlet-class>com.plus.openfire.servlet.ProxyServlet</servlet-class> <init-param> <param-name>url</param-name> <param-value>http://192.168.1.100:7070/http-bind/</param-value> </init-param> </servlet> <!--@@JSPC-SERVLETS@@--> <!-- Servlet mappings --> <servlet-mapping> <servlet-name>HttpBindServlet</servlet-name> <url-pattern>/http-bind/*</url-pattern> </servlet-mapping>
以下代码来自于http://www.iteye.com/topic/520109
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ProxyServlet extends HttpServlet {
private String url;
/**
* 对servlet进行请求处理,并将结果在指定输出流中输出
*
* @param os
* @param servletName
* @param parm
* @throws IOException
* @throws MalformedURLException
*/
private void process(HttpServletRequest req, HttpServletResponse resp,
String[] target) throws MalformedURLException, IOException {
// 取得连接
HttpURLConnection huc = (HttpURLConnection) new URL(url + target[0])
.openConnection();
// 设置连接属性
huc.setDoOutput(true);
huc.setRequestMethod("POST");
huc.setUseCaches(false);
huc.setInstanceFollowRedirects(true);
huc.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
huc.connect();
// 往目标servlet中提供参数
OutputStream targetOS = huc.getOutputStream();
targetOS.write(target[1].getBytes());
targetOS.flush();
targetOS.close();
// 取得页面输出,并设置页面编码及缓存设置
resp.setContentType(huc.getContentType());
resp.setHeader("Cache-Control", huc.getHeaderField("Cache-Control"));
resp.setHeader("Pragma", huc.getHeaderField("Pragma"));
resp.setHeader("Expires", huc.getHeaderField("Expires"));
OutputStream os = resp.getOutputStream();
// 将目标servlet的输入流直接往页面输出
InputStream targetIS = huc.getInputStream();
int r;
while ((r = targetIS.read()) != -1) {
os.write(r);
}
targetIS.close();
os.flush();
os.close();
huc.disconnect();
}
/**
* 将参数中的目标分离成由目标servlet名称和参数组成的数组
*
* @param queryString
* @return
* @throws UnsupportedEncodingException
*/
private String[] parse(Map map) throws UnsupportedEncodingException {
String[] arr = { "", "" };
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry me = (Entry) iter.next();
String[] varr = (String[]) me.getValue();
if ("servletName".equals(me.getKey())) {
// 取出servlet名称
arr[0] = varr[0];
} else {
// 重新组装参数字符串
for (int i = 0; i < varr.length; i++) {
// 参数需要进行转码,实现字符集的统一
arr[1] += "&" + me.getKey() + "="
+ URLEncoder.encode(varr[i], "utf-8");
}
}
}
arr[1] = arr[1].replaceAll("^&", "");
return arr;
}
@Override
public void init() throws ServletException {
// 设置目标服务器地址
url = this.getInitParameter("url");
if (!url.endsWith("/"))
url = url + "/";
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String[] target = parse(req.getParameterMap());
process(req, resp, target);
}
}