9.1.5、QQ登陆聊天功能(服务端推送新闻、离线留言和文件)
9.1.5.1、服务端推送新闻
1、需求分析
2、思路分析
3、代码实现
QQServer:
1)cn.com.agree.qqserver.service.SendNewsToAllClient
package cn.com.agree.qqserver.service;
import cn.com.agree.qqcommon.Message;
import cn.com.agree.qqcommon.MessageType;
import cn.com.agree.stream.MyObjectOutputStream;
import cn.com.agree.util.Utility;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;
/**
* @version 1.0
* @ClassName SendNewsToAll
* @Description TODO 类描述
* @date 2024/1/12 11:37 上午
**/
@Slf4j
public class SendNewsToAllClient implements Runnable {
@Override
public void run() {
while (true) {
//构建消息对象
Message message = new Message();
message.setSender("服务器");
message.setMsgType(MessageType.MESSAGE_ONLINEAll_MS);
Scanner scanner = new Scanner(System.in);
log.debug("请输入要推送的服务器消息(输入exit退出):");
String news = scanner.next();
if("exit".equals(news)){
log.debug("服务器推送线程已退出");
break;
}
message.setContent(news);
message.setSendTime(new Date().toString());
log.debug(message.getSender()+" 对大家说: "+message.getContent());
//遍历服务端所有的用户id得到对应的线程socket转发给对应的客户端
Map<String, ServerConnectClient> hm = ManageServerConnectClient.getHm();
Iterator<String> iterator = hm.keySet().iterator();
while (iterator.hasNext()) {
String userId = iterator.next().toString();
try {
ObjectOutputStream oos = new MyObjectOutputStream(ManageServerConnectClient.getServerConnectClient(userId).getSocket().getOutputStream());
oos.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2)cn.com.agree.qqserver.service.qqServer
while (true) {
socket = serverSocket.accept();
//获取来自客户端发送过来到用户对象
log.debug("socket Client连接成功");
new Thread(new SendNewsToAllClient()).start();
ObjectInputStream bis = new MyObjectInputStream(socket.getInputStream());
User user = (User) bis.readObject();
//获取输出流对象写入返回给客户端的消息
ObjectOutputStream oos = new MyObjectOutputStream(socket.getOutputStream());
og.debug("user:{}",user);
Message message = new Message();
...
}
4、运行效果
9.1.5.2、离线留言和文件
1、需求分析
2、思路分析
3.1、代码实现(发送离线消息)
1)cn.com.agree.qqserver.service.ManageServerConnectClient
private static Map<String, List<Message>> notOnlineMessages = new ConcurrentHashMap<>();
public static void addNotOnlineMessage(String getterId, List<Message> messages){
notOnlineMessages.put(getterId, messages);
}
public static List<Message> getNotOnlineMessage(String getterId) {
return notOnlineMessages.get(getterId);
}
2)cn.com.agree.qqserver.service.ServerConnectClient
case MessageType.MESSAGE_COMM_MS:
log.debug("message:{}", message);
log.debug(message.getSender() + " 对 " + message.getGetter() + " 说: " + message.getContent());
ServerConnectClient connectClient = ManageServerConnectClient.getServerConnectClient(message.getGetter());
if(connectClient==null){
//做离线消息处理,将数据保存到数据库(这里保存到Map中)
if(ManageServerConnectClient.getNotOnlineMessage(message.getGetter())==null){
List<Message> messages = new ArrayList<>();
messages.add(message);
ManageServerConnectClient.addNotOnlineMessage(message.getGetter(),messages);
}else{
ManageServerConnectClient.getNotOnlineMessage(message.getGetter()).add(message);
}
}else {
//转发消息
ObjectOutputStream oos2 = new MyObjectOutputStream(connectClient.getSocket().getOutputStream());
oos2.writeObject(message);//如果用户不在线,可以保存到数据库做离线转发
}
break;
3) cn.com.agree.qqserver.service.qqServer
//去服务端查询是否有来自他的消息,有的话转发给对应的用户
List<Message> notOnlineMessage = ManageServerConnectClient.getNotOnlineMessage(user.getUserId());
if(notOnlineMessage!=null&¬OnlineMessage.size()>0){
for (Message message1 : notOnlineMessage) {
ObjectOutputStream oos2 = new MyObjectOutputStream(socket.getOutputStream());
oos2.writeObject(message1);
}
}
4.1、效果演示
上线后收到消息
3.2、代码实现(发送离线文件)
case MessageType.MESSAGE_FILE_MESSAGE:
//log.debug("message:{}", message);
log.debug(message.getSender()+" 给 "+message.getGetter()+" 发送了 "+message.getSrc()+" 到我的电脑的 "+message.getDesc()+" 路径");
ServerConnectClient serverConnectClient = ManageServerConnectClient.getServerConnectClient(message.getGetter());
if(serverConnectClient==null){
//做离线消息处理,将数据保存到数据库(这里保存到Map中)
if(ManageServerConnectClient.getNotOnlineMessage(message.getGetter())==null){
List<Message> messages = new ArrayList<>();
messages.add(message);
ManageServerConnectClient.addNotOnlineMessage(message.getGetter(),messages);
}else{
ManageServerConnectClient.getNotOnlineMessage(message.getGetter()).add(message);
}
}else {
//进行转发给客户端
ObjectOutputStream oos4= new MyObjectOutputStream(serverConnectClient.socket.getOutputStream());
oos4.writeObject(message);
}
break;
4.2、效果展示
300上线后成功接收