如何基于BS架构开发聊天程序
最近经常看到关于“如何基于BS架构开发聊天程序”的问题,这里把写的一个简要实例代码贴出来。
那么BS的聊天系统,一般两种技术(各有优劣):
1、基于Ajax或子页面刷新的拉模型;
2、基于HTTP长连接的推模型。
因为Ajax的“拉模型”,比较常见,这里给出基于HTTP长连接的“推模型”:
由三个页面组成:
chatmain.jsp 框架页面,引入两个Frame页面,并负责创建聊天室;
chatwnd.jsp 聊天信息窗口,负责用服务器推的方式显示所有人的聊天信息;
chatsender.jsp 聊天发送窗口,负责发送自己想说的话。
注意:本样例主要是为了说明 “基于长连接的推模型”,在聊天室完备性上完全不具有参考意义。
【chatmain.jsp 框架页面】
1 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 2 <%@ page import="java.util.*"%> 3 <% 4 // 这三句话只是为了防止浏览器缓存 5 response.setHeader("Cache-Control", "no-cache, no-store"); //HTTP 1.1 6 response.setHeader("Pragma", "no-cache"); //HTTP 1.0 7 response.setDateHeader("Expires", 0); //prevents caching at the proxy server 8 9 10 // 检查并按需创建“聊天室” 11 ArrayList<String> lstMsg = (ArrayList<String>) application.getAttribute("room"); 12 if (lstMsg == null) { 13 application.setAttribute("room", new ArrayList<String>()); 14 } 15 %> 16 <html> 17 <frameset rows="80%, 20%"> 18 <frame src="chatwnd.jsp"></frame> 19 <frame src="chatsender.jsp"></frame> 20 </frameset> 21 </html>
【chatwnd.jsp 聊天信息窗口】
1 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 2 <%@ page import="java.util.*"%> 3 <%@ page import="java.io.*"%> 4 <html> 5 <h2>Welcome to the ChatRoom!</h2> 6 <% 7 // 这三句话只是为了防止浏览器缓存 8 response.setHeader("Cache-Control", "no-cache, no-store"); //HTTP 1.1 9 response.setHeader("Pragma", "no-cache"); //HTTP 1.0 10 response.setDateHeader("Expires", 0); //prevents caching at the proxy server 11 12 13 Integer myMsgPos = 0; // 记录最后显示消息的位置 14 ArrayList<String> lstMsg = (ArrayList<String>) application.getAttribute("room"); 15 out.flush(); // 把之前的HTML信息都刷出去 16 PrintWriter pw = response.getWriter(); // 用PrintWriter取代JspWriter以便于检查Socket异常 17 try { 18 synchronized (lstMsg) { 19 while (true) { // 死循环,也就意味着本次HTTP请求不会结束 20 if (lstMsg.size() > myMsgPos) { // 检查有没有新的消息 21 // 循环显示所有新消息 22 System.out.println("Got new msg to push: "+(lstMsg.size()-myMsgPos)); 23 for (int i = myMsgPos; i < lstMsg.size(); i++) { 24 String msg = lstMsg.get(i); 25 pw.write("<p>"+msg+"</p>"); 26 } 27 if (pw.checkError()) { // 强制将输出缓冲区内容发送出去,并检查异常 28 System.out.println("IOException detected, JSP end."); 29 break; // 说明已经发生IOException(一般是浏览器页面关掉了) 30 } 31 myMsgPos = lstMsg.size(); // 更新最后显示的消息位置 32 } 33 System.out.println("Waiting new msg..." + out.getRemaining()); 34 lstMsg.wait(); // 临时释放对lstMsg的独占(同步锁),等待新消息的到来 35 } 36 } 37 } catch (Exception ex) { 38 System.out.println(ex); 39 } 40 %> 41 </html>
【chatsender.jsp 聊天发送窗口】
1 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 2 <%@ page import="java.util.*" %> 3 <%@ page import="java.text.*" %> 4 <% 5 SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); 6 // 这三句话只是为了防止浏览器缓存 7 response.setHeader("Cache-Control", "no-cache, no-store"); //HTTP 1.1 8 response.setHeader("Pragma", "no-cache"); //HTTP 1.0 9 response.setDateHeader("Expires", 0); //prevents caching at the proxy server 10 11 12 // 获取POST的“发言” 13 String msg = request.getParameter("msg"); 14 if (msg!=null && msg.length()>0) { 15 msg = "[" + sdf.format(new Date()) + "]" + session.getId() + ": " + msg; 16 System.out.println(msg); // 调试跟踪用的信息 17 ArrayList<String> lstMsg = (ArrayList<String>) application.getAttribute("room"); 18 synchronized (lstMsg) { 19 lstMsg.add(msg); // 消息放入池中(消息太多会溢出的,这里并没有进行处理) 20 lstMsg.notifyAll(); // 通知chatwnd.jsp们,有新的消息来了,可以推给浏览器了 21 } 22 } 23 %> 24 <!DOCTYPE unspecified PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 25 <html> 26 <form method="post"> 27 My Speak: <input name="msg" type="text" size="40" /> <input type="submit" /> 28 </form> 29 </html>
转载自:http://blog.csdn.net/ldh911/article/details/7268879