疫情防控交流社区平台——3.4 开发社区核心功能

🌕开发社区核心功能

5.私信列表

在这里插入图片描述

5.1 Message

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Message {

    private int id;
    private int fromId;             //消息发送人
    private int toId;               //消息接受者
    private String conversationId;  //会话id,用来标识会话的,中间有个_,所以不是int类型;如果没这个字段,利用fromId和toId组合在一起也能查到,只是不方便
    //设计这个会话id目的:为了将来在查询会话有关的数据时,以会话为条件进行一个查询筛选的时候方便
    private String content;
    private int status;             //状态: 0未读 1已读 2删除
    private Date createTime;

}

5.2 MessageMapper

//@Repository
@Mapper
public interface MessageMapper {

    //1.查询当前用户的会话列表,针对每个会话只返回一条最新的私信
    public List<Message> selectConversations(int userId,int offset,int limit);

    //2.查询当前用户会话的数量
    public int selectConversationCount(int userId);

    //3.查询某个会话所包含的私信列表(开发详情页面需要用到)
    public List<Message> selectLetters(String conversationId,int offset,int limit);

    //4.查询某个会话所包含的私信数量
    public int selectLetterCount(String conversationId);

    //5.查询未读私信的数量
    public int selectLetterUnreadCount(int userId,String conversationId);

}

5.3 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.yty.community.dao.MessageMapper">

    <sql id="selectFields">
        id,from_id,to_id,conversation_id,content,status,create_time
    </sql>

    <!--1.查询当前用户的会话列表,针对每个会话只返回一条最新的私信-->
    <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>

    <!--2.查询当前用户会话的数量-->
    <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>

    <!--3.查询某个会话所包含的私信列表(开发详情页面需要用到)-->
    <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>

    <!--4.查询某个会话所包含的私信数量-->
    <select id="selectLetterCount" resultType="int">
        select count(id)
        from message
        where status != 2
        and from_id != 1
        and conversation_id = #{conversationId}
    </select>

    <!--5.查询未读私信的数量-->
    <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>
5.3.1 MapperTests —— sql测试
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class MapperTests {

	@Resource
    private MessageMapper messageMapper;

	/*
    * MessageMapper方法测试
    * */
    @Test
    //直接一个方法测5个sql语句的方法
    public void testSelectLetters(){
        //1.查询当前用户的会话列表
        List<Message> list = messageMapper.selectConversations(111, 0, 10);
        for (Message message : list) {
            System.out.println(message);
        }
        //2.查询当前用户会话的数量
        int i = messageMapper.selectConversationCount(111);
        System.out.println(i);
        //3.查询某个会话所包含的私信列表(开发详情页面需要用到)
        List<Message> letters = messageMapper.selectLetters("111_112", 0, 10);
        for (Message letter : letters) {
            System.out.println(letter);
        }
        //4.查询某个会话所包含的私信数量
        int a = messageMapper.selectLetterCount("111_112");
        System.out.println(a);
        //5.查询未读私信的数量
        int b = messageMapper.selectLetterUnreadCount(131, "111_131");
        System.out.println(b);
    }
}
5.3.2 结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
sql无任何错误!

5.4 MessageService

@Service
public class MessageService {

    @Resource
    private MessageMapper messageMapper;

    //1.查询当前用户的会话列表,针对每个会话只返回一条最新的私信
    public List<Message> findConversations(int userId,int offset,int limit){
        return messageMapper.selectConversations(userId, offset, limit);
    }
    //2.查询当前用户会话的数量
    public int findConversationCount(int userId){
        return messageMapper.selectConversationCount(userId);
    }
    //3.查询某个会话所包含的私信列表(开发详情页面需要用到)
    public List<Message> findLetters(String conversationId,int offset,int limit){
        return messageMapper.selectLetters(conversationId, offset, limit);
    }
    //4.查询某个会话所包含的私信数量
    public int findLetterCount(String conversationId){
        return messageMapper.selectLetterCount(conversationId);
    }
    //5.查询未读私信的数量
    public int findLetterUnreadCount(int userId,String conversationId){
        return messageMapper.selectLetterUnreadCount(userId, conversationId);
    }
    
}

5.5 MessageController

@Controller
//@RequestMapping("/message")
public class MessageController {

    @Resource
    private MessageService messageService;
    @Resource
    private HostHolder hostHolder; //当前用户信息,所有操作肯定都是关于当前用户的,很重要
    @Resource
    private UserService userService;

    //私信列表
    @RequestMapping(path = "/letter/list",method = RequestMethod.GET)
    public String getLetterList(Model model, Page page){
        User user = hostHolder.getUsers();
        //分页信息
        page.setLimit(5);
        page.setPath("/letter/list");
        //page.setRows(messageService.findConversationCount(hostHolder.getUsers().getId()));
        //这里我就不通过hostHolder.getUsers().getId())获取当前用户id了,后面还会多次用到hostHolder,所以直接在上面一次性获取出来,不用每次都去一大串取,如下
        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) {
                HashMap<String, Object> map = new HashMap<>();
                map.put("conversation",message);
                map.put("letterCount",messageService.findLetterCount(message.getConversationId()));
                map.put("unreadCount",messageService.findLetterUnreadCount(user.getId(),message.getConversationId()));
                int targetId = user.getId() == message.getFromId() ? message.getToId() : message.getFromId();
                map.put("target",userService.findByUserId(targetId));

                conversations.add(map);
            }
        }
        model.addAttribute("conversations",conversations);
        //查询未读消息数量
        int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(),null);
        model.addAttribute("letterUnreadCount",letterUnreadCount);

        return "/site/letter";
    }
}

5.6 letter.html页面修改

5.7 测试结果

在这里插入图片描述
成功!

6.私信详情

数据层、业务层方法在 “私信列表” 的时候就已经全部搞定了,这里只弄表现层代码。

6.1 MessageController

	//2.私信详情
    @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*/
        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.findByUserId(message.getFromId()));
                letters.add(map);
            }
        }
        model.addAttribute("letters",letters);

        //*私信目标
        model.addAttribute("target",getLetterTargetYTY(conversationId));

        return "/site/letter-detail";
    }

    //*封装一个方法 —— 用于显示谁在跟你发私信,知道和你私信的目标人
    private User getLetterTargetYTY(String conversationId){
        String[] ids = conversationId.split("_");  //对xxx_xxx拆分,前面小id,后面大id
        int id0 = Integer.parseInt(ids[0]);      //[0] 代表 前面小的id
        int id1 = Integer.parseInt(ids[1]);      //[1] 代表 前面大的id

        if (hostHolder.getUsers().getId()==id0){
            return userService.findByUserId(id1);  //如果当前用户id等于小的id,所以和你发消息的就是大的id,取大的id名字作为和你发消息的人
        }else {
            return userService.findByUserId(id0);
        }
    }

6.2 letter-detail.html页面修改

6.3 测试结果

在这里插入图片描述

7.发送私信

在这里插入图片描述

7.1 MessageMapper

	//发送私信 —— 添加
    public int insertMessage(Message message);

    //修改消息的状态 —— 1 已读(会用List来,因为可能有多条未读消息)
    public int updateStatus(List<Integer> ids,int status);

7.2 message-mapper.xml

	<!--发送私信 —— 添加-->
    <insert id="insertMessage" parameterType="Message" keyProperty="id">
        insert into message (<include refid="insertFields"></include>) 
        values (#{fromId},#{toId},#{conversationId},#{content},#{status},#{createTime})
    </insert>
    
    <!--修改消息的状态 —— 已读-->
    <update id="updateStatus">
        update message set status = #{status}
        where id in
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </update>

7.3 MessageService

	//发送私信 —— 添加
    public int addMessage(Message message){
        message.setContent(HtmlUtils.htmlEscape(message.getContent()));   //对标签进行转义
        message.setContent(sensitiveFilter.filter(message.getContent())); //敏感词过滤
        return messageMapper.insertMessage(message);
    }

    修改消息的状态 —— 1 已读
    public int readMessage(List<Integer> ids){
        return messageMapper.updateStatus(ids,1);
    }

7.4 MessageController

先看3,然后回看2的补充代码,最后看单独的方法。

	//2.私信详情
    @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*/
        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.findByUserId(message.getFromId()));
                letters.add(map);
            }
        }
        model.addAttribute("letters",letters);

        //*私信目标
        model.addAttribute("target",getLetterTargetYTY(conversationId));

        /*功能补充:提取未读消息,将其设为已读*/
        List<Integer> ids = getLetterIds(letterList);
        if (!ids.isEmpty()){
            messageService.readMessage(ids);
        }

        return "/site/letter-detail";
    }
	
	/*功能补充:提取未读消息,将其设为已读*/
    //先判断当前用户是不是接受者(toName),只有接受者才能设置已读这种情况。
    private List<Integer> getLetterIds(List<Message> letterList){
        List<Integer> ids = new ArrayList<>();

        if (letterList != null){
            for (Message message : letterList) {
                if (hostHolder.getUsers().getId() == message.getToId() && message.getStatus() == 0) {
                    ids.add(message.getId());
                }
            }
        }
        return ids;
    }

	/*3.发送私信*/
    @RequestMapping(path = "/letter/send",method = RequestMethod.POST)
    @ResponseBody
    public String sendLetter(String toName,String content){
        //查到我们要私信发送目标的名字
        User target = userService.findUserByName(toName);
        if (target == null){
            return CommunityUtil.getJSONString(1,"发送目标用户不存在!");
        }

        Message message = new Message();
        message.setFromId(hostHolder.getUsers().getId());  //确定正在发私信的用户的id,不是目标用户就是收私信的用户
        message.setToId(target.getId());
        if (message.getFromId() < message.getToId()){
            message.setConversationId(message.getFromId()+"_"+message.getToId());
        }else {
            message.setConversationId(message.getToId()+"_"+message.getFromId());
        }
        message.setContent(content);
        message.setCreateTime(new Date());
        messageService.addMessage(message);
        //之后做统一异常处理
        return CommunityUtil.getJSONString(0);
    }

7.5 letter-detail.html页面修改

7.6 测试结果

使用aaa账户发私信给yty1
在这里插入图片描述
在这里插入图片描述
点进去看详情:
在这里插入图片描述
再发一条:
在这里插入图片描述

然后切换到yty1的用户,
在这里插入图片描述
看详情,并进行回复,然后切回aaa用户查看已读。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
成功!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

11_1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值