先在接受客户端消息的逻辑块中,先判断接受方是否在线,将其拆分为两种情况,如果对方在线,那么由服务器将消息转发给接收方,如果对方不在线,那么将其加入到一个key为用户id,value为一个消息集合(ArrayList)的离线集合(ConcurrentHashMap)中,当用户登录时判断该用户的id是否存在于该集合的key中,如果存在,那么通过id,获取到对应的消息集合(ArrayList),通过用户id获取到对应的socket,将消息集合发送到客户端
客户端思路:在客户端的线程中,对接受的object对象使用instance of判断其运行类型,如果为message对象,则进行之前的逻辑,如果为ArrayList对象,则遍历其中所有的message对象,取出内容并打印。
服务器端的新增代码 编写一个OffLineMessageService类 用来处理离线消息####package qqserver.service;
import CommonServerClient.Message;
import org.junit.Test;
import sun.net.util.IPAddressUtil;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
@SuppressWarnings({"all"})
public class OffLineMessageService {
//key->getterId value->contents
private static ConcurrentHashMap offlineMap=new ConcurrentHashMap();
public static ConcurrentHashMap getOfflineMap() {
return offlineMap;
}
public static void setOfflineMap(ConcurrentHashMap offlineMap) {
OffLineMessageService.offlineMap = offlineMap;
}
@Test
public void test(){
HashMap ssHashMap = new HashMap<>();
ssHashMap.put("string","hello");
System.out.println(ssHashMap.containsKey("string"));
}
//将离线消息存入到集合中
//编写getter不在线 并将离线消息添加到offlineMap
public static void addOfflineMap(Message message){
//如果getter不存在 那么创建一个ArrayList 并将message放入
if(!offlineMap.containsKey(message.getGetter())){
ArrayList messages = new ArrayList<>();
messages.add(message);
offlineMap.put(message.getGetter(),messages);
}
else {
ArrayList arrayList = offlineMap.get(message.getGetter());
arrayList.add(message);
}
System.out.println("离线消息已经存放在offlineMap中");
}
//编写方法判断user是否存在于offlineMap中 如果存在 就获取对应getter的socket 将ArrayList中的所有内容发送
public static void sendOfflineMessage(String userId,ConcurrentHashMap offlineMap){
if (offlineMap.containsKey(userId)){
try {
ArrayList arrayList = (ArrayList) offlineMap.get(userId);
OutputStream os = ManageClientThread.getServerConnectClientThread(userId).getSocket().getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
//将message集合发送到客户端
oos.writeObject(arrayList);
System.out.println("发送成功");
} catch (IOException e) {
e.printStackTrace();
}
}
else System.out.println("发送失败");
}
//编写方法判断getter是否在线
public static boolean isOnline(String getterId){
HashMap hm = ManageClientThread.getHm();
return hm.containsKey(getterId);
}
//将离线消息从offlineMap删除
public static void deleteOfflineMessage(String getterId){
ArrayList remove = offlineMap.remove(getterId);
System.out.println("删除消息成功"+remove);
}
}
在接受客户端消息时 判断接收方是否在线 并将离线消息加入到集合中
if(message.getMesType().equals(MessageType.MESSAGE_COMM_MES)){
//写一个方法 判断getter是否在线 不在线的话 将message对象存入到集合中
if (!OffLineMessageService.isOnline(message.getGetter())){
System.out.println("该用户不在线 将在登录后接受到消息");
OffLineMessageService.addOfflineMap(message);
}
else {
//根据message获取getterId 在得到对应的线程
ServerConnectClientThread serverConnectClientThread = ManageClientThread.getServerConnectClientThread(message.getGetter());
OutputStream outputStream = serverConnectClientThread.getSocket().getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(outputStream);
oos.writeObject(message);
}
用户登录成功后调用方法发送离线消息
if(checkUser(u.getUserId(),u.getPassword())){//验证通过
message.setMesType(MessageType.MESSAGE_LOGIN_SUCCEED);
//将message对象回复
oos.writeObject(message);
//创建一个线程,和客户端保持通讯,该线程持有socket对象
ServerConnectClientThread serverConnectClientThread = new ServerConnectClientThread(socket, u.getUserId());
serverConnectClientThread.start();
//把该线程对象放入到集合中进行管理
ManageClientThread.addClientThread(u.getUserId(),serverConnectClientThread);
ConcurrentHashMap offlineMap = OffLineMessageService.getOfflineMap();
//发送离线消息
OffLineMessageService.sendOfflineMessage(u.getUserId(),offlineMap);
OffLineMessageService.deleteOfflineMessage(u.getUserId());
}
else {
System.out.println("用户 id=" + u.getUserId() + " pwd=" + u.getPassword() + " 验证失败");
message.setMesType(MessageType.MESSAGE_LOGIN_FAIL);
oos.writeObject(message);
//关闭socket
socket.close();
}
客户端新增代码
@Override
public void run() {
//因为需要在后台和服务器通讯,因此做成while循环
while (true){
try {
System.out.println("客户端线程等待读取服务器端发送的消息");
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
//处理读入的对象
Object o = ois.readObject();//如果服务器没有发送objec对象,线程会阻塞在这里
if (o instanceof ArrayList){
ArrayList messageArrayList=(ArrayList)o;
System.out.println("以下是您的离线消息:⬇");
for (Message message : messageArrayList) {
System.out.println(message.getSender()+": "+message.getContent()+" time:");
}
}
else
{
Message message=(Message)o;
//判断message类型 然后做相应的业务处理
//如果读取到的式服务得到的返回在线用户列表
if (message.getMesType().equals(MessageType.MESSAGE_RET_ONLINE_FRIEND)){
//取出在线列表信息,并显示
String[] onlineUsers = message.getContent().split(" ");
System.out.println("========当前在线用户列表========");
for (int i = 0; i
第一篇文章 记录学习过程哈 兄弟们都加油
暑期编程PK赛
得CSDN机械键盘等精美礼品! 


