深入剖析聊天系统的类设计
在开发聊天系统时,合理的类设计至关重要。它不仅能提高系统的可维护性和扩展性,还能确保系统的性能和稳定性。下面将详细介绍聊天系统中各个关键类的设计和功能。
1. 打开存储并管理上下文
首先,需要打开存储并将其作为上下文的值进行管理。以下是相关代码:
// Öffne den Store
try {
Configuration theStoreConfig =
ConfigManager.getConfigManager().getConfiguration(
aContextName, theStorename, true);
theStore = StoreFactory.getInstance(theStoreConfig);
}
catch (PersistenceException pe) {
throw new SMIException(pe);
}
// Hinterlege den Store als Wert dieses Kontextes
// unter dem Schlüssel C_Store
putValue(C_Store, theStore);
这段代码的操作步骤如下:
1. 通过
ConfigManager
获取存储配置。
2. 使用
StoreFactory
根据配置实例化存储对象。
3. 将存储对象作为上下文的值,以
C_Store
为键进行存储。
2. 管理聊天参与者
为了管理聊天参与者,引入了
ChatSwitch
类。它继承自
SMIEventSwitch
,并在
init
方法中添加了用户列表。以下是
ChatSwitch
类的代码:
package de.webapp.Chat ;
import de.webapp.Framework.SMI.* ;
import java.util.Hashtable;
public class ChatSwitch extends SMIEventSwitch implements C_Chat {
/** Fügt dem Switch eine Nutzerliste hinzu. */
public void init(String aSwitchName, I_SMIContext aSMIContext)
throws SMIException {
super.init(aSwitchName, aSMIContext);
putValue(C_Userlist, new Hashtable());
}
}
操作步骤如下:
1. 继承
SMIEventSwitch
类。
2. 重写
init
方法。
3. 在
init
方法中,使用
putValue
方法将一个新的
Hashtable
作为用户列表,以
C_Userlist
为键存储在
SMIEventSwitch
中。
3. 方便访问用户列表和存储的基类
为了方便后续的
I_SMICommandListener
类访问用户列表和存储,创建了
ChatBean
基类。它封装了用户对象的管理,并对
executeSMIEvent
方法进行了重写。以下是
ChatBean
类的代码:
package de.webapp.Chat;
import java.util.Hashtable;
import de.webapp.Framework.SMI.*;
import de.webapp.Framework.Persistence.*;
/** Basisklasse für weitere ChatBeans */
public class ChatBean extends SMICommandListener implements C_Chat {
/** Setzt die Nutzerliste und führt Folgekommando aus */
public void executeSMIEvent(SMIEvent aSMIEvent) {
SMICommand aSMICommand = (SMICommand)aSMIEvent;
// Nutzerliste setzen
aSMICommand.putValue(C_Userlist, getUserlist());
// Kommando ausführen
super.executeSMIEvent(aSMICommand);
// Gegebenenfalls Folgekommando ausführen
String theFollowUpCommand =
(String)aSMICommand.getValue(C_FollowUpCommand);
if (theFollowUpCommand != null) {
aSMICommand.setCommand(theFollowUpCommand);
aSMICommand.removeValue(C_FollowUpCommand);
getSMIEventSwitch().executeSMIEvent(aSMICommand);
}
}
/** Leere Methode, falls executeSMIEvent() ausreicht */
public void noop(SMICommand aSMICommand) {}
/** Gibt das Nutzer-Objekt aus der Session zurück */
protected User getUser(SMICommand aSMICommand) {
return (User)aSMICommand.getSessionValue(C_User);
}
/** Hinterlegt ein Nutzer-Objekt in der Session */
protected void setUser(SMICommand aSMICommand, User aUser) {
aSMICommand.putSessionValue(C_User, aUser);
}
/** Entfernt ein Nutzer-Objekt aus der Session */
protected void removeUser(SMICommand aSMICommand) {
aSMICommand.removeSessionValue(C_User);
}
/** Gibt die Nutzerliste des Switches zurück */
protected Hashtable getUserlist() {
return (Hashtable)getSMIEventSwitch().getValue(C_Userlist);
}
/** Gibt den Store des I_SMIContextes zurück */
protected I_Store getStore() {
return (I_Store)getSMIEventSwitch().getSMIContext().getValue(C_Store);
}
}
操作步骤如下:
1. 继承
SMICommandListener
类。
2. 重写
executeSMIEvent
方法:
- 将用户列表设置到
SMICommand
中。
- 执行当前命令。
- 若存在后续命令,设置命令并执行。
3. 提供
getUser
、
setUser
和
removeUser
方法,用于管理用户对象在会话中的存储和获取。
4. 提供
getUserlist
和
getStore
方法,用于获取用户列表和存储对象。
4. 消息类的设计
在聊天系统中,消息是核心元素。通过
Message
类来封装消息,包含发送者和消息文本。以下是
Message
类的代码:
package de.webapp.Chat ;
/** Kapselt eine Nachricht */
public class Message {
protected User myFrom;
protected String myText;
/** Konstruktor */
public Message(User aFrom, String aText) {
myFrom = aFrom;
myText = aText;
}
/** Gibt den Absender zurück */
public User getFrom() {
return myFrom;
}
/** Gibt den Nachrichtentext zurück */
public String getText() {
return myText;
}
}
操作步骤如下:
1. 定义
Message
类,包含
User
类型的发送者和
String
类型的消息文本。
2. 提供构造函数,用于初始化发送者和消息文本。
3. 提供
getFrom
和
getText
方法,用于获取发送者和消息文本。
5. 用户对象的设计
用户对象是聊天系统中的重要组成部分。
User
类继承自
Persistence
,实现了
I_Persistence
接口,并具备用户管理和消息处理的功能。以下是
User
类的部分代码:
package de.webapp.Chat;
import java.util.*;
import java.io.*;
import java.sql.*;
import javax.servlet.http.*;
import de.webapp.Framework.Persistence.*;
import de.webapp.Framework.Log.*;
/** Nutzer des Chats */
public class User extends Persistence
implements C_Chat, HttpSessionBindingListener {
/** Name des Nutzers */
protected String myName;
/** Paßwort des Nutzers */
protected String myPassword;
/** Sendefarbe des Nutzers */
protected Integer myColor;
/** Chatraum, in dem sich der Nutzer befindet */
protected transient ChatRoom myChat;
/** Nachrichtenschlange */
protected transient Vector myMessageQueue;
/** Zeitpunkt, zu dem die letzte Nachricht gesendet wurde */
protected transient long myLastMessage;
/** Zeigt an, ob das asynchrone Schreiben der Nachrichten gestoppt wurde */
protected transient boolean stopped;
/** Aktuelle benutzter I_MessageWriter */
protected transient I_MessageWriter myWriter;
/** Geschützter -Konstruktor */
protected User() {}
/** Konstruktor mit Peer */
public User(I_PersistencePeer aPeer) throws PersistenceException {
super(aPeer);
init();
}
/** Konstruktor mit Peer und ResultSet */
public User(I_PersistencePeer aPeer, ResultSet rs)
throws PersistenceException {
super(aPeer, rs);
init();
}
/** Konstruktor mit Peer, ResultSet und ObjectIdentifier (für MS-Access) */
public User(I_PersistencePeer aPeer, ResultSet rs,
String aObjectIdentifier)
throws PersistenceException {
this(aPeer);
this.bind(rs, aObjectIdentifier);
}
/** Initialisierung */
protected void init() {
myMessageQueue = new Vector();
myChat = null;
myWriter = null;
stopped = false;
}
// 其他方法...
}
操作步骤如下:
1. 继承
Persistence
类,实现
C_Chat
和
HttpSessionBindingListener
接口。
2. 定义用户的属性,如姓名、密码、发送颜色等。
3. 提供多个构造函数,用于初始化用户对象。
4. 提供
init
方法,初始化消息队列、聊天室、消息写入器等。
6. 消息发送器
ChatDispatcher
类负责消息的发送。它继承自
ChatBean
,实现了
sendMessage
命令。以下是
ChatDispatcher
类的代码:
package de.webapp.Chat;
import java.util.*;
import java.io.*;
import de.webapp.Framework.SMI.*;
import de.webapp.Framework.Persistence.*;
import de.webapp.Framework.Log.*;
/** Übernimmt das Versenden von Nachrichten */
public class ChatDispatcher extends ChatBean implements C_Chat {
/** Sendet eine Nachricht */
public void send(SMICommand aSMICommand) throws PersistenceException {
// Nutzer überhaupt noch eingeloggt?
User theUser = getUser(aSMICommand);
if (theUser == null) {
aSMICommand.putValue(C_Template,
aSMICommand.getValue("userNotLoggedIn"));
return;
}
// Zeitstempel setzen
theUser.touch();
// Parameter aus der Anfrage lesen
// theTo enthält die ObjectIdentifier der Adressaten
String[] theTo = aSMICommand.getRequest().getParameterValues(C_To);
// theText enthält die Nachricht
String theText = (String)aSMICommand.getValue(C_Message);
// wenn theToAll != null ist, ist die Nachricht an alle
String theToAll = (String)aSMICommand.getValue(C_All);
// theColor enthält die Farbe als Integer
Integer theColor = new Integer((String)aSMICommand.getValue(C_Color));
if (!theColor.equals(theUser.getColor())) {
// gegebenenfalls Farbe persistent speichern
updateColor(aSMICommand);
}
// Nachricht nur versenden, wenn es auch Adressaten gibt
if (theTo != null || theToAll != null) {
Message theMessage = new Message(theUser, theText);
if (theToAll==null) {
// Private Messages einzeln zustellen
// eine Kopie an den Absender soll in jedem Fall dabei sein
theMessage.getFrom().handleMessage(theMessage);
for (int i=0; i < theTo.length; i++) {
User aUser = (User)getUserlist().get(theTo[i]);
if (aUser != null && aUser != theMessage.getFrom())
aUser.handleMessage(theMessage);
}
}
else {
// allgemeine Methode für alle
for (Enumeration e = getUserlist().elements();
e.hasMoreElements();) {
User aUser = (User)e.nextElement();
if (aUser != null) aUser.handleMessage(theMessage);
}
}
}
}
/** Speichert das NutzerObjekt mit neuer Farbe */
protected void updateColor(SMICommand aSMICommand)
throws PersistenceException {
// Store besorgen
I_Store theStore = getStore();
User theUser = getUser(aSMICommand);
synchronized(theStore) {
theUser.setColor(
new Integer((String)aSMICommand.getValue(C_Color)));
try {
theStore.begin();
theUser.update();
theStore.commit();
}
catch (Throwable t) {
theStore.rollback();
if (t instanceof PersistenceException) {
throw (PersistenceException)t;
}
throw new SMIEventListenerException(t);
}
}
}
}
操作步骤如下:
1. 继承
ChatBean
类。
2. 实现
send
方法:
- 检查用户是否登录。
- 设置用户的时间戳。
- 读取请求参数,如收件人、消息内容、是否发送给所有人、颜色等。
- 若颜色有变化,调用
updateColor
方法更新颜色。
- 根据收件人情况,发送消息给指定用户或所有人。
3. 实现
updateColor
方法,用于更新用户的颜色并持久化存储。
7. 用户注册和更新
ChatRegistration
类负责用户的注册和更新操作。以下是
ChatRegistration
类的代码:
package de.webapp.Chat;
import java.util.*;
import java.io.*;
import de.webapp.Framework.SMI.*;
import de.webapp.Framework.Persistence.*;
import de.webapp.Framework.Log.*;
/** Manipulation eines Nutzer-Objekts */
public class ChatRegistration extends ChatBean implements C_Chat {
/** Erzeugt ein Nutzer-Objekt und hinterlegt es in der HttpSession */
public void create(SMICommand aSMICommand) throws PersistenceException {
// Store besorgen.
I_Store theStore = getStore();
User theUser;
// Store nach neuem Persistence des Typs "User" fragen
theUser = (User)theStore.newPersistence("User");
// Attribute setzen und eventuell Fehlermeldung ausgeben
if (!setAttributes(aSMICommand, theUser)) {
aSMICommand.putValue(C_ErrorMessage,
"Ihre Eingaben waren fehlerhaft. "
+ "Bitte versuchen Sie es nocheinmal.");
aSMICommand.putValue(C_Template, aSMICommand.getValue("failure"));
return;
}
// Store sichern
synchronized(theStore) {
try {
theStore.begin();
theUser.create();
theStore.commit();
// User in der HttpSession hinterlegen -> ChatBean
setUser(aSMICommand, theUser);
}
// wenn canCreate() false zurückgibt, wird eine
// PersistenceRuntimeException ausgelöst.
// => Fehlermeldung ausgeben.
catch (PersistenceRuntimeException pre) {
theStore.rollback();
aSMICommand.putValue(C_ErrorMessage,
"Der Name, den Sie gewählt haben, ist belegt.");
aSMICommand.putValue(C_Template,
aSMICommand.getValue("failure"));
}
catch (Throwable t) {
theStore.rollback();
if (t instanceof PersistenceException) {
throw (PersistenceException)t;
}
throw new SMIEventListenerException(t);
}
}
}
/** Speichert Änderungen eines Nutzer-Objekts in der Datenbank */
public void update(SMICommand aSMICommand) throws PersistenceException {
// Nutzer aus der HttpSession lesen
User theUser = getUser(aSMICommand);
// falls kein Nutzer vorhanden, Fehlermeldung ausgeben
if (theUser == null) {
aSMICommand.putValue(C_Template,
aSMICommand.getValue("userNotLoggedIn"));
return;
}
// Store besorgen.
I_Store theStore = getStore();
// Attribute setzen und eventuell Fehlermeldung ausgeben
if (!setAttributes(aSMICommand, theUser)) {
aSMICommand.putValue(C_ErrorMessage,
"Ihre Eingaben waren fehlerhaft. "
+ "Bitte versuchen Sie es noch einmal.");
aSMICommand.putValue(C_Template, aSMICommand.getValue("failure"));
return;
}
// Store sichern
synchronized(theStore) {
try {
theStore.begin();
theUser.update();
theStore.commit();
}
// wenn canUpdate() false zurückgibt, wird eine
// PersistenceRuntimeException ausgelöst.
// => Fehlermeldung ausgeben.
catch (PersistenceRuntimeException pre) {
theStore.rollback();
aSMICommand.putValue(C_ErrorMessage,
"Der Name, den Sie gewählt haben, ist belegt.");
aSMICommand.putValue(C_Template,
aSMICommand.getValue("failure"));
}
catch (Throwable t) {
theStore.rollback();
if (t instanceof PersistenceException) {
throw (PersistenceException)t;
}
throw new SMIEventListenerException(t);
}
}
}
/** Setzt die Attribute eines Persistence und gibt false zurück,
falls die Werte nicht sinnvoll sind */
protected boolean setAttributes(SMICommand aSMICommand, User aUser) {
// Werte aus dem Kommando lesen.
String thePassword1 = (String)aSMICommand.getValue(C_Password);
String thePassword2 = (String)aSMICommand.getValue(C_Password2);
String theUsername = (String)aSMICommand.getValue(C_Username);
// 其他逻辑...
}
}
操作步骤如下:
1. 继承
ChatBean
类。
2. 实现
create
方法:
- 从存储中获取新的用户对象。
- 设置用户属性,若属性设置失败,显示错误信息。
- 开启事务,创建用户对象并提交事务。
- 将用户对象存储到会话中。
- 若创建失败,回滚事务并显示错误信息。
3. 实现
update
方法:
- 从会话中获取用户对象,若用户不存在,显示错误信息。
- 设置用户属性,若属性设置失败,显示错误信息。
- 开启事务,更新用户对象并提交事务。
- 若更新失败,回滚事务并显示错误信息。
4. 实现
setAttributes
方法,用于设置用户属性。
通过以上这些类的设计和实现,我们可以构建一个功能完善的聊天系统。每个类都有其特定的职责,相互协作,确保系统的正常运行。在实际开发中,我们可以根据具体需求对这些类进行扩展和优化。
下面是一个简单的类关系图,展示了各个类之间的关系:
classDiagram
class SMIEventSwitch
class SMICommandListener
class Persistence
class I_Persistence
class I_SMIContext
class I_Store
class I_MessageWriter
class ChatContext
class ChatSwitch
class ChatBean
class Message
class User
class ChatDispatcher
class ChatRegistration
class HTMLMessageWriter
SMIEventSwitch <|-- ChatSwitch
SMICommandListener <|-- ChatBean
Persistence <|-- User
User ..|> I_Persistence
ChatContext *-- I_Store
ChatSwitch *-- I_SMIContext
ChatBean *-- ChatSwitch
ChatBean *-- I_Store
Message *-- User
User *-- I_MessageWriter
ChatBean <|-- ChatDispatcher
ChatBean <|-- ChatRegistration
I_MessageWriter <|.. HTMLMessageWriter
这个类关系图清晰地展示了各个类之间的继承、关联和依赖关系,有助于我们更好地理解整个聊天系统的架构。
综上所述,合理的类设计是构建高效、稳定聊天系统的基础。通过对各个类的功能和职责进行明确划分,我们可以提高代码的可维护性和扩展性,为后续的开发和优化提供便利。
深入剖析聊天系统的类设计
8. 消息写入器接口与实现
在聊天系统中,消息的写入需要一个统一的接口和具体的实现。
I_MessageWriter
接口定义了消息写入的基本方法,而
HTMLMessageWriter
类则是该接口的一个具体实现,用于将消息以 HTML 格式写入。
以下是
I_MessageWriter
接口的代码:
package de.webapp.Chat;
import java.io.IOException;
/** Definiert einen Nachrichten-Schreiber */
public interface I_MessageWriter {
/** Schreibt eine Nachricht */
public void write(Message aMessage) throws IOException;
/** Zeigt an, ob dieser I_MessageWriter noch schreiben kann */
public boolean canWrite();
}
操作步骤如下:
1. 定义
write
方法,用于写入消息,可能会抛出
IOException
异常。
2. 定义
canWrite
方法,用于检查是否还能继续写入消息。
以下是
HTMLMessageWriter
类的代码:
package de.webapp.Chat;
import java.io.*;
public class HTMLMessageWriter implements I_MessageWriter, C_Chat {
public HTMLMessageWriter(Writer aWriter) {
myWriter = aWriter;
}
protected int mySentBytes;
protected Writer myWriter;
/** Schreibt eine Nachricht mit dem aktuellen Writer. */
public void write(Message aMessage) throws IOException {
StringBuffer theOutput = new StringBuffer();
theOutput.append(aMessage.getFrom().getName());
theOutput.append(": <font color=\""
+ C_Colors[aMessage.getFrom().getColor().intValue()]+ "\">");
theOutput.append(aMessage.getText());
theOutput.append("</font><p>");
myWriter.write(theOutput.toString());
myWriter.flush();
mySentBytes += theOutput.length();
}
/** Überprüft, ob noch geschrieben werden kann. */
public boolean canWrite() {
if (myWriter instanceof PrintWriter) {
((PrintWriter)myWriter).println();
return (!((PrintWriter)myWriter).checkError() && mySentBytes < C_MaxBytes);
}
try {
myWriter.flush();
}
catch (IOException ioe) {
return false;
}
return true;
}
}
操作步骤如下:
1. 实现
I_MessageWriter
接口和
C_Chat
接口。
2. 提供构造函数,接收一个
Writer
对象。
3. 实现
write
方法:
- 构建包含发送者姓名、消息内容和颜色的 HTML 字符串。
- 使用
Writer
对象写入该字符串并刷新。
- 记录已发送的字节数。
4. 实现
canWrite
方法:
- 若
Writer
是
PrintWriter
类型,检查是否有错误且已发送字节数是否小于最大字节数。
- 否则,尝试刷新
Writer
,若抛出异常则返回
false
,否则返回
true
。
9. 用户对象的持久化与属性管理
用户对象的持久化和属性管理是聊天系统的重要组成部分。
User
类继承自
Persistence
类,实现了
I_Persistence
接口,确保用户对象可以持久化存储。同时,它还管理用户的属性,如姓名、密码和发送颜色。
以下是
User
类的属性和方法相关代码:
package de.webapp.Chat;
import java.util.*;
import java.io.*;
import java.sql.*;
import javax.servlet.http.*;
import de.webapp.Framework.Persistence.*;
import de.webapp.Framework.Log.*;
/** Nutzer des Chats */
public class User extends Persistence
implements C_Chat, HttpSessionBindingListener {
/** Name des Nutzers */
protected String myName;
/** Paßwort des Nutzers */
protected String myPassword;
/** Sendefarbe des Nutzers */
protected Integer myColor;
// 其他属性...
/** Gibt den Namen zurück */
public String getName() {
return myName;
}
/** Setzt den Namen */
public void setName(String aName) {
myName = aName;
// Zustandsänderung!
setModified();
}
/** Gibt das Paßwort zurück */
public String getPassword() {
return myPassword;
}
/** Setzt das Paßwort */
public void setPassword(String aPassword) {
myPassword = aPassword;
// Zustandsänderung!
setModified();
}
/** Gibt die Farbe zurück */
public Integer getColor() {
return myColor;
}
/** Setzt die Farbe */
public void setColor(Integer aColor) {
myColor = aColor;
setModified();
}
// 其他方法...
}
操作步骤如下:
1. 定义用户的属性,如
myName
、
myPassword
和
myColor
。
2. 提供
getName
、
getPassword
和
getColor
方法,用于获取用户的属性值。
3. 提供
setName
、
setPassword
和
setColor
方法,用于设置用户的属性值,并在属性修改时调用
setModified
方法标记状态更改。
10. 用户对象的验证与持久化操作
为了确保用户对象的唯一性和数据的一致性,
User
类提供了
canCreate
和
canUpdate
方法进行验证,同时实现了持久化操作的相关方法。
以下是相关代码:
package de.webapp.Chat;
// 导入相关包...
/** Nutzer des Chats */
public class User extends Persistence
implements C_Chat, HttpSessionBindingListener {
// 属性和构造函数...
/** Prüft, ob ein Nutzer-Objekt erzeugt werden darf */
public boolean canCreate() throws PersistenceException {
return isNameFree();
}
/** Prüft, ob ein Nutzer-Objekt persistent geändert werden darf */
public boolean canUpdate() throws PersistenceException {
return isNameFree();
}
/** Zeigt an, ob ein Name bereits von einem anderen Objekt belegt ist */
protected boolean isNameFree() throws PersistenceException {
I_Persistence sameName =
getPeer().getRetriever().retrieve(getAttribute("Name"), myName);
return (sameName == null || sameName == this);
}
/** Hilfsmethode zum Erlangen einen PersistenceAttribute-Objekts */
protected PersistenceAttribute getAttribute(String aAttributeName) {
return getPeer().getType().getAttributeWithName(aAttributeName);
}
// 其他方法...
}
操作步骤如下:
1. 实现
canCreate
方法,调用
isNameFree
方法检查是否可以创建用户对象。
2. 实现
canUpdate
方法,同样调用
isNameFree
方法检查是否可以更新用户对象。
3. 实现
isNameFree
方法:
- 通过
getPeer().getRetriever().retrieve
方法查找是否有同名的用户对象。
- 若没有同名对象或同名对象就是当前对象,则返回
true
,否则返回
false
。
4. 实现
getAttribute
方法,用于获取指定名称的
PersistenceAttribute
对象。
11. 用户对象的消息处理
用户对象需要处理接收到的消息,
User
类提供了
handleMessage
和
writeMessages
方法来实现消息的接收和写入。
以下是相关代码:
package de.webapp.Chat;
// 导入相关包...
/** Nutzer des Chats */
public class User extends Persistence
implements C_Chat, HttpSessionBindingListener {
// 属性和构造函数...
/** Schreibt eine Nachricht in die Nachrichtenschlange und
benachrichtigt einen wartenden Thread */
public void handleMessage(Message aMessage) {
myMessageQueue.addElement(aMessage);
synchronized (this) {
notify();
}
}
/** Schreibt Nachrichten mit dem übergebenen I_MessageWriter bis
canWrite() false zurückgibt oder stopped true ist */
public synchronized void writeMessages(I_MessageWriter aWriter) {
// wartende Threads, die nicht mehr schreiben können
// (canWrite() == false) die Chance zum verlassen dieser Methode
// und myWriter = null zu setzen
notify();
// Falls ein anderer Writer noch funktionstüchtig
// ist, Ausnahme auslösen
if (myWriter != null) throw new IllegalStateException();
// Writer übernehmen
myWriter = aWriter;
try {
// Schreibschleife
while(myWriter.canWrite() && !stopped) {
// Nachrichtenschlange leerschreiben
while (myMessageQueue.size() > 0 && myWriter.canWrite()
&& !stopped) {
Message theMessage = (Message)myMessageQueue.elementAt(0);
myWriter.write(theMessage);
myMessageQueue.removeElementAt(0);
}
try {
// Mindestens alle 10 Sekunden aufwachen, um zu testen,
// ob der Writer noch funktioniert und das asynchrone
// Schreiben noch nicht gestoppt wurde.
wait(10000);
}
catch (InterruptedException ie) {}
}
}
catch (IOException ioe) {
if (Log.isLog()) {
Log.log(ioe);
}
}
// Writer auf null setzen
myWriter = null;
}
// 其他方法...
}
操作步骤如下:
1. 实现
handleMessage
方法:
- 将接收到的消息添加到消息队列
myMessageQueue
中。
- 同步块中调用
notify
方法唤醒可能等待的线程。
2. 实现
writeMessages
方法:
- 调用
notify
方法唤醒可能等待的线程。
- 检查是否已有其他
I_MessageWriter
在使用,若有则抛出异常。
- 接收传入的
I_MessageWriter
对象。
- 进入循环,只要
I_MessageWriter
可以写入且
stopped
标志为
false
,就继续处理消息。
- 在内部循环中,从消息队列中取出消息并使用
I_MessageWriter
写入,同时移除已处理的消息。
- 每 10 秒唤醒一次线程,检查
I_MessageWriter
是否还能工作以及
stopped
标志。
- 若发生
IOException
,记录日志。
- 最后将
myWriter
置为
null
。
12. 用户对象与会话的绑定与解绑
为了实现用户对象与
HttpSession
的绑定和解绑,
User
类实现了
HttpSessionBindingListener
接口,提供了
valueBound
和
valueUnbound
方法。
以下是相关代码:
package de.webapp.Chat;
// 导入相关包...
/** Nutzer des Chats */
public class User extends Persistence
implements C_Chat, HttpSessionBindingListener {
// 属性和构造函数...
/** Beim Binden dieses Objekts an die HttpSession den Referenzzähler erhöhen */
public void valueBound(HttpSessionBindingEvent e) {
if (Log.isLog(C_Log.METHOD)) {
Log.log("User " + getName()
+ " wurde an die HttpSession gebunden.", C_Log.METHOD);
}
retain();
}
/** Beim Entbinden dieses Objekts von der HttpSession den Referenzzähler erniedrigen,
beim Chat abmelden und die Chatassoziation löschen */
public void valueUnbound(HttpSessionBindingEvent e) {
if (Log.isLog(C_Log.METHOD)) {
Log.log("User " + getName()
+ " wurde von der HttpSession entbunden.", C_Log.METHOD);
}
release();
if (myChat != null) myChat.unregister(this);
removeChat();
}
// 其他方法...
}
操作步骤如下:
1. 实现
valueBound
方法:
- 若日志开启,记录用户绑定到
HttpSession
的信息。
- 调用
retain
方法增加引用计数。
2. 实现
valueUnbound
方法:
- 若日志开启,记录用户从
HttpSession
解绑的信息。
- 调用
release
方法减少引用计数。
- 若用户在聊天室中,调用
myChat.unregister
方法从聊天室注销。
- 调用
removeChat
方法移除与聊天室的关联。
13. 总结与展望
通过上述对聊天系统各个类的详细分析,我们可以看到一个完整的聊天系统是如何通过合理的类设计构建起来的。每个类都有其明确的职责,相互协作,实现了用户管理、消息发送、消息接收和持久化存储等功能。
在实际应用中,我们可以根据具体需求对这些类进行扩展和优化。例如,可以添加更多的消息类型,实现更复杂的消息处理逻辑;可以优化持久化存储的性能,提高系统的响应速度;还可以增加更多的用户管理功能,如用户权限管理、用户信息修改等。
未来的发展方向可以包括引入实时通信技术,如 WebSocket,实现更实时的消息交互;结合人工智能技术,实现智能聊天机器人,提供更智能的服务;以及优化系统的安全性,防止信息泄露和恶意攻击。
以下是一个简单的消息处理流程图,展示了消息从发送到接收的过程:
graph LR
A[发送者] --> B[ChatDispatcher]
B --> C{消息类型}
C -->|私聊| D[指定用户]
C -->|群聊| E[所有用户]
D --> F[User.handleMessage]
E --> F
F --> G[消息队列]
G --> H[User.writeMessages]
H --> I[I_MessageWriter]
I --> J[接收者界面]
这个流程图清晰地展示了消息在聊天系统中的传递过程,有助于我们更好地理解系统的工作原理。
总之,合理的类设计是构建高效、稳定聊天系统的关键。通过不断地优化和扩展,我们可以为用户提供更好的聊天体验。
398



被折叠的 条评论
为什么被折叠?



