当前位置:文档之家› 聊天室模块

聊天室模块

A 聊天室模块

A.1 聊天室模块概述

A.1.1 功能描述

聊天室的基本功能就是聊天,其他功能都是对基本功能的一个强化。本章中的聊天室主要包括以下功能。

?用户登录,包括验证用户是否在线。

?实时显示在线人员列表及在线人数。

?用户发言,包括选择表情和字体颜色功能。

?安全退出聊天室。

A.1.2 系统流程

聊天室的系统流程如图A.1所示。

图A.1 系统流程图

A.1.3 主界面预览

为了使读者对本模块有一个基本的了解,下面将给出聊天室的主界面预览效果图。聊天室的主界面运行结果如图A.2所示。

1

2

图A.2 主界面运行结果图

A.2 关键技术

在模块中,应用的关键技术为Ajax 重构和Application 对象的相关方法,下面进行详细介绍。

A.2.1 Ajax 重构

随着Ajax 应用程序的不断扩展,将会有越来越多的JavaScript 代码应用到Ajax 中,这可能导致许多意想不到的问题。因此有必要对Ajax 代码进行重构。下面将介绍实现Ajax 重构的基本步骤。

创建一个单独的JS 文件,名称为AjaxRequest.js ,并且在该文件中编写重构Ajax 所需的代码,具体代码如下:

var net=new Object(); //编写构造函数

net.AjaxRequest=function(url,onload,onerror,method,params){ this.req=null;

this.onload=onload;

this.onerror=(onerror) ? onerror : this.defaultError; this.loadDate(url,method,params); }

//编写用于初始化XMLHttpRequest 对象并指定处理函数,最后发送HTTP 请求的方法 net.AjaxRequest.prototype.loadDate=function(url,method,params){ if (!method){

method="GET"; }

if (window.XMLHttpRequest){ this.req=new XMLHttpRequest(); } else if (window.ActiveXObject){

this.req=new ActiveXObject("Microsoft.XMLHTTP"); }

if (this.req){ try{

var loader=this;

this.req.onreadystatechange=function(){

net.AjaxRequest.onReadyState.call(loader);

}

this.req.open(method,url,true);

if(method=="POST"){

this.req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");

}

this.req.send(params);

}catch (err){

this.onerror.call(this);

}

}

}

//重构回调函数

net.AjaxRequest.onReadyState=function(){

var req=this.req;

var ready=req.readyState;

if (ready==4){

if (req.status==200 ){

this.onload.call(this);

}else{

this.onerror.call(this);

}

}

}

//重构默认的错误处理函籹

net.AjaxRequest.prototype.defaultError=function(){

alert("错误数据\n\n回调状态:"+this.req.readyState+"\n状态: "+this.req.status);

}

在需要应用Ajax的页面中应用以下的语句包含JS文件“AjaxRequest.js”。

在应用Ajax的页面中编写错误处理的方法、实例化Ajax对象的方法和回调函数,具体代码如下:

A.2.2 Application对象

Application对象是一个环境上下文(Context)对象,用于保存应用程序中的所有公有数据,服务器启动并且自动创建Application对象以后,只要没有关闭服务器,Application 对象将一直存在,所有用户可以共享Application对象。

Application对象为JSP提供的内置对象,可以直接使用,但是在Servlet中,需要通过以下代码来获取该对象的实例,才可以使用该对象。

ServletContext application = getServletContext();

3

Application 对象提供了很多方法,本实例中,只使用了setAttribute()方法和getAttribute()方法。

首先来介绍setAttribute()方法,该方法用于将一个对象绑定到一个属性上,该属性在整个Servlet 上下文中都适用。setAttribute()方法的语法格式如下:

application.setAttribute(String name,Object object);

?

name :用于指定一个属性名,该属性在整个Servlet 上下文中都适用。 ? object :用于指定属性值。

例如,在本实例中,设置保存聊天信息的Application 对象的属性的具体代码如下:

application.setAttribute("message", sourceMessage);

下面再来介绍getAttribute()方法,该方法用于返回Application 对象的指定属性的值。如果不存在该属性,则返回null 。getAttribute()方法的基本语法如下:

application. getAttribute(String name);

?

name :用于指定一个属性名。

例如,在本实例中,设置获取聊天信息的Application 对象的属性的具体代码如下:

String sourceMessage = application.getAttribute("message").toString();

A.3 聊天室的实现过程

A.3.1 实现用户登录

当用户访问聊天室时,首先进入的是登录聊天室页面。在该页面中,用户输入自己喜欢的用户名,如图A.3所示,单击“进入”按钮,系统将判断输入的用户是否被占用,如果被占用将给出提示,否则进入到聊天室主界面。

图A.3 用户登录页面

实现用户登录的具体步骤如下。

(1)编写聊天室登录页面index.jsp ,在该页面中添加如表A.1所示的表单及表单元素。

表A.1 index.jsp 页面所涉及的表单及表单元素

(2)编写用来保存在线用户和对在线用户进行具体操作的类,这里为UserInfo,在该类中主要包括返回外界使用的实例对象、添加用户、获取用户列表和移用户的方法。UserInfo类的具体代码如下:

package com.wgh.model;

import java.util.Vector;

public class UserInfo {

private static UserInfo user = new UserInfo();

private Vector vector = null; // 利用private调用构造函数,防止被外界产生新的instance对象

public UserInfo() {

this.vector = new Vector();

}

// 外界使用的instance对象

public static UserInfo getInstance() {

return user;

}

// 增加用户

public boolean addUser(String user) {

if (user != null) {

this.vector.add(user);

return true;

} else {

return false;

}

}

// 获取用户列表

public Vector getList() {

return vector;

}

// 移除用户

public void removeUser(String user) {

if (user != null) {

vector.removeElement(user);

}

}

}

(3)创建UserListener类,主要实现valueBound(HttpSessionBindingEvent arg0)和valueUnbound(HttpSessionBindingEvent arg0)方法,用于监控session中的对象变化情况。在该方法中,在valueBound()方法中向控制台输出上线用户的信息,在valueUnbound()方法中向控制台输出下线用户的信息。UserListener类的具体代码如下:

package com.wgh.servlet;

import https://www.doczj.com/doc/704570899.html,erInfo;

import javax.servlet.http.HttpSessionBindingEvent;

public class UserListener implements

javax.servlet.http.HttpSessionBindingListener {

private String user;

private UserInfo container = UserInfo.getInstance(); //获得UserInfo类的对象

public UserListener() {

user = "";

}

// 设置在线监听人员

public void setUser(String user) {

https://www.doczj.com/doc/704570899.html,er = user;

}

// 获取在线监听

5

6

public String getUser() {

return https://www.doczj.com/doc/704570899.html,er;

}

// 当Session有对象加入时执行的方法

public void valueBound(HttpSessionBindingEvent arg0) {

System.out.println("上线用户:" + https://www.doczj.com/doc/704570899.html,er);

}

// 当Session有对象移除时执行的方法

public void valueUnbound(HttpSessionBindingEvent arg0) {

System.out.println("下线用户:" + https://www.doczj.com/doc/704570899.html,er);

if (user != "") {

container.removeUser(user);

}

}

}

说明:HttpBindingListener接口的valueBound()方法在有对象加入session时会被自动

执行,而valueUnbound()方法则是有对象从session中移除时会被自动执行。

(4)编写聊天室的Servlet实现类,并在该类中加添加登录聊天室的方法loginRoom(),在该方法中,首先获取登录用户,然后判断该用户是否登录,如果已经登录,给出提示信息,否则将该用户添加到在线用户列表中,并且向Application对象的聊天内容属性中添加一条系统公告信息,最后,将页面重定向到登录成功页。loginRoom()方法的具体代码如下:public void loginRoom(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html;charset=UTF-8");

HttpSession session = request.getSession();

String username=request.getParameter("username"); //获得登录用户名

UserInfo user=UserInfo.getInstance(); //获得UserInfo类的对象

session.setMaxInactiveInterval(600); //设置Session的过期时间为10分钟

Vector vector=user.getList();

boolean flag=true; //标记是否登录的变量

//判断用户是否登录

if(vector!=null&&vector.size()>0){

for(int i=0;i

if(username.equals(vector.elementAt(i))){

PrintWriter out;

try {

out = response.getWriter();

out.println("");

} catch (IOException e) {

e.printStackTrace();

}

flag=false;

break; //跳出for循环

}

}

}

//保存用户信息

if(flag){

UserListener ul=new UserListener(); //创建UserListener的对象

ul.setUser(username); //添加用户

user.addUser(ul.getUser()); //添加用户到UserInfo类的对象中

session.setAttribute("user",ul); //将UserListener对象绑定到Session中

session.setAttribute("username",username); //保存当前登录的用户名

session.setAttribute("loginTime",new Date().toLocaleString()); //保存登录时间

ServletContext application=getServletContext(); //获取Application对象

String sourceMessage="";

if(null!=application.getAttribute("message")){

sourceMessage=application.getAttribute("message").toString();

7

} sourceMessage+="系统公告:" + username + "走进了聊天室!
"; application.setAttribute("message",sourceMessage);

try { request.getRequestDispatcher("login_ok.jsp").forward(request, response); } catch (Exception ex) { Logger.getLogger(Messages.class.getName()).log(Level.SEVERE, null, ex); } } }

(5)编写登录成功页login_ok.jsp ,在该文件中,将页面重定向到聊天室的主界面。登录成功页的具体代码如下:

<%@page contentType="text/html" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="https://www.doczj.com/doc/704570899.html,/jsp/jstl/core"%>

A.3.2 编写聊天室的主界面

在用户登录页面中,输入用户名,单击“进入”按钮,即可进入到聊天室的主界面,如图A.2所示,在该页面中共包括页面头部、在线人员列表区、聊天内容显示区和用户发言区4部分,具体布局如图A.4所示。

图A.4 主页面的布局图

聊天室主界面主要用采用

标记进行部局,其关键代码如下:

在线人员列表

聊天内容

8

A.3.3 实时显示在线人员列表

在开发聊天室程序时,为了让用户及时了解在线线用户,并与各用户进行交流,需要提供实时获取并显示在线人员列表的功能。在本章中介绍的聊天室的主界面中,左侧显示在线人员列表,及在线人数,如图A.5所示。

图A.5 在线人员列表

在实现在线人员列表显示时,为了实时显示在线人员列表,这里应用了Ajax 技术,关于Ajax 重构的方法,请参见A.2.1节。实现实时显示在线人员列表的具体步骤如下。 (1)在main.jsp 页面中,编写自定义的JavaScript 函数showOnline(),用于实例化Ajax 对象。showOnline()函数的具体代码如下:

function showOnline(){ var loader=new net.AjaxRequest("online.jsp?nocache="+ new Date().getTime(),deal_online,onerror,"GET"); }

在上面的代码中,一定要加代码“?nocache="+new Date().getTime()”,否则将出现在线人员列表不更新的情况。

(2)创建online.jsp 文件。在该文件中,主要是将保存到集合类中的在线人员列表显示到页面。online.jsp 页面的代码如下:

<%@page contentType="text/html" pageEncoding="UTF-8" %> <%@ page import="https://www.doczj.com/doc/704570899.html,erInfo"%> <%@ page import="java.util.*"%> <%

UserInfo list=UserInfo.getInstance(); Vector vector=list.getList(); int amount=0; %>

<%if(vector!=null&&vector.size()>0){ String username=""; amount=vector.size(); for(int i=0;i

<%}}%>

9

欢迎来到心之语聊天室!
所有人
<%=username%>
当前在线[<%=amount%>]人

(3)在聊天室的主界面中,将左侧用于显示在线人员列表的单元格的id 属性设置为online ,用于实时显示在线人员列表,具体代码如下:

在线人员列表

(4)编写Ajax 的回调函数deal_online(),用于将获取的在线人员列表赋值给id 为online 的标记的innerHTML 属性。deal_online()函数的具体代码如下:

function deal_online(){ online.innerHTML=this.req.responseText; }

(5)为了让页面载入后,就调用Ajax 获取在线人员列表,并且每隔10秒钟,便获取一次数据,还需要在页面中添加以下JavaScript 代码。

window.setInterval("showOnline();",10000); window.onload=function(){ showOnline(); //当页面载入后显示在线人员列表

}

(6)细心的读者可以会发现,聊天对象文本框被设置为只读属性,这样用户就不能手动输入聊天对象,所以还需要提供选择聊天对象的功能,这可以通过在主页面中添加选择聊天对象的JavaScript 自定义函数及在在线人员列表上添加超链接实现。实现将选择的聊天对象添加到聊天对象文本框的JavaScript 代码如下:

(7)在在线人员列表上添加超链接,具体代码如下:

<%=username%>

A.3.3 实现用户发言

在聊天室程序中,一个必不可少的功能就是实现用户发言,在本章介绍的聊天室中,用户发言区位于聊天室主界面的底部,如图A.6所示。

图A.6 用户发言区

实现用户发言的具体步骤如下。

(1)在页面的合适位置添加用于收集用户发言信息的表单及表单元素,如表A.2所示。

表A.2 用户发言区所涉及的表单及表单元素

10

首先验证用户输入信息的合法性,然后再将提交的表单元素的内容连接为一个参数字符串,并实例化Ajax 对象。send()函数的具体代码如下:

function send(){ //验证聊天信息并发送 if(form1.to.value==""){ alert("请选择聊天对象!");return false; } if(form1.content1.value==""){ alert("发送信息不可以为空!");form1.content1.focus();return false; } var param="from="+form1.from.value+"&face="+form1.face.value+"&color="+form1.color.value+ "&to="+form1.to.value+"&content="+ form1.content1.value; var loader=new net.AjaxRequest("Messages?action=sendMessage",deal_send,onerror,"POST",param); }

(3)在聊天室相关的Servlet 实现类中,添加发送聊天信息的方法sendMessages()。在该方法中,首先获取用户发言相关信息,并对可能出现中文的信息进行转码,然后判断保存当天聊天信息的XML 文件是否存存,如果不存在,则创建该XML 文件,最后将聊天信息保存到XML 文件中,并重定向网页。sendMessages()方法的具体代码如下:

public void sendMessages(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

response.setContentType("text/html;charset=UTF-8"); request.setCharacterEncoding("UTF-8"); Random random = new Random();

String from = request.getParameter("from"); //发言人 String face = request.getParameter("face"); //表情 String to = request.getParameter("to"); //接收者 String color = request.getParameter("color"); //字体颜色 String content = request.getParameter("content"); //发言内容 String sendTime = new Date().toLocaleString(); //发言时间 ServletContext application = getServletContext();

String sourceMessage = application.getAttribute("message").toString(); try {

//发言时间

sourceMessage += "" + from + "" + face + "[" + to + "]说:" + "" + content + "(" + sendTime + ")
";

application.setAttribute("message", sourceMessage);

11

request.getRequestDispatcher("Messages?action=getMessages&nocache=" + random.nextInt(10000)).forward(request, response);

} catch (Exception ex) {

Logger.getLogger(Messages.class.getName()).log(Level.SEVERE, null, ex); } }

A.3.4 实时显示聊天内容

在聊天室程序中,另一个必不可少的功能就是实现显示聊天内容。这里介绍的聊天室中,聊天内容显示区位于聊天室主界面的右侧,如图A.7所示。

图A.7 聊天内容显示区

在实现显示聊天内容时,为了实时显示聊天内容,这里应用了Ajax 技术,关于Ajax 重构的方法,请参见A.2.1节。实现实时显示聊天内容的具体步骤如下。

(1)编写自定义的JavaScript 函数showContent(),用于实例化Ajax 对象。

showContent()函数的具体代码如下:

function showContent(){ var loader1=new net.AjaxRequest("Messages?action=getMessages&nocache="+ new Date().getTime(),deal_content,onerror,"GET"); }

(2)在聊天室相关的Servlet 实现类中,编写getMessages()方法,用于将页面重定向到显示聊天内容的JSP 页面。getMessages()方法的具体代码如下:

public void getMessages(HttpServletRequest request,HttpServletResponse response) { response.setContentType("text/html;charset=UTF-8"); try {

request.getRequestDispatcher("content.jsp").forward(request, response); } catch (Exception ex) {

Logger.getLogger(Messages.class.getName()).log(Level.SEVERE, null, ex); } }

(3)编写显示聊天内容的JSP 页面,在该页面中只需要应用EL 表达式将返回的执行结果输出即可,具体代码如下:

<%@page contentType="text/html" pageEncoding="UTF-8" %> ${message}

(4)在聊天室的主界面中,在右侧用于显示聊天内容的单元格,添加一个id 属性为content 的

标记,用于实时显示聊天内容。具体代码如下:

聊天内容

12

(5)编写Ajax 的回调函数deal_content(),在该函数中,首先获取Ajax 处理页的返回值,然后去除字中的Unicode 空白符,最后判断在获取信息时是否产生错误,如果是则退出聊天室,否则,将获取的聊天内容赋值给id 为content 的

标记的innerHTML 属性。deal_content()函数的具体代码如下:

function deal_content(){ var returnV alue=this.req.responseText; //获取Ajax 处理页的返回值 var h=returnV alue.replace(/\s/g,""); //去除字符串中的Unicode 空白符 if(h=="error"){ Exit(); }else{ content.innerHTML=sysBBS+returnValue+""; //当聊天信息超过一屏时,设置最先发送的聊天信息不显示 document.getElementById('content').scrollTop = document.getElementById('content').scrollHeight*2; } }

(6)为了让页面页面载入后,就调用Ajax 获取聊天内容,并且每隔1秒钟,便获取一次数据,还需要在页面中添加以下JavaScript 代码。

window.setInterval("showContent();",1000); window.onload=function(){ showContent(); //当页面载入后显示聊天内容

}

A.3.5 退出聊天室

在聊天室的主界面中,单击“退出聊天室”按钮,要以退出聊天室。实现退出聊天室的具体步骤如下:

(1)编写自定义的JavaScript 函数Exit(),在该函数中首先将页面重定向到退出聊天室页面leave.jsp ,然后再弹出“欢迎您下次光临!”对话框,具体代码如下:

function Exit(){

window.location.href="leave.jsp"; alert("欢迎您下次光临!"); }

(2)在“退出聊天室”按钮的onclick 事件中调用自定义的JavaScript 函数Exit(),关键代码如下:

(3)编写退出聊天室页面leave.jsp ,在该页面中,首先销毁Session ,然后将页面重定向到登录页面。leave.jsp 页面完成代码如下:

<%@page contentType="text/html" pageEncoding="UTF-8" %> <%

session.invalidate();

response.sendRedirect("index.jsp"); %>

相关主题
文本预览