此次最困难的功能,也找了很多资料最终花了一些时间实现了该功能(文章中的uml时序图是本人第一次画,有误差的地方肯定是有的,希望大家可以指点一二,在此谢过)
1.产品需求
从需求中提取了以下几点要完成
添加订阅动作
用户 发布,评论,送花,拍砖 会插入到 订阅表(为了订阅到后期有人评论时收到提醒)
评论内容动作时
用户每次对事件评论后产生信息并插入到消息表(为了订阅者获取某个事件的最后一个消息)
产生消息提醒
每次用户登陆或者其他操作时会触发产生消息队列,每次订阅表中获取订阅的事件最后产生的评论信息,放入消息表里
更新消息已读
每次点击进入详情时更新全部的消息提醒
2.设计实现
1.uml功能时序图
以下图是产生订阅事件信息及提醒信息时序图
以下图是用户触发从提醒表提取未读消息,放入未读表中,以及更改已读消息状态的时序图
2.数据库设计
主要字段解释 ( 红色部分为以后拓展功能时用到的这次不会用到的字段 )
- subscription=订阅表:{content_id:“事件Id”,user_id:"用户id"}
- notify=消息表:{sender_id:"对事件评论的用户id",content_id:”事件Id“}
- user_notify=用户未读消息队列:{content_id:“事件Id”,user_id:"用户id",read_yn:"读取状态"}
3.重要代码实现部分
1.利用aop的after 每次拍砖,献花,评论后执行 后续的订阅,和生成评论消息动作,
此次使用aop 其实就是为了怕用户在做完主要动作后还要等待后续的动作会影响用户体验
<!-- 通知 -->
<bean id ="xmlHandler" class="com.brickman.aop.XMLAdvice"/>
<!-- aop 配置 消息-->
<aop:config>
<aop:aspect id="aspectService" ref="xmlHandler">
<!-- aop 监听拍砖,献花,评论后 执行 后续插入订阅表和生成评论-->
<aop:pointcut id="remindPoint" expression="execution(* com.brickman.bo.*.insertRecord(..)) || execution(* com.brickman.bo.*.addComment(..))"/>
<aop:after method="doAfterInsertRemind" pointcut-ref="remindPoint"/>
</aop:aspect>
</aop:config>
2.每次如果订阅表里已经有了之前事件Id那么就更新订阅表的订阅时间
3.用户在登陆或者其他操作时触发生产未读消息队列
重点时找到notify中生成消息时间大于订阅表中的更新时间,并获取最大的notifyId相关数据
SELECT MAX(b.notify_id) AS notify_id,b.content_id AS content_id
FROM brick_subscription a,brick_notify b
WHERE a.content_id=b.content_id
AND a.user_id = #{userId}
AND b.sender_id <![CDATA[<>]]> #{userId}
AND a.update_time <![CDATA[<]]> b.created_time
GROUP BY b.content_id
4.插入用户提醒队列表时 主要还要判断是否已经有过该事件如果有就不插入,为了避免两次mysql连接直接一次性写在一个sql中
INSERT INTO brick_user_notify ( user_id, content_id, notify_id )
SELECT #{userId},#{contentId},#{notifyId}
FROM DUAL
WHERE NOT EXISTS (
SELECT 1
FROM brick_user_notify
WHERE content_id=#{contentId} AND user_id=#{userId} AND notify_id=#{notifyId}
)
点击进入用户未读消息的事件后,会更新某个事件的所有未读消息为已读
如果此时此刻,你也在北漂、上漂、广漂、深漂,那这里就是你的新家:www.brickman.cn。
欢迎加入砖头人大家庭,现邀请你体验为你定制开发的“砖头人app”。