chatService第一阶段
在第一版本中这个项目我实现了好友模块相关功能的实现,有添加,删除,拉黑老友,拒绝申请还有一些查询功能,后来接入了sso,使用到了ThreadLocal来存储登录用户信息,通过Aop实现了操作记录日志的功能.
在这期间遇到了很多的问题.总结以下重点问题.
在第一个添加好友功能里面要实现一连串的验证,并且之后验证还可能增加,需要可拓展性,可拓展性可以使用ioc来实现,但是一连串验证在搜索之后,发现有责任链和规则链.
责任链是每一个验证都会执行,规则链是如果其中一个满足了条件可以终止执行,很明显,在我们添加好友验证中只要一个不满足停止了,所以我们选用规则链.在写规则的时候也出现了一些错误,比如数字判断可以使用NumberUtil.equals,我开始使用了ObjectUtil.
规则链代码:
@Service
public class RuleChain {
@Resource
private ReviewMapper reviewMapper;
@Resource
List<Rule> rules;
public boolean validate(AddFriendDto addFriendDto) {
for (Rule rule : rules) {
if (!rule.validate(addFriendDto)) {
return false;
}
}
ReviewPo reviewPo = ReviewPo.builder()
.fromUserId(addFriendDto.getFromUserId())
.toUserId(addFriendDto.getToUserId())
.greeting(addFriendDto.getGreeting())
.source(addFriendDto.getSource())
.build();
reviewMapper.insert(reviewPo);
CaLoginUser caLoginUser = LoginUserHolder.get();
caLoginUser.setTraceId(reviewPo.getId());
LoginUserHolder.set(caLoginUser);
return true;
}
}
@Component
@Order(1)
public class OneRule extends Rule {
@Resource
private FriendMapper friendMapper;
@Resource
private RedissonClient redissonClient;
@Override
public boolean validate(AddFriendDto addFriendDto) {
FriendPo friendPo = friendMapper.selectOne(new LambdaQueryWrapper<FriendPo>().eq(FriendPo::getUserId, addFriendDto.getFromUserId())
.eq(FriendPo::getFriendId, addFriendDto.getToUserId()));
//没有拉黑和删除
if (ObjectUtil.isNotNull(friendPo)&&NumberUtil.equals(friendPo.getIsBlack(),YesOrNo.NO.getCode())&&NumberUtil.equals(friendPo.getDelFlag(),YesOrNo.NO.getCode())) {
throw new ReviewException("你们已经是好友,无法发起申请");
}
redissonClient.getBucket("friend"+String.valueOf(addFriendDto.getFromUserId() + addFriendDto.getToUserId())).set(friendPo);
return true;
}
}
在规则链条中,我开始每一次都去查询了数据库,但是后来发现有的查询是重复的,最后把相同的第一次查询结果放到了redis里面,这样可以减轻数据库的压力.
在接入sso的时候,也用到了以前没注意的在方法内发起网络请求.
HttpUtil.get(URL,ImmutableMap.<String, Object>of("token",StrUtil.trimToEmpty(token)))
,可以发起get或者post请求,第一个参数是URL,第二个是参数,可以直接使用Map来存.
关于ThreadLocal,因为我们每一次网络请求,都是一个独立的线程,所以用ThreadLocal来存储用户信息,相当于存了一个全局变量,可以在任何位置都得到这个参数,非常方便.
public class LoginUserHolder {
private static final ThreadLocal<CaLoginUser> LONGIN_USER_HOLDER = new ThreadLocal<CaLoginUser>();
/**
* set holder中内容
*
* @author cong.zhen
* @date 2023/01/29
*/
public static void set(CaLoginUser abstractLoginUser) {
LONGIN_USER_HOLDER.set(abstractLoginUser);
}
/**
* 获取holder中的值
*
* @author cong.zhen
* @date 2023/01/29
*/
public static CaLoginUser get() {
return LONGIN_USER_HOLDER.get();
}
/**
* 得到真实姓名
*
* @author cong.zhen
* @date 2023/01/29
*/
public static String getUserName() {
CaLoginUser caLoginUser = LONGIN_USER_HOLDER.get();
if (ObjectUtil.isNull(caLoginUser)) {
return StrUtil.EMPTY;
}
return caLoginUser.getUsername();
}
/**
* 删除保存的用户
*
* @author cong.zhen
* @date 2023/01/29
*/
public static void remove() {
LONGIN_USER_HOLDER.remove();
}
}
最后实现了通过Aop来实现操作记录日志的功能,在这个里面也遇到了一些问题,我需要实现将当前操作的数据库相关记录的id存起来,修改和删除的可以直接获取到id,但是插入的需要使用mabatisplus回填主键来实现,通过搜索和尝试发现,使用mybatisplus自带的Insert可以自动实现回填主键,只需要在ID上设置相关的规则,自增或者雪花算法等.其次这个id也应该是一个全局变量,我就把他存储到了用户信息里面来实现这个功能.
reviewMapper.insert(reviewPo);
CaLoginUser caLoginUser = LoginUserHolder.get();
caLoginUser.setTraceId(reviewPo.getId());
LoginUserHolder.set(caLoginUser);
还没有评论,来说两句吧...