仿牛客网社区项目(十七)私信列表
私信列表
- 私信列表
- 查询当前用户的会话列表, 每个会话只显示一条最新的私信。
- 支持分页显示。
- 私信详情
- 查询某个会话所包含的私信。
- 支持分页显示。
首先看一下数据库的设计,私信相当于一个对话功能,那么两个人就组成一个对话,这段对话里有A发给B的消息,有B发给A的消息,那么我们把发送者和接收者的id拼接到一起形成一个会话id,把id小的拼接在前面。还有一种私信是系统通知,那么只需要把from_id指定一个固定的值,这里指定为1。
实体类#
新建Message实体类,对应数据库字段。
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Message {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
private Integer fromId;
private Integer toId;
private String conversationId;
private String content;
private int status;//这里status是int类型的 不然sql语句会出问题
private Date createTime;
}
数据层#
新建MessageMapper,定义好方法。私信列表需要显示的内容:
package com.neu.langsam.community.dao;
import com.neu.langsam.community.entity.Message;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface MessageMapper {
//查询当前用户的会话列表,针对每个会话只返回一条最新的私信
List<Message> selectConversations(int userId,int offset,int limit);
//查询当前用户的会话数量
int selectConversationCount(int userId);
//查询某个会话所包含的私信列表
List<Message> selectLetters(String conversationId,int offset,int limit);
//查询某个会话所包含的私信数量
int selectLetterCount(String conversationId);
//查询未读私信的数量
int selectLetterUnreadCount(int userId,String conversationId);
}
新建message-mapper.xml实现上面的方法。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.huang.community.mapper.MessageMapper">
<sql id="selectFields">
id,from_id,to_id,conversation_id,content,status,create_time
</sql>
//status=2为已删除,from_id=1是系统通知
//按照对话id进行分组,查出每个组里最大的id,那就是最新的私信
<select id="selectConversations" resultType="Message">
SELECT
<include refid="selectFields"></include>
FROM message
WHERE id in (
SELECT max(id) from message
WHERE `status` !=2
AND from_id !=1
AND (from_id =#{userId} or to_id=#{userId})
GROUP BY conversation_id
)
ORDER BY id desc
limit #{offset},#{limit}
</select>
//统计会话数量
<select id="selectConversationCount" resultType="int">
select count(m.maxid)
from (
SELECT max(id) as maxid
from message
WHERE `status` != 2
AND from_id != 1
AND (from_id = #{userId} or to_id = #{userId})
GROUP BY conversation_id
) as m
</select>
<select id="selectLetters" resultType="Message">
select
<include refid="selectFields"></include>
from message
where status != 2
and from_id != 1
and conversation_id = #{conversationId}
order by id desc
limit #{offset},#{limit}
</select>
<select id="selectLetterCount" resultType="int">
select count(id)
from message
where status != 2
and from_id != 1
and conversation_id = #{conversationId}
</select>
<select id="selectLetterUnreadCount" resultType="int">
select count(id)
from message
where status=0
and from_id!=1
and to_id=#{userId}
<if test="conversationId!=null">
and conversation_id=#{conversationId}
</if>
</select>
</mapper>
业务层#
新建MessageService,比较简单,之间返回查询到的数据。
package com.neu.langsam.community.service;
import com.neu.langsam.community.dao.MessageMapper;
import com.neu.langsam.community.entity.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class MessageService {
@Autowired
private MessageMapper messageMapper;
public List<Message> findConversations(int userId, int offset, int limit) {
return messageMapper.selectConversations(userId, offset, limit);
}
public int findConversationCount(int userId) {
return messageMapper.selectConversationCount(userId);
}
public List<Message> findLetters(String conversationId, int offset, int limit) {
return messageMapper.selectLetters(conversationId, offset, limit);
}
public int findLetterCount(String conversationId) {
return messageMapper.selectLetterCount(conversationId);
}
public int findLetterUnreadCount(int userId, String conversationId) {
return messageMapper.selectLetterUnreadCount(userId, conversationId);
}
}
表现层#
要加载私信列表,从hostholder获取当前用户。将会话和私信内容,未读数量等封装到List<map<>>里。
package com.huang.community.controller;
import com.huang.community.model.NewPage;
import com.huang.community.pojo.Message;
import com.huang.community.pojo.User;
import com.huang.community.service.MessageService;
import com.huang.community.service.UserService;
import com.huang.community.util.CommunityUtil;
import com.huang.community.util.HostHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.*;
@Controller
public class MessageController {
@Autowired
private MessageService messageService;
@Autowired
private HostHolder hostHolder;
@Autowired
private UserService userService;
// 私信列表
@RequestMapping(path = "/letter/list", method = RequestMethod.GET)
public String getLetterList(Model model, NewPage page) {
User user = hostHolder.getUser();
// 分页信息
page.setLimit(5);
page.setPath("/letter/list");
page.setRows(messageService.findConversationCount(user.getId()));
// 会话列表
List<Message> conversationList = messageService.findConversations(
user.getId(), page.getOffset(), page.getLimit());
List<Map<String, Object>> conversations = new ArrayList<>();
if (conversationList != null) {
for (Message message : conversationList) {
Map<String, Object> map = new HashMap<>();
map.put("conversation", message);
map.put("letterCount", messageService.findLetterCount(message.getConversationId()));
//需要显示的是私信者的信息 所以需要排除自己,因为自己可能是from 或 to
map.put("unreadCount", messageService.findLetterUnreadCount(user.getId(), message.getConversationId()));
int targetId = user.getId() == message.getFromId() ? message.getToId() : message.getFromId();
map.put("target", userService.findUserById(targetId));
conversations.add(map);
}
}
model.addAttribute("conversations", conversations);
// 查询未读消息数量
int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null);
model.addAttribute("letterUnreadCount", letterUnreadCount);
return "/site/letter";
}
查看效果
然后继续开发会话详情功能。当前端点击会话列表中的某一个时,传入会话id,查询该会话id下的所有私信。页面上还需要显示发送私信的人,拆解conversationid,判断哪个是收信人。
@RequestMapping(path = "/letter/detail/{conversationId}",method = RequestMethod.GET)
public String getLetterDetail(@PathVariable("conversationId") String conversationId,Page page,Model model){
//分页信息
page.setLimit(5);
page.setPath("/letter/detail/"+conversationId);
page.setRows(messageService.findLetterCount(conversationId));
//私信列表
List<Message> letterList=messageService.findLetters(conversationId,page.getOffset(),page.getLimit());
List<Map<String,Object>> letters=new ArrayList<>();
if(letterList!=null){
for (Message message:letterList){
Map<String,Object> map=new HashMap<>();
map.put("letter",message);
map.put("fromUser",userService.findUserById(message.getFromId()));
letters.add(map);
}
}
model.addAttribute("letters",letters);
//私信目标
model.addAttribute("target",getLetterTarget(conversationId));
return "/site/letter-detail";
}
private User getLetterTarget(String conversationId){
String[] ids=conversationId.split("_");
int id0=Integer.parseInt(ids[0]);
int id1=Integer.parseInt(ids[1]);
if (hostHolder.getUser().getId()==id0){
return userService.findUserById(id1);
}else {
return userService.findUserById(id0);
}
}
分类:
仿牛客网社区项目
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署