持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情
使用MongoDB存储信息表
消息模块的数据量一般都比较大,因为会一直增长,所以这里使用mongoDB作为存储容器。
当然,mongoDB也不是万能的,当数据量达到一定程度时,依旧会出现崩溃的现象。这时候,我们可以通过定时任务,在每个月末的时候,选一个没有人使用的时间,将上个月的数据迁移到另一张表中,做到冷热分离。当然,历史数据也不会无限制的增加,过一段时间,也必须进行删除。
创建message集合
用来保存消息的主题以及发送人的信息
@Data
@Document(collection = "message")
public class MessageEntity implements Serializable {
// 自动生成的主键值
@Id
private String _id;
// UUID值,并且设置有唯一性索引,防止消息被重复消费
@Indexed(unique = true)
private String uuid;
// 发送者ID,就是用户ID。如果是系统自动发出,这个ID值是0
@Indexed
private Integer senderId;
// 发送者的头像URL。在消息页面要显示发送人的头像
private String senderPhoto="https://static-1258386385.cos.ap-beijing.myqcloud.com/img/System.jpg";
// 发送者名称,也就是用户姓名。在消息页面要显示发送人的名字
private String senderName;
// 消息正文
@Indexed
private Date sendTime;
// 发送时间
private String msg;
}
message_ref集合
用来存储消息集合的id,以及接收人的信息。
@Document(collection = "message_ref")
@Data
public class MessageRefEntity implements Serializable{
// 主键
@Id
private String _id;
// message记录的_id
@Indexed
private String messageId;
// 接收人ID
@Indexed
private Integer receiverId;
// 是否已读
@Indexed
private Boolean readFlag;
// 是否为新接收的消息
@Indexed
private Boolean lastFlag;
}
创建消息模块的持久层
创建MessageDao类
@Repository
public class MessageDao {
@Autowired
private MongoTemplate mongoTemplate;
public String insert(MessageEntity entity) {
//把北京时间转换成格林尼治时间
Date sendTime = entity.getSendTime();
sendTime = DateUtil.offset(sendTime, DateField.HOUR, 8);
entity.setSendTime(sendTime);
entity = mongoTemplate.save(entity);
return entity.get_id();
}
public List<HashMap> searchMessageByPage(int userId, long start, int length) {
JSONObject json = new JSONObject();
json.set("$toString", "$_id");
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.addFields().addField("id").withValue(json).build(),
Aggregation.lookup("message_ref", "id", "messageId", "ref"),
//Aggregation.match(Criteria.where("ref.receiverId").is(userId)),
Aggregation.project("id", "msg", "sendTime","senderId","senderName","senderPhoto","uuid")
.and(item-> Document.parse("{$filter:{input:\"$ref\",as:\"item\",cond:{$eq:[\"$$item.receiverId\","+userId+"]}}}")).as("ref"),
Aggregation.sort(Sort.by(Sort.Direction.DESC, "sendTime")),
Aggregation.skip(start),
Aggregation.limit(length)
);
AggregationResults<HashMap> results = mongoTemplate.aggregate(aggregation, "message", HashMap.class);
List<HashMap> list = results.getMappedResults();
list.forEach(one -> {
List<MessageRefEntity> refList = (List<MessageRefEntity>) one.get("ref");
MessageRefEntity entity = refList.get(0);
boolean readFlag = entity.getReadFlag();
String refId = entity.get_id();
one.remove("ref");
one.put("readFlag", readFlag);
one.put("refId", refId);
one.remove("_id");
//把格林尼治时间转换成北京时间
Date sendTime = (Date) one.get("sendTime");
sendTime = DateUtil.offset(sendTime, DateField.HOUR, -8);
String today = DateUtil.today();
//如果是今天的消息,只显示发送时间,不需要显示日期
if (today.equals(DateUtil.date(sendTime).toDateStr())) {
one.put("sendTime", DateUtil.format(sendTime, "HH:mm"));
}
//如果是以往的消息,只显示日期,不显示发送时间
else {
one.put("sendTime", DateUtil.format(sendTime, "yyyy/MM/dd"));
}
});
return list;
}
public HashMap searchMessageById(String id) {
HashMap map = mongoTemplate.findById(id, HashMap.class, "message");
Date sendTime = (Date) map.get("sendTime");
//把格林尼治时间转换成北京时间
sendTime = DateUtil.date(sendTime).offset(DateField.HOUR, -8);
map.replace("sendTime", DateUtil.format(sendTime, "yyyy-MM-dd HH:mm"));
return map;
}
}
创建MessageRefDao类
@Repository
public class MessageRefDao {
@Autowired
private MongoTemplate mongoTemplate;
public String insert(MessageRefEntity entity) {
entity = mongoTemplate.save(entity);
return entity.get_id();
}
/**
* 查询未读消息数量
*
* @param userId
* @return
*/
public long searchUnreadCount(int userId) {
Query query = new Query();
query.addCriteria(Criteria.where("readFlag").is(false).and("receiverId").is(userId));
long count = mongoTemplate.count(query, MessageRefEntity.class);
return count;
}
/**
* 查询新接收消息数量
*
* @param userId
* @return
*/
public long searchLastCount(int userId) {
Query query = new Query();
query.addCriteria(Criteria.where("lastFlag").is(true).and("receiverId").is(userId));
Update update = new Update();
update.set("lastFlag", false);
UpdateResult result = mongoTemplate.updateMulti(query, update, "message_ref");
long rows = result.getModifiedCount();
return rows;
}
/**
* 把未读消息变更为已读消息
*
* @param id
* @return
*/
public long updateUnreadMessage(String id) {
Query query = new Query();
query.addCriteria(Criteria.where("_id").is(id));
Update update = new Update();
update.set("readFlag", true);
UpdateResult result = mongoTemplate.updateFirst(query, update, "message_ref");
long rows = result.getModifiedCount();
return rows;
}
/**
* 根据ID删除ref消息
*
* @param id
* @return
*/
public long deleteMessageRefById(String id) {
Query query = new Query();
query.addCriteria(Criteria.where("_id").is(id));
DeleteResult result = mongoTemplate.remove(query, "message_ref");
long rows = result.getDeletedCount();
return rows;
}
/**
* 删除某个用户全部消息
*
* @param userId
* @return
*/
public long deleteUserMessageRef(int userId) {
Query query = new Query();
query.addCriteria(Criteria.where("receiverId").is(userId));
DeleteResult result = mongoTemplate.remove(query, "message_ref");
long rows = result.getDeletedCount();
return rows;
}
}
创建消息模块的业务层
创建MessageService.java类
public interface MessageService {
public String insertMessage(MessageEntity entity);
public String insertRef(MessageRefEntity entity);
public long searchUnreadCount(int userId);
public long searchLastCount(int userId);
public List<HashMap> searchMessageByPage(int userId, long start, int length) ;
public HashMap searchMessageById(String id);
public long updateUnreadMessage(String id) ;
public long deleteMessageRefById(String id);
public long deleteUserMessageRef(int userId);
}
创建MessageServiceImpl.java类
@Service
public class MessageServiceImpl implements MessageService {
@Autowired
private MessageDao messageDao;
@Autowired
private MessageRefDao messageRefDao;
@Override
public String insertMessage(MessageEntity entity) {
String id = messageDao.insert(entity);
return id;
}
@Override
public String insertRef(MessageRefEntity entity) {
String id = messageRefDao.insert(entity);
return id;
}
@Override
public long searchUnreadCount(int userId) {
long count = messageRefDao.searchUnreadCount(userId);
return count;
}
@Override
public long searchLastCount(int userId) {
long count = messageRefDao.searchLastCount(userId);
return count;
}
@Override
public List<HashMap> searchMessageByPage(int userId, long start, int length) {
List<HashMap> list = messageDao.searchMessageByPage(userId, start, length);
return list;
}
@Override
public HashMap searchMessageById(String id) {
HashMap map = messageDao.searchMessageById(id);
return map;
}
@Override
public long updateUnreadMessage(String id) {
long rows = messageRefDao.updateUnreadMessage(id);
return rows;
}
@Override
public long deleteMessageRefById(String id) {
long rows = messageRefDao.deleteMessageRefById(id);
return rows;
}
@Override
public long deleteUserMessageRef(int userId) {
long rows=messageRefDao.deleteUserMessageRef(userId);
return rows;
}
}
创建消息模块的Web层
获取分页消息列表
创建SearchMessageByPageForm.java类
@ApiModel
@Data
public class SearchMessageByPageForm {
@NotNull
@Min(1)
private Integer page;
@NotNull
@Range(min = 1,max = 40)
private Integer length;
}
创建MessageController.java类
@RestController
@RequestMapping("/message")
@Api("消息模块网络接口")
public class MessageController {
@Autowired
private JwtUtil jwtUtil;
@Autowired
private MessageService messageService;
@PostMapping("/searchMessageByPage")
@ApiOperation("获取分页消息列表")
public R searchMessageByPage(@Valid @RequestBody SearchMessageByPageForm form, @RequestHeader("token") String token) {
int userId = jwtUtil.getUserId(token);
int page = form.getPage();
int length = form.getLength();
long start = (page - 1) * length;
List<HashMap> list = messageService.searchMessageByPage(userId, start, length);
return R.ok().put("result", list);
}
}
根据ID查询消息
创建SearchMessageByIdForm.java类
@ApiModel
@Data
public class SearchMessageByIdForm {
@NotBlank
private String id;
}
在MessageController.java中编写Web方法
public class MessageController {
……
@PostMapping("/searchMessageById")
@ApiOperation("根据ID查询消息")
public R searchMessageById(@Valid @RequestBody SearchMessageByIdForm form) {
HashMap map = messageService.searchMessageById(form.getId());
return R.ok().put("result", map);
}
}
把未读消息更新成已读消息
创建UpdateUnreadMessageForm.java类
@ApiModel
@Data
public class UpdateUnreadMessageForm {
@NotBlank
private String id;
}
在MessageController.java中编写Web方法
public class MessageController {
……
@PostMapping("/updateUnreadMessage")
@ApiOperation("未读消息更新成已读消息")
public R updateUnreadMessage(@Valid @RequestBody UpdateUnreadMessageForm form) {
long rows = messageService.updateUnreadMessage(form.getId());
return R.ok().put("result", rows == 1 ? true : false);
}
}
删除消息
创建DeleteMessageRefByIdForm.java类
@Data
@ApiModel
public class DeleteMessageRefByIdForm {
@NotBlank
private String id;
}
在MessageController.java中编写Web方法
public class MessageController {
……
@PostMapping("/deleteMessageRefById")
@ApiOperation("删除消息")
public R deleteMessageRefById(@Valid @RequestBody DeleteMessageRefByIdForm form){
long rows=messageService.deleteMessageRefById(form.getId());
return R.ok().put("result", rows == 1 ? true : false);
}
}