Spring Boot 站内信的设计与实现
什么是站内信
在WEB系统中,站内信相当于是一个托管在服务器上的轻量邮局,它可以从WEB系统或者是用户获取信息并发送给指定的用户或者是用户群体。
站内信的类型
据我所知,当前实现站内信的方式主要通过两种:
-
通过
Websocket
来进行实现 - 通过纯数据库来进行实现
同时,基础的站内信一般都会实现两大功能,点到点的消息传送,点到面的消息传送
点到点的消息传送
点到点的消息传送,类似于我们关系型数据库所讲的一对一关系,也就是说,用户可以对用户进行消息的投递,或者是说用户对管理员进行消息的投递
点到面的消息传送
点到面的消息传送,类似于关系型数据库所说的一对多关系,web后台对应多个用户,也就是说,web后台可以对多个用户(用户群)进行群发消息通知
站内信的应用场景
-
通知公告
-
营销类活动
-
相关的信息通知
-
用户之间的互动
- 订阅信息
......
站内信的设计
在这里我们暂且只介绍下数据库的后端实现步骤,下次有机会的话介绍websocket方式
前端方面就靠你们自己吧
数据库
我们通过两张表实现,新建inner_message
和inner_message_text
表
CREATE TABLE `inner_message_text` (
`id` varchar(255) NOT NULL COMMENT '站内信内容id',
`sendId` int(255) unsigned DEFAULT NULL COMMENT '发信者id',
`content` text NOT NULL COMMENT '信件内容',
`groupId` int(2) unsigned DEFAULT NULL COMMENT '群发站内消息用 0->群发用户组 1->群发管理组',
`type` int(1) NOT NULL COMMENT '0 -> 系统消息 , 1 -> 私信 , 2 -> 站内通知',
`postDate` datetime NOT NULL COMMENT '发信时间',
PRIMARY KEY (`id`),
KEY `suid` (`sendId`),
KEY `groupId` (`groupId`),
CONSTRAINT `groupId` FOREIGN KEY (`groupId`) REFERENCES `user` (`groupId`),
CONSTRAINT `suid` FOREIGN KEY (`sendId`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE `inner_message` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
`getUid` int(255) unsigned NOT NULL COMMENT '接受者的id',
`messageId` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '站内信内容id',
`status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '站内信的状态 -> 未读 已读 删除',
PRIMARY KEY (`id`),
KEY `mid` (`messageId`),
KEY `uid` (`getUid`),
CONSTRAINT `mid` FOREIGN KEY (`messageId`) REFERENCES `inner_message_text` (`id`),
CONSTRAINT `uid` FOREIGN KEY (`getUid`) REFERENCES `user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
如上,我们分了两个表,一个存放信息列表,一个存放信息内容表,这样的好处就是解耦合,试想一下,倘若我们将所有数据放在一张表上,那么每个用户收到的信息都会被存入数据库中,几百人的使用量还好说,一旦用户数量上升,那么你的数据库只有一个结果:boom~
SpringBoot中要做的一些事情
持久化框架在这里我使用的是MybatisPlus
,在这里我推荐一下jpa
和beetlSQL
,用着是真滴舒服
这一些相应的配置我就不赘述了
我们在Constant池中进行常量的定义
...
@Getter
public enum Message{
STATUS_NOTREAD("未读"),
STATUS_READ("已读"),
STATUS_DELETED("已删除"),
TYPE_SYSTEM("系统消息",0),
TYPE_PRIVATE("私信",1),
TYPE_NOTICE("站内通知",2)
GROUP_TYPE_USER("用户组",0),
GROUP_TYPE_ADMIN("管理组",1)
;
private Integer val;
private String name;
Message(String name , Integer val){
this.val = val ;
this.name = name ;
}
Message(String name){
this.name = name ;
}
}
...
同时,我们在VO层中添加我们的MessageVO
用于接收传递的数据对象
package com.eendtech.witkey.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* @ author Seale
* @ Description: 站内信VO对象
* @ QQ:1801157108
* @ Date 2020/2/3 18:51
*/
@Data
@Accessors(chain = true)
public class MessageVO implements Serializable {
private static final long serialVersionUID = -5424113637283045181L;
private String messageId ;
private Integer sendUid ;
private Integer getUid ;
private Integer type ;
private Date postDate ;
private Integer groupId;
private String content ;
private String status ;
}
以下是自定义的Mapper文件,当前使用的持久化框架是MybatisPlus
简称MP
<?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.eendtech.witkey.mapper.MessageMapper">
<!--根据站内信的接收人id和站内信的类型进行查询-->
<resultMap id="findMessageByGetUidAndTypeResult" type="com.eendtech.witkey.model.Message">
<id property="id" column="id"/>
<result property="getUid" column="getUid"/>
<result property="status" column="status"/>
<result property="messageId" column="messageId"/>
<association property="messageText" javaType="MessageText">
<id property="id" column="mid"/>
<result property="sendId" column="sendId"/>
<result property="content" column="content"/>
<result property="type" column="type"/>
<result property="group" column="group"/>
<result property="postDate" column="postDate"/>
</association>
</resultMap>
<resultMap id="findSendMessageBySendUidMap" type="com.eendtech.witkey.model.Message">
<id property="id" column="id"/>
<result property="getUid" column="getUid"/>
<result property="status" column="status"/>
<result property="messageId" column="messageId"/>
<association property="messageText" javaType="MessageText">
<id property="id" column="mid"/>
<result property="sendId" column="sendId"/>
<result property="content" column="content"/>
<result property="groupId" column="groupId"/>
<result property="type" column="type"/>
<result property="postDate" column="postDate"/>
</association>
</resultMap>
<sql id="selectContent">
m.id, m.getUid, m.messageId, m.status, t.id as mid, t.sendId, t.content, t.type, t.postDate ,t.groupId
</sql>
<sql id="systemContent">
id,sendId,content,groupId,type,postDate
</sql>
<select id="findMessageByGetUidAndType" resultMap="findSendMessageBySendUidMap" parameterType="integer">
SELECT
<include refid="selectContent" />
FROM inner_message m
LEFT JOIN inner_message_text t
ON m.messageId = t.id
WHERE m.getUid = #{uid}
And t.type = #{type}
</select>
<select id="findSendMessageBySendUid" resultMap="findSendMessageBySendUidMap" parameterType="integer">
SELECT
<include refid="selectContent" />
FROM inner_message m
LEFT JOIN inner_message_text t
ON m.messageId = t.id
where t.sendId = #{sendUid}
</select>
<select id="findGroupSystemMessageNotReadForGetUid" resultType="com.eendtech.witkey.model.MessageText">
SELECT
<include refid="systemContent"/>
FROM
inner_message_text as t
WHERE
(SELECT count(1) as num FROM inner_message as m WHERE m.messageId = t.id AND m.getUid = #{getUid}) = 0
AND
t.type = 0
</select>
</mapper>
在这里讲解一下findGroupSystemMessageNotReadForGetUid
,查找群发的未读系统消息通过接收者的uid,我们通过在inner_message
中查找getUid
是否存在,如果不存在并且inner_message_text
中的id
也不再inner_message
中,那么这个时候返回的便是该用户接收到的系统群发的未读系统通知
具体的流程是这样的
MODEL
package com.eendtech.witkey.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @ author Seale
* @ Description: 站内信实体
* @ QQ:1801157108
* @ Date 2020/2/3 16:22
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@TableName(value = "inner_message")
public class Message implements Serializable {
private static final long serialVersionUID = 7887210545783690313L;
@TableId(type = IdType.AUTO)
private Integer id;
private Integer getUid;
private String messageId;
private String status;
private MessageText messageText;
}
package com.eendtech.witkey.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* @ author Seale
* @ Description: 站内信内容实体
* @ QQ:1801157108
* @ Date 2020/2/3 16:30
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@TableName(value = "inner_message_text")
public class MessageText implements Serializable {
private static final long serialVersionUID = -7070081047200484184L;
@TableId(type = IdType.UUID)
private String id ;
private Integer sendId;
private String content;
private Integer type;
private Integer groupId;
private Date postDate;
}
Service层
package com.eendtech.witkey.service.message;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.eendtech.witkey.model.Message;
import com.eendtech.witkey.model.MessageText;
import com.eendtech.witkey.vo.MessageVO;
import java.util.List;
/**
* @ author Seale
* @ Description:
* @ QQ:1801157108
* @ Date 2020/2/3 17:03
*/
public interface MessageService extends IService<Message> {
/***
* 函数名: addOne
* 函数说明: 在message中添加一条私信
* 创建时间: 2020/2/3 17:13
* @Param message:
* @return: java.lang.String
*/
String addPrivateOne(MessageVO message);
/***
* 函数名: addSystemOne
* 函数说明: 添加一条系统提示信息 (点对点)
* 创建时间: 2020/2/3 19:06
* @Param messageVO:
* @return: java.lang.String
*/
String addSystemOne(MessageVO messageVO);
/***
* 函数名: addSystemGroup
* 函数说明: 添加一条全体的系统提示信息
* 创建时间: 2020/2/5 20:40
* @Param messageVO:
* @return: java.lang.String
*/
String addSystemGroup(MessageVO messageVO);
/***
* 函数名: addNoticeOne
* 函数说明: 添加一条站内通知信息
* 创建时间: 2020/2/3 19:06
* @Param messageVO:
* @return: java.lang.String
*/
String addNoticeOne(MessageVO messageVO);
/***
* 函数名: updateOne
* 函数说明: 更新一条message,这种修改原则上只适用于站内通知,更改内容
* 创建时间: 2020/2/3 17:17
* @Param message:
* @return: java.lang.String
*/
String updateOne(MessageVO messageVO);
/***
* 函数名: updateOneStatus
* 函数说明: 修改一条站内信的状态,根据getUid和messageID
* 创建时间: 2020/2/3 17:19
* @Param message:
* @return: java.lang.String
*/
String updateOneStatusByGetUidAndMessageId(MessageVO messageVO);
/***
* 函数名: updateAllStatus
* 函数说明: 根据当前的getUid修改所有站内信的状态
* 创建时间: 2020/2/3 17:20
* @Param message:
* @return: java.lang.String
*
*/
String updateAllStatusByGetUid(MessageVO messageVO);
/***
* 函数名: delOne
* 函数说明: 删除一条message,根据messageID进行删除,两个表中的内容都将被删除
* 创建时间: 2020/2/3 17:30
* @Param message:
* @return: java.lang.String
*/
String delOne(MessageVO messageVO);
String delMany(List<MessageVO> messages);
//************查询接口***************************//
/***
* 函数名: findMessageByGetUidAndType
* 函数说明: 根据站内信的接收人id和站内信的类型进行查询
* 创建时间: 2020/2/3 17:58
* @Param getUid:
* @Param type:
* @return: com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.eendtech.witkey.model.Message>
*/
Page<Message> findMessageByGetUidAndType(Integer getUid , Integer type , Integer page , Integer size);
Page<Message> findMessageByGetUidAndType(Integer getUid , Integer type , Integer page );
/***
* 函数名: findSendMessageBySendUid
* 函数说明: 根据发送人id查询当前id发送的站内私信
* 创建时间: 2020/2/3 18:00
* @Param sendUid:
* @return: com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.eendtech.witkey.model.MessageText>
*/
Page<Message> findSendMessageBySendUid(Integer sendUid,Integer page , Integer size);
Page<Message> findSendMessageBySendUid(Integer sendUid,Integer page );
/***
* 函数名: findSendNoticeMessage
* 函数说明: 查询当前用户组的系统通知(所有的)
* 创建时间: 2020/2/3 18:08
* @return: com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.eendtech.witkey.model.MessageText>
*/
Page<MessageText> findSendSysMessage( Integer page , Integer size);
Page<MessageText> findSendSysMessage( Integer page );
/***
* 函数名: findNotceMessageNotReadForGetUid
* 函数说明: 查询当前用户组id的未读系统通知
* 创建时间: 2020/2/4 13:57
* @Param getUid:
* @Param page:
* @Param size:
* @return: com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.eendtech.witkey.model.MessageText>
*/
Page<MessageText> findSystemMessageNotReadForGetUid(Integer getUid , Integer page , Integer size);
Page<MessageText> findSystemMessageNotReadForGetUid(Integer getUid , Integer page );
/***
* 函数名: setGroupSystemMessageReadForGetUid
* 函数说明: 将群发系统未读通知设置成已读
* 创建时间: 2020/2/4 20:14
* @Param mid:
* @Param getUid:
* @return: java.lang.String
*/
String setGroupSystemMessageReadForGetUid(String mid,Integer getUid);
/***
* 函数名: groupSendNotice
* 函数说明: 发送用户组站内消息
* 创建时间: 2020/2/4 13:59
* @Param vo:
* @return: java.lang.String
*/
String groupSendSystem(MessageVO vo);
}
package com.eendtech.witkey.service.message.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.eendtech.witkey.constants.BaseConstant;
import com.eendtech.witkey.mapper.MessageMapper;
import com.eendtech.witkey.model.Message;
import com.eendtech.witkey.model.MessageText;
import com.eendtech.witkey.service.message.MessageService;
import com.eendtech.witkey.service.message.MessageTextService;
import com.eendtech.witkey.utils.BaseUtils;
import com.eendtech.witkey.vo.MessageVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
* @ author Seale
* @ Description:
* @ QQ:1801157108
* @ Date 2020/2/3 17:04
*/
@Transactional
@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements MessageService {
@Autowired
MessageTextService messageTextService;
@Autowired
MessageMapper messageMapper;
final static Integer DEFAULT_SIZE = 10 ;
//在message中添加一条信息
@Override
public String addPrivateOne(MessageVO messageVO) {
Date now = BaseUtils.getTimeNow();
Message message;
MessageText text = new MessageText();
text.setContent(messageVO.getContent())
.setType(BaseConstant.Message.TYPE_PRIVATE.getVal())
.setPostDate(now)
.setSendId(messageVO.getSendUid());
//进行text表的插入
boolean text_flag = messageTextService.save(text);
//获取text表中的id
String messageId = text.getId();
message = initMessage(messageId, messageVO.getGetUid());
boolean message_flag = save(message);
if (text_flag || message_flag) {
return "发送成功";
}
return "发送失败";
}
@Override
public String addSystemOne(MessageVO messageVO) {
// TODO: 2020/2/5 此方案暂不实现
return null;
}
@Override
public String addSystemGroup(MessageVO messageVO) {
Date now = BaseUtils.getTimeNow();
//Message message;
MessageText text = new MessageText();
text.setPostDate(now)
.setType(BaseConstant.Message.TYPE_SYSTEM.getVal())
.setContent(messageVO.getContent());
//进行text的插入
boolean text_flag = messageTextService.save(text);
//取出messageId
/*String messageId = text.getId();
message = initMessage(messageId, messageVO.getGetUid());
boolean message_falg = save(message);*/
if (text_flag) return "发送成功";
return "发送失败";
}
@Override
public String addNoticeOne(MessageVO messageVO) {
Date now = BaseUtils.getTimeNow();
Message message;
MessageText text = new MessageText();
text.setPostDate(now)
.setType(BaseConstant.Message.TYPE_NOTICE.getVal())
.setContent(messageVO.getContent());
//进行text的插入
boolean text_flag = messageTextService.save(text);
//取出messageId
String messageId = text.getId();
message = initMessage(messageId, messageVO.getGetUid());
boolean message_falg = save(message);
if (text_flag || message_falg) return "发送成功";
return "发送失败";
}
@Override
public String updateOne(MessageVO messageVO) {
String messageId = messageVO.getMessageId();
String content = messageVO.getContent();
MessageText text = new MessageText();
Date now = BaseUtils.getTimeNow();
text.setPostDate(now)
.setContent(content)
.setId(messageId);
boolean text_flag = messageTextService.updateById(text);
//此时应该在message表中修改消息状态 -> 未读
Message message = new Message();
message.setStatus(BaseConstant.Message.STATUS_NOTREAD.getName());
//进行message表中消息状态的修改
boolean message_flag =
lambdaUpdate()
.eq(Message::getMessageId, messageId)
.update(message);
if (text_flag || message_flag) return "修改消息成功";
return "修改消息失败";
}
@Override
public String updateOneStatusByGetUidAndMessageId(MessageVO messageVO) {
String messageId = messageVO.getMessageId();
Integer getUid = messageVO.getGetUid();
Message message = new Message();
String status = messageVO.getStatus();
if (choiceStatus(status) != null) {
message.setStatus(choiceStatus(status));
boolean flag =
lambdaUpdate()
.eq(Message::getGetUid, getUid)
.eq(Message::getMessageId, messageId)
.update(message);
if (flag) return "成功";
}
return "状态改变失败";
}
@Override
public String updateAllStatusByGetUid(MessageVO messageVO) {
Integer getUid = messageVO.getGetUid();
Message message = new Message();
String status = messageVO.getStatus();
//进行判断,已读或者删除状态
if (choiceStatus(status) != null) {
message.setStatus(choiceStatus(status));
boolean flag =
lambdaUpdate()
.eq(Message::getGetUid, getUid)
.update(message);
if (flag) return "成功";
}
return "状态修改失败";
}
@Override
public String delOne(MessageVO messageVO) {
//// TODO: 2020/2/3 当前版本不考虑复杂后台管理故暂不实现
return null;
}
@Override
public String delMany(List<MessageVO> messages) {
//// TODO: 2020/2/3 当前版本不考虑复杂后台管理故暂不实现
return null;
}
@Override
public Page<Message> findMessageByGetUidAndType(Integer getUid, Integer type , Integer page , Integer size) {
//根据站内信的接收人id和站内信的类型进行查询
if (choiceType(type) != null){
Page<Message> p = new Page<>();
p.setCurrent(page)
.setSize(size)
.setRecords(messageMapper.findMessageByGetUidAndType(getUid,type,p));
return p;
}
return null;
}
@Override
public Page<Message> findMessageByGetUidAndType(Integer getUid, Integer type, Integer page) {
return findMessageByGetUidAndType(getUid,type,page,DEFAULT_SIZE);
}
@Override
public Page<Message> findSendMessageBySendUid(Integer sendUid, Integer page , Integer size) {
Page<Message> p = new Page<>();
p.setCurrent(page)
.setSize(size)
.setRecords(messageMapper.findSendMessageBySendUid(sendUid,p));
return p;
}
@Override
public Page<Message> findSendMessageBySendUid(Integer sendUid, Integer page ) {
return findSendMessageBySendUid(sendUid,page,DEFAULT_SIZE);
}
@Override
public Page<MessageText> findSendSysMessage(Integer page, Integer size) {
Page<MessageText> p = new Page<>();
LambdaQueryWrapper<MessageText> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(MessageText::getType,BaseConstant.Message.TYPE_SYSTEM.getVal())
.eq(MessageText::getGroupId,BaseConstant.Message.GROUP_TYPE_USER.getVal());
p.setCurrent(page).setSize(size);
return (Page<MessageText>) messageTextService.page(p,wrapper);
}
@Override
public Page<MessageText> findSendSysMessage(Integer page) {
return findSendSysMessage(page,DEFAULT_SIZE);
}
@Override
public Page<MessageText> findSystemMessageNotReadForGetUid(Integer getUid, Integer page, Integer size) {
Page<MessageText> p = new Page<>();
p.setCurrent(page).setSize(size)
.setRecords(messageMapper.findGroupSystemMessageNotReadForGetUid(getUid,p));
return p;
}
@Override
public Page<MessageText> findSystemMessageNotReadForGetUid(Integer getUid, Integer page) {
return findSystemMessageNotReadForGetUid(getUid,page,DEFAULT_SIZE);
}
@Override
public String setGroupSystemMessageReadForGetUid(String mid, Integer getUid) {
Message message = new Message();
message.setMessageId(mid)
.setStatus(BaseConstant.Message.STATUS_READ.getName())
.setGetUid(getUid);
boolean flag = saveOrUpdate(message);
if(flag) return "已读";
return "失败";
}
@Override
public String groupSendSystem(MessageVO vo) {
MessageText text = new MessageText();
text.setContent(vo.getContent())
.setPostDate(BaseUtils.getTimeNow())
.setType(BaseConstant.Message.TYPE_SYSTEM.getVal())
.setGroupId(BaseConstant.Message.GROUP_TYPE_USER.getVal());
boolean flag = messageTextService.saveOrUpdate(text);
if (flag) return "发送成功";
return "失败";
}
//*************************************************************************************************
private Message initMessage(String messageId, Integer uid) {
Message message = new Message();
message.setStatus(BaseConstant.Message.STATUS_NOTREAD.getName())
.setMessageId(messageId)
.setGetUid(uid);
return message;
}
private String choiceStatus(String status) {
if (status.equals(BaseConstant.Message.STATUS_READ.getName()))
return (BaseConstant.Message.STATUS_READ.getName());
else if (status.equals(BaseConstant.Message.STATUS_DELETED.getName()))
return (BaseConstant.Message.STATUS_DELETED.getName());
return null;
}
private Integer choiceType(Integer type){
if (type.equals(BaseConstant.Message.TYPE_SYSTEM.getVal()))
return BaseConstant.Message.TYPE_SYSTEM.getVal();
else if (type.equals(BaseConstant.Message.TYPE_PRIVATE.getVal()))
return BaseConstant.Message.TYPE_PRIVATE.getVal();
else if (type.equals(BaseConstant.Message.TYPE_NOTICE.getVal()))
return BaseConstant.Message.TYPE_NOTICE.getVal();
return null;
}
}
简单的测试
封装一个返回工具集
package com.eendtech.witkey.utils;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
/**
* @ author Seale
* @ Description: Json返回包集合类
* @ QQ:1801157108
* @ Date 2020/2/1 19:18
*/
@Getter@Setter
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ReturnsKit <T>{
//状态码
private Integer code;
//结果
private T result;
//消息
private String message;
//状态
private String status;
}
再编写测试Controller
@GetMapping("/getSys/{uid}")
public ReturnsKit<Page<MessageText>> sys (@PathVariable Integer uid){
Page<MessageText> page = messageService.findSystemMessageNotReadForGetUid(uid,1);
return new ReturnsKit<Page<MessageText>>().setResult(page)
.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setStatus(BaseConstant.Returns.SUCCESS.getStatus());
}
最后
本篇探索只适合于本人的毕设内容,不代表可以运用于生产环境,这里只是讲一个大概的思路
控制器类还没完全写好,写好了放上来
补上完整的Controller层
package com.eendtech.witkey.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eendtech.witkey.constants.BaseConstant;
import com.eendtech.witkey.model.Message;
import com.eendtech.witkey.model.MessageText;
import com.eendtech.witkey.service.message.MessageService;
import com.eendtech.witkey.utils.BaseUtils;
import com.eendtech.witkey.utils.ReturnsKit;
import com.eendtech.witkey.vo.MessageVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @ author Seale
* @ Description: 信息的接口控制类
* @ QQ:1801157108
* @ Date 2020/2/4 17:40
*/
@RestController
@RequestMapping("/api/message")
public class MessageController {
@Autowired
MessageService messageService;
@GetMapping("/getNotReadSys/{uid}")
public ReturnsKit<Page<MessageText>> getUidNotReadSystemMessage(@PathVariable("uid") Integer uid, Integer page, Integer size) {
//查询当前用户组 uid的未读系统通知
size = BaseUtils.initSize(size);
page = BaseUtils.initPage(page);
ReturnsKit<Page<MessageText>> returnsKit = new ReturnsKit<>();
return returnsKit.setStatus(BaseConstant.Returns.SUCCESS.getStatus())
.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setResult(messageService.findSystemMessageNotReadForGetUid(uid, page, size));
}
@GetMapping("/getReadSys/{uid}")
public ReturnsKit<Page<Message>> getSys(@PathVariable Integer uid, Integer page , Integer size){
page = BaseUtils.initPage(page);
size = BaseUtils.initSize(size);
ReturnsKit<Page<Message>> returnsKit = new ReturnsKit<>();
if (verifyParam(uid,size,page)){
return returnsKit.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setStatus(BaseConstant.Returns.SUCCESS.getStatus())
.setResult(messageService.findMessageByGetUidAndType(uid,BaseConstant.Message.TYPE_SYSTEM.getVal(),page,size));
}else
return returnsKit.setCode(BaseConstant.Returns.PARAM_ERRO.getCode())
.setStatus(BaseConstant.Returns.PARAM_ERRO.getStatus())
.setMessage(BaseConstant.ReturnMessage.PARAM_NOT_NULL.getVal());
}
@PostMapping("/sendGroupSysMsg")
public ReturnsKit<String> sendGroupSystemMessage(@RequestBody MessageVO vo) {
//发送用户组站内系统消息
ReturnsKit<String> returnsKit = new ReturnsKit<>();
if (verifyParam(vo.getContent())) {
String msg = messageService.groupSendSystem(vo);
if (msg.equals("发送成功")) {
return returnsKit.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setStatus(BaseConstant.Returns.SUCCESS.getStatus())
.setMessage(msg);
} else {
return returnsKit.setCode(BaseConstant.Returns.FAIL.getCode())
.setStatus(BaseConstant.Returns.FAIL.getStatus())
.setMessage(msg);
}
}
return returnsKit.setCode(BaseConstant.Returns.PARAM_ERRO.getCode())
.setStatus(BaseConstant.Returns.PARAM_ERRO.getStatus())
.setMessage(BaseConstant.ReturnMessage.PARAM_NOT_NULL.getVal());
}
@PostMapping("/readGroupSysMsg")
public ReturnsKit<String> setGroupSystemMessageRead(@RequestBody MessageVO vo) {
//将系统群发的系统通知设置为已读
ReturnsKit<String> returnsKit = new ReturnsKit<>();
if (verifyParam(vo.getGetUid(), vo.getMessageId())) {
String msg = messageService.setGroupSystemMessageReadForGetUid(vo.getMessageId(), vo.getGetUid());
if (msg.equals("已读")) {
return returnsKit.setMessage(msg)
.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setStatus(BaseConstant.Returns.SUCCESS.getStatus());
} else {
return returnsKit.setMessage(msg)
.setStatus(BaseConstant.Returns.FAIL.getStatus())
.setCode(BaseConstant.Returns.FAIL.getCode());
}
} else {
return returnsKit.setMessage(BaseConstant.ReturnMessage.PARAM_NOT_NULL.getVal())
.setCode(BaseConstant.Returns.PARAM_ERRO.getCode())
.setStatus(BaseConstant.Returns.PARAM_ERRO.getStatus());
}
}
@GetMapping("/getAllSysForGroup")
public ReturnsKit<Page<MessageText>> getAllSysForGroup(Integer page, Integer size) {
//查询当前已发送的系统通知(所有的)
size = BaseUtils.initSize(size);
page = BaseUtils.initPage(page);
ReturnsKit<Page<MessageText>> returnsKit = new ReturnsKit<>();
return returnsKit.setStatus(BaseConstant.Returns.SUCCESS.getStatus())
.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setResult(messageService.findSendSysMessage(page, size));
}
@GetMapping("/getSendPrivate/{uid}")
public ReturnsKit<Page<Message>> getSendMessageBySendUid(@PathVariable Integer uid, Integer page, Integer size) {
//根据发送人id查询当前id发送的站内私信
size = BaseUtils.initSize(size);
page = BaseUtils.initPage(page);
ReturnsKit<Page<Message>> returnsKit = new ReturnsKit<>();
if (verifyParam(uid)) {
return returnsKit.setResult(messageService.findSendMessageBySendUid(uid, page, size))
.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setStatus(BaseConstant.Returns.SUCCESS.getStatus());
} else {
return returnsKit.setMessage(BaseConstant.ReturnMessage.PARAM_NOT_NULL.getVal())
.setCode(BaseConstant.Returns.PARAM_ERRO.getCode())
.setStatus(BaseConstant.Returns.PARAM_ERRO.getStatus());
}
}
@GetMapping("/getPrivate/{uid}")
public ReturnsKit<Page<Message>> getPrivateMsg(@PathVariable Integer uid, Integer page, Integer size) {
//得到当前id收到的站内私信
page = BaseUtils.initPage(page);
size = BaseUtils.initSize(size);
ReturnsKit<Page<Message>> returnsKit = new ReturnsKit<>();
if (verifyParam(uid)) {
return returnsKit.setStatus(BaseConstant.Returns.SUCCESS.getStatus())
.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setResult(messageService.findMessageByGetUidAndType(uid, BaseConstant.Message.TYPE_PRIVATE.getVal(), page, size));
} else {
return returnsKit.setStatus(BaseConstant.Returns.PARAM_ERRO.getStatus())
.setCode(BaseConstant.Returns.PARAM_ERRO.getCode())
.setMessage(BaseConstant.ReturnMessage.PARAM_NOT_NULL.getVal());
}
}
@GetMapping("/getNotice/{uid}")
public ReturnsKit<Page<Message>> getNoticeMsg(@PathVariable Integer uid, Integer page, Integer size) {
//得到当前id收到的站内通知
page = BaseUtils.initPage(page);
size = BaseUtils.initSize(size);
ReturnsKit<Page<Message>> returnsKit = new ReturnsKit<>();
if (verifyParam(uid)) {
return returnsKit.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setStatus(BaseConstant.Returns.SUCCESS.getStatus())
.setResult(messageService.findMessageByGetUidAndType(uid, BaseConstant.Message.TYPE_NOTICE.getVal(), page, size));
} else {
return returnsKit.setCode(BaseConstant.Returns.PARAM_ERRO.getCode())
.setStatus(BaseConstant.Returns.PARAM_ERRO.getStatus())
.setMessage(BaseConstant.ReturnMessage.PARAM_NOT_NULL.getVal());
}
}
/***
* 函数名: setAllNotSystemMsgRead
* 函数说明: 当前接口设置所有的非系统通知为已读状态
* 创建时间: 2020/2/5 16:17
* @return: com.eendtech.witkey.utils.ReturnsKit<java.lang.String>
*/
@PostMapping("/readNotSysAll/{uid}")
public ReturnsKit<String> setAllNotSystemMsgRead(@PathVariable Integer uid) {
ReturnsKit<String> returnsKit = new ReturnsKit<>();
if (verifyParam(uid)) {
MessageVO vo = new MessageVO();
vo.setGetUid(uid)
.setStatus(BaseConstant.Message.STATUS_READ.getName());
return returnsKit.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setStatus(BaseConstant.Returns.SUCCESS.getStatus())
.setMessage(messageService.updateAllStatusByGetUid(vo));
} else {
return returnsKit.setCode(BaseConstant.Returns.PARAM_ERRO.getCode())
.setStatus(BaseConstant.Returns.PARAM_ERRO.getStatus())
.setMessage(BaseConstant.ReturnMessage.PARAM_NOT_NULL.getVal());
}
}
@PostMapping("/readNotSys")
public ReturnsKit<String> setNotSysMsgRead(@RequestBody MessageVO vo) {
//设置一条站内信或者私信为已读
ReturnsKit<String> returnsKit = new ReturnsKit<>();
if (verifyParam(vo.getGetUid(), vo.getMessageId())) {
String msg = messageService.updateOneStatusByGetUidAndMessageId(vo);
if (msg.equals("成功")) {
return returnsKit.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setStatus(BaseConstant.Returns.SUCCESS.getStatus())
.setMessage(msg);
} else {
return returnsKit.setCode(BaseConstant.Returns.FAIL.getCode())
.setStatus(BaseConstant.Returns.FAIL.getStatus())
.setMessage(msg);
}
} else {
return returnsKit.setCode(BaseConstant.Returns.PARAM_ERRO.getCode())
.setStatus(BaseConstant.Returns.PARAM_ERRO.getStatus())
.setMessage(BaseConstant.ReturnMessage.PARAM_NOT_NULL.getVal());
}
}
@PostMapping("/updateSysMsg")
public ReturnsKit<String> updateSys(@RequestBody MessageVO vo) {
//修改一条系统通知
ReturnsKit<String> returnsKit = new ReturnsKit<>();
if (verifyParam(vo.getMessageId(), vo.getContent())) {
String msg = messageService.updateOne(vo);
if (msg.equals("修改消息成功")) {
return returnsKit.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setStatus(BaseConstant.Returns.SUCCESS.getStatus())
.setMessage(msg);
} else {
return returnsKit.setCode(BaseConstant.Returns.FAIL.getCode())
.setStatus(BaseConstant.Returns.FAIL.getStatus())
.setMessage(msg);
}
} else {
return returnsKit.setCode(BaseConstant.Returns.PARAM_ERRO.getCode())
.setStatus(BaseConstant.Returns.PARAM_ERRO.getStatus())
.setMessage(BaseConstant.ReturnMessage.PARAM_NOT_NULL.getVal());
}
}
@PostMapping("/sendNotice")
//添加一条站内通知信息
public ReturnsKit<String> sendNotice(@RequestBody MessageVO vo) {
ReturnsKit<String> returnsKit = new ReturnsKit<>();
if (verifyParam(vo.getGetUid(), vo.getContent())) {
String msg = messageService.addNoticeOne(vo);
if (msg.equals("发送成功")) {
return returnsKit.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setStatus(BaseConstant.Returns.SUCCESS.getStatus())
.setMessage(msg);
} else {
return returnsKit.setCode(BaseConstant.Returns.FAIL.getCode())
.setStatus(BaseConstant.Returns.FAIL.getStatus())
.setMessage(msg);
}
} else {
return returnsKit.setCode(BaseConstant.Returns.PARAM_ERRO.getCode())
.setStatus(BaseConstant.Returns.PARAM_ERRO.getStatus())
.setMessage(BaseConstant.ReturnMessage.PARAM_NOT_NULL.getVal());
}
}
@PostMapping("/sendSys")
public ReturnsKit<String> sendSys(@RequestBody MessageVO vo) {
ReturnsKit<String> returnsKit = new ReturnsKit<>();
if (verifyParam(vo.getContent())) {
String msg = messageService.addSystemGroup(vo);
if (msg.equals("发送成功"))
return returnsKit.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setStatus(BaseConstant.Returns.SUCCESS.getStatus())
.setMessage(msg);
else
return returnsKit.setCode(BaseConstant.Returns.FAIL.getCode())
.setStatus(BaseConstant.Returns.FAIL.getStatus())
.setMessage(msg);
} else
return returnsKit.setCode(BaseConstant.Returns.PARAM_ERRO.getCode())
.setStatus(BaseConstant.Returns.PARAM_ERRO.getStatus())
.setMessage(BaseConstant.ReturnMessage.PARAM_NOT_NULL.getVal());
}
//发送私信 点对点
@PostMapping("/sendPrivate")
public ReturnsKit<String> sendPrivate(@RequestBody MessageVO vo){
ReturnsKit<String> returnsKit = new ReturnsKit<>();
if (verifyParam(vo.getContent(),vo.getGetUid(),vo.getSendUid())) {
String msg = messageService.addPrivateOne(vo);
if (msg.equals("发送成功"))
return returnsKit.setCode(BaseConstant.Returns.SUCCESS.getCode())
.setStatus(BaseConstant.Returns.SUCCESS.getStatus())
.setMessage(msg);
else
return returnsKit.setCode(BaseConstant.Returns.FAIL.getCode())
.setStatus(BaseConstant.Returns.FAIL.getStatus())
.setMessage(msg);
}else
return returnsKit.setCode(BaseConstant.Returns.PARAM_ERRO.getCode())
.setStatus(BaseConstant.Returns.PARAM_ERRO.getStatus())
.setMessage(BaseConstant.ReturnMessage.PARAM_NOT_NULL.getVal());
}
//验证参数是否为空
private boolean verifyParam(Object... objects) {
for (Object o : objects) {
if (o == null) {
return false;
}
}
return true;
}
}
这个时候我们通过ajax或者axios调用我们的restful接口就行了!
3 comments
楼主还有兴趣发websocket方式嘛?
你这不是实时的呀
你想要实时的在客户端进行轮询或者用websocket实现,我这个只是毕设设计的