chatdemo_message.java package chat.classinfo; /* 封装消息对象的类,这里为了演示就只设置了message一个属性 ,提供相应的set、get方法*/ public class Message { private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } chatdemo_getmsg.jsva package chat.servlet; import java.io.IOException; import java.io.PrintWriter; import java.util.Hashtable; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import chat.classinfo.Message; /* 监听是否有消息输入,当页面加载时就会用AJAX访问该servlet, */ public class GetMsgServlet extends HttpServlet { // 用一个Hashtable保存正在监听消息的客户端,键为每个客户端的session,值为消息对象 public static Hashtable<String, Message> waitList = new Hashtable<String, Message>(); public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } /* 消息监听,如果没有消息就会等待,当发送消息的servlet执行后会释放该同步锁 */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 保存Message对象 Message msg = new Message(); // 把该对象与相应的session放到Hashtable中, waitList.put(request.getSession(true).getId(), msg); // 消息同步,消息刚刚创建是没有任何内容的,所以一定会先进入等待状态,等到消息值放进去之后再执行后面的操作 synchronized (msg) { try { // 同步等待 msg.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // 当执行到这一步时,就说明消息同步已被唤醒,就说明msg里面已经把消息内容放进去了。 // 设置返回编码 response.setCharacterEncoding("utf-8"); // 用pw保存返回输出对象 PrintWriter pw = response.getWriter(); // 把消息内容通过输出对象输出 pw.print(msg.getMessage()); // 把输出对象清空关闭 pw.flush(); pw.close(); } } chatdemosendmsg.jsva package chat.servlet; import java.io.IOException; import java.util.Iterator; import java.util.Set; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import chat.classinfo.Message; /* 当点击发送按钮提交表单执行该servlet,对消息进行处理 */ public class SendMsgSrevlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } /* 处理消息,把消息放进消息对象,把同步锁唤醒 */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置传过来的数据编码 request.setCharacterEncoding("utf-8"); // 得到由输入的消息内容 String chatmsg = request.getParameter("chatmsg"); // 通过Set(Hashtable键)获取所有正在等待的session列表,方便使用迭代器 Set<String> sessions = GetMsgServlet.waitList.keySet(); // 使用迭代器Iterator方便遍历到所有的等待session Iterator<String> sessionsIt = sessions.iterator(); // 遍历所有等待的session对象 while (sessionsIt.hasNext()) { // 获取每一个等待的sessionid String sessionId = sessionsIt.next(); // 通过sessionid获取该等待session的消息对象 Message msg = GetMsgServlet.waitList.get(sessionId); // 在把输入框传过来的消息内容放进消息对象中时,可以用迭代器方便的把该等待session从等待列表中移除 sessionsIt.remove(); // 把消息内容放进消息对象,把同步消息唤醒 msg.setMessage(chatmsg); // 同步唤醒所有正在等待的消息对象 synchronized (msg) { msg.notifyAll(); } } } }