前言
很不容易哈,最近事情比较多,也是终于抽到空,水那么一两篇博文了。那么咱们速战速决,要源码的朋友得等等,因为还在开发当中。不过这块的话我会准备两个版本,一个就是很随意的版本,也就是现在写的版本,这个方便理解里面的功能实现。还有一个版本就是优化版本,代码会看起来更舒服,一开始我是想好好写的,但是一方面时间问题断断续续的,还有一方面也是懒,不想去整理,毕竟直接cv比造一些小轮子要快。
效果
首先我们可以看到这里有一个用户,叫做Huterox03
之后是我们的第二个用户Huterox
Test社区是Huterox03用户创建的社区,当这个用户点击,选择加入自己的社区的时候会提示不行。
WhiteHole社区是用户Huterox创建的社区,此时Huterox03用户点击加入WhiteHole社区
这个时候,在Huterox用户的消息页面当中,就会出现这个消息,以及对应的消息提示
点击消息的头部,还可以查看到对方用户的用户信息页面,然后这个信息页面的关注按钮变成了这个同意按钮(我是打算重新设计一个页面的,但是这个还是以后再说吧)
之后当Huterox作为管理员,同意之后的话,Huterox03会受到消息,然后可以查看到消息,还可以看到对应的由nutty消息服务器传过来的消息。
可以看到此时接收到的消息的列表。
效果大概就是这样的。
流程
技术难度的话,几乎没有,说白了还是CURD那一套,只是中间调用了一些其他的服务来完成业务罢了,写这个烦的只是接口调试罢了。
此外这里值得一提的是,这里对与社区的创建者是保密的,不会在用户的界面展示,但是后台还是可以查看的,主要是出于对创建者的保护(好吧是我忘了写展示页面了)
搞清楚了这个那么接下来就简单了。
这里前端代码我就不给了,无非是socket网络连接,然后接受罢了。而且代码先前也是给过的。
所以的话,我们来聊聊这个服务之间的一个推送。
请求服务
判断当前用户
首先是我们需要对当前的用户进行一个判断。 是不是社区的创建者,然后前端提交的这个userid到底是不是存在的。虽然咱们这个一开始会先进行一个校验,但是为了安全嘛,理论上来说,通过了token校验,用户是存在的。但是这种事情保险一点总没错。
String userid = joinQ.getUserid();
Long communityid = joinQ.getCommunityid();
String backMessage = "已经通知社区管理员请等待哟~";
if(redisUtils.hasKey(RedisTransKey.getRedisJoinCommunity(userid+"_"+communityid))){
return R.error(BizCodeEnum.OVER_REQUEST.getCode(), BizCodeEnum.OVER_REQUEST.getMsg());
}
//分别对社区,对用户进行校验
CommunityEntity comm = communityService.getById(communityid);
if(comm==null){
return R.error(BizCodeEnum.NO_SUCHCOMMUNITY.getCode(),BizCodeEnum.NO_SUCHCOMMUNITY.getMsg());
}
//此时查看当前是不是自己加入自己的社区
if(comm.getUserid().equals(userid)){
backMessage="看来您对您自己的社区很满意哇~";
return R.ok(backMessage);
}
R info = feignUserService.info(userid);
String userString = FastJsonUtils.toJson(info.get("user"));
UserEntity user = FastJsonUtils.fromJson(userString, UserEntity.class);
if(user==null){
return R.error(BizCodeEnum.NO_SUCHUSER.getCode(),BizCodeEnum.NO_SUCHUSER.getMsg());
}
//都通过之后的话,我们开始发送消息给服务,这个是审核消息,直接发送即可
消息转发
之后的话就是咱们的消息的转发。
HoleAduitMsgQ holeAduitMsgQ = new HoleAduitMsgQ();
holeAduitMsgQ.setMsgtitle("加入社区申请");
holeAduitMsgQ.setMsg(user.getNickname()+"申请加入:"+comm.getCommunityTitle()+"社区");
//消息是转发给管理员的
holeAduitMsgQ.setUserid(comm.getUserid());
holeAduitMsgQ.setLinkid(userid);
holeAduitMsgQ.setLinkid2(String.valueOf(communityid));
// 1-文章,2-提问,3-回答,4-pushAc,5-Merge,6-社区成员申请,7-成员请求成功
holeAduitMsgQ.setType(6);
feignHoleAduitMsgService.holeAduitMsg(holeAduitMsgQ);
那么这里的话调用到了一个远程的nutty接口,这个接口是这样的:
@Service
public class HoleAduitMsgServiceImpl implements HoleAduitMsgService {
@Autowired
HoleAuditService auditService;
@Override
public R holeaduitMsg(HoleAduitMsgQ holeAduitMsgQ) {
//1.对消息进行存储,只要用户在线的话,我们就直接先给他签收一下
String userid = holeAduitMsgQ.getUserid();
Channel channel = UserConnectPool.getChannelFromMap(userid);
HoleAuditEntity holeAuditEntity = new HoleAuditEntity();
BeanUtils.copyProperties(holeAduitMsgQ,holeAuditEntity);
holeAuditEntity.setCreateTime(DateUtils.getCurrentTime());
if(channel!=null){
//这边只是保证存在,双层保险,这个时候的话就是在线
Channel realChannel = UserConnectPool.getChannelGroup().find(channel.id());
if(realChannel!=null){
holeAuditEntity.setStatus(1);
//我们这边直接转发消息就好了,不需要再额外处理
realChannel.writeAndFlush(
new TextWebSocketFrame(
JsonUtils.objectToJson(
Objects.requireNonNull(R.ok().put("data", holeAuditEntity))
.put("type", MessageActionEnum.HOLEADUITMSG.type)
)
)
);
}else {
//状态为2表示当前用户可能由于什么原因没有和我们的消息服务器连接
holeAuditEntity.setStatus(2);
}
}else {
holeAuditEntity.setStatus(2);
}
//这里进行消息的存储
auditService.save(holeAuditEntity);
return R.ok();
}
}
完整代码
那么这里的话,就是完成了咱们的一个处理
public R JoinUser(JoinQ joinQ) {
/**
* 这里负责用户社区的加入
* 这个userid是谁要加入我们这个社区
* 1. 判断用户是不是加入了
* 2. 通知社区对应的管理员,让管理员进行审核
* 3. 管理员审核通过后,完成用户的加入
* 4. 这个接口限制1分钟一次
* */
String userid = joinQ.getUserid();
Long communityid = joinQ.getCommunityid();
String backMessage = "已经通知社区管理员请等待哟~";
if(redisUtils.hasKey(RedisTransKey.getRedisJoinCommunity(userid+"_"+communityid))){
return R.error(BizCodeEnum.OVER_REQUEST.getCode(), BizCodeEnum.OVER_REQUEST.getMsg());
}
//分别对社区,对用户进行校验
CommunityEntity comm = communityService.getById(communityid);
if(comm==null){
return R.error(BizCodeEnum.NO_SUCHCOMMUNITY.getCode(),BizCodeEnum.NO_SUCHCOMMUNITY.getMsg());
}
//此时查看当前是不是自己加入自己的社区
if(comm.getUserid().equals(userid)){
backMessage="看来您对您自己的社区很满意哇~";
return R.ok(backMessage);
}
R info = feignUserService.info(userid);
String userString = FastJsonUtils.toJson(info.get("user"));
UserEntity user = FastJsonUtils.fromJson(userString, UserEntity.class);
if(user==null){
return R.error(BizCodeEnum.NO_SUCHUSER.getCode(),BizCodeEnum.NO_SUCHUSER.getMsg());
}
//都通过之后的话,我们开始发送消息给服务,这个是审核消息,直接发送即可
//查看当前的这个成员是不是已经加入了
Map<String, Object> params = new HashMap<>();
params.put("userid",user.getUserid());
params.put("communityid",communityid);
R r = feignCommunityisInService.communityisIn(params);
String in = FastJsonUtils.toJson(r.get("in"));
CommunityJoinEntity isJoin = FastJsonUtils.fromJson(in, CommunityJoinEntity.class);
//此时已经存在了
if(isJoin !=null){
backMessage = "您已经加入该社区了";
redisUtils.set(RedisTransKey.setJoinCommunityKey(userid)
,1,1, TimeUnit.MINUTES
);
return R.ok(backMessage);
}
HoleAduitMsgQ holeAduitMsgQ = new HoleAduitMsgQ();
holeAduitMsgQ.setMsgtitle("加入社区申请");
holeAduitMsgQ.setMsg(user.getNickname()+"申请加入:"+comm.getCommunityTitle()+"社区");
//消息是转发给管理员的
holeAduitMsgQ.setUserid(comm.getUserid());
holeAduitMsgQ.setLinkid(userid);
holeAduitMsgQ.setLinkid2(String.valueOf(communityid));
// 1-文章,2-提问,3-回答,4-pushAc,5-Merge,6-社区成员申请,7-成员请求成功
holeAduitMsgQ.setType(6);
feignHoleAduitMsgService.holeAduitMsg(holeAduitMsgQ);
//存储成功设置标志
redisUtils.set(RedisTransKey.setJoinCommunityKey(userid+"_"+communityid)
,1,10, TimeUnit.MINUTES
);
return R.ok(backMessage);
}
审核服务
之后的话,是咱的审核服务,这个的话其实也是,首先消息的服务是共用一个,但是的话,咱们的这个的话,对与数据的校验什么的稍微复杂一点儿。
完整代码长这样,很大一部分是在构建消息类,实体类,然后是对用户的行为进行一定的约束。
public R AcJoinUser(AcJoinQ acJoinQ) {
/**
* 这里进行10秒限制
* 1. 先进行疯狂校验
* 2. 进行存储
* 3. 通知用户
* */
String userid = acJoinQ.getUserid();
String backMessage = "操作完成,已通知该成员";
if(redisUtils.hasKey(RedisTransKey.getAcAuthority(userid))){
return R.error(BizCodeEnum.TOO_FASTAUTHORITY.getCode(), BizCodeEnum.TOO_FASTAUTHORITY.getMsg());
}
Long communityid = acJoinQ.getCommunityid();
String membersid = acJoinQ.getMembersid();
//先对社区进行校验
CommunityEntity comm = communityService.getById(communityid);
if(comm==null){
return R.error(BizCodeEnum.NO_SUCHCOMMUNITY.getCode(),BizCodeEnum.NO_SUCHCOMMUNITY.getMsg());
}
String manageID = comm.getUserid();
if(!manageID.equals(userid)){
//此时可以判断为非法越权操作,直接封杀2个小时
redisUtils.set(RedisTransKey.setAcAuthority(userid)
,1,120, TimeUnit.MINUTES
);
return R.error(BizCodeEnum.BAD_AUTHORITY.getCode(),BizCodeEnum.BAD_AUTHORITY.getMsg());
}
//对用户和成员进行校验
R info = feignUserService.info(userid);
String userString = FastJsonUtils.toJson(info.get("user"));
UserEntity manager = FastJsonUtils.fromJson(userString, UserEntity.class);
if(manager==null){
return R.error(BizCodeEnum.NO_SUCHUSER.getCode(),BizCodeEnum.NO_SUCHUSER.getMsg());
}
info = feignUserService.info(membersid);
userString = FastJsonUtils.toJson(info.get("user"));
UserEntity members = FastJsonUtils.fromJson(userString, UserEntity.class);
if(members==null){
return R.error(BizCodeEnum.NO_SUCHUSER.getCode(),BizCodeEnum.NO_SUCHUSER.getMsg());
}
UsersEntity usersEntity = new UsersEntity();
CommunityJoinEntity communityJoinEntity = new CommunityJoinEntity();
//查看当前的这个成员是不是已经加入了
Map<String, Object> params = new HashMap<>();
params.put("userid",membersid);
params.put("communityid",communityid);
R r = feignCommunityisInService.communityisIn(params);
String in = FastJsonUtils.toJson(r.get("in"));
CommunityJoinEntity isJoin = FastJsonUtils.fromJson(in, CommunityJoinEntity.class);
//此时已经存在了
if(isJoin !=null){
backMessage = "您已加入此社区";
redisUtils.set(RedisTransKey.setAcAuthority(manageID)
,1,10, TimeUnit.SECONDS
);
return R.ok(backMessage);
}
//查询成员的头像信息
R RHeadImg = feignHeadimgService.headimg(membersid);
String headImgString = FastJsonUtils.toJson(RHeadImg.get("headimg"));
HeadimgEntity headimg_members = FastJsonUtils.fromJson(headImgString, HeadimgEntity.class);
if(headimg_members!=null){
usersEntity.setUserimg(headimg_members.getImgpath());
}
//查询管理员头像信息
RHeadImg = feignHeadimgService.headimg(manageID);
headImgString = FastJsonUtils.toJson(RHeadImg.get("headimg"));
HeadimgEntity headimg_manage = FastJsonUtils.fromJson(headImgString, HeadimgEntity.class);
if(headimg_manage!=null){
communityJoinEntity.setCommunityImg(headimg_manage.getImgpath());
}
//此时进行存储
usersEntity.setUserid(membersid);
usersEntity.setUserNickname(members.getNickname());
usersEntity.setCommunityid(communityid);
usersEntity.setCommunityName(comm.getCommunityTitle());
usersEntity.setCreateTime(DateUtils.getCurrentTime());
usersService.save(usersEntity);
//更新成员的一个社区加入的情况
communityJoinEntity.setCommunityImg(comm.getCommunityImg());
communityJoinEntity.setCommunityInfo(comm.getCommunityInfo());
communityJoinEntity.setCommunityid(comm.getCommunityid());
communityJoinEntity.setCommunityUserid(comm.getUserid());
communityJoinEntity.setCommunityUserNickname(comm.getUserNickname());
communityJoinEntity.setCommunityName(comm.getCommunityTitle());
communityJoinEntity.setUserid(membersid);
communityJoinEntity.setCommunityJoinTime(DateUtils.getCurrentTime());
feignCommunityJoinService.save(communityJoinEntity);
//此时向用户发送消息,告诉用户社区申请通过
HoleAduitMsgQ holeAduitMsgQ = new HoleAduitMsgQ();
holeAduitMsgQ.setMsgtitle("您的申请已经通过");
holeAduitMsgQ.setMsg("Congratulations,成为"+comm.getCommunityTitle()+"的一员!");
holeAduitMsgQ.setUserid(membersid);
holeAduitMsgQ.setLinkid(String.valueOf(comm.getCommunityid()));
// 1-文章,2-提问,3-回答,4-pushAc,5-Merge,6-成员,7-成员请求成功
holeAduitMsgQ.setType(7);
feignHoleAduitMsgService.holeAduitMsg(holeAduitMsgQ);
//存储成功设置标志
redisUtils.set(RedisTransKey.setAcAuthority(manageID)
,1,10, TimeUnit.SECONDS
);
backMessage = "操作完成,已通知该成员";
return R.ok(backMessage);
}
总结
今天的话,就写了这两个功能,ok,接下来要去背单词了。