BBS论坛项目总结(持更)
总结各个功能实现的简单思路,自己按心情总结的,持续更新中~~
源码百度云地址:链接:https://pan.baidu.com/s/1ix2MN2-JKwbeGrIg59WAQw
提取码:yhk3
注册:
前端表单提交后,依次检验用户信息是否完整,并通过mailClient.process("/mail/activation",content)将模板和内容发邮件到指定邮箱,里面包含一条激活链接,里面拼接了用户id和code。
邮件激活:
链接对应的url作为邮箱激活的path,将用户id和code接收后调用service层,查看用户状态是否已激活,已激活则返回状态到controller层,否则验证code是否与用户对应code是否一致,一致则成功激活,更改用户状态,并返回状态值,controller接收到状态值后返回对应状态信息填充到前端。
用户登陆:
设计一个登陆凭证类包含用户id,ticket用户登陆的唯一凭证,过期时间,登陆状态,在service层验证用户名,密码之后,生成登陆凭证,并将生成UUID作为ticket传入map返回controller层。
controller层从session中取出验证码校验,查看是否记住我,如果已勾选记住我,则将登陆凭证的过期时间设置长一点,调用service层登陆逻辑,若返回中有ticket则返回登录成功。
登陆凭证类相当于一个session的作用,若全部校验成功则生成一个唯一标识登陆凭证,这样可以通过唯一标识直接访问。
显示登录信息:
每次发出请求都要渲染登录消息这一栏,所以用拦截器实现,在preHandler中从cookie中取出ticket,验证用户凭证后通过,为了便于后面业务中可能常用到用户信息,可以在验证通过后将用户信息暂存,考虑到线程并发安全问题,编写一个HostHolder类用threadLocal保存用户信息。
检查登陆状态:
对登陆后才能访问的方法进行拦截,采用自定义注解的方式,若方法有该注解且未持有该用户,则进行拦截。
过滤敏感词:
构建前缀树,将敏感词写成文本读入前缀树,做敏感词过滤。
帖子发布:
service层过滤敏感词,controller层先判断是否持有该用户,在发送帖子成功或失败时返回json字符串用于异步显示消息,不用重复刷新页面,可用fastjson将转换成json字符串封装为工具类。
帖子评论显示:
评论类的属性有评论id;userId;entityType(评论对象类型,帖子或评论);entityId(评论对象id);targetId(回复目标的用户id);content;status;createTime;
查看一个帖子评论时,先根据查询帖子对应信息,再根据帖子中的用户id查询用户信息,用于显示帖子自身的信息。
再根据帖子entityType和帖子id作为entityId在comment表中查询帖子对应评论,返回一个List,
对于返回的comment集合中只有关于comment自身的信息,所以需要遍历list,依次查询评论对应的用户信息,以及以后会补充的点赞信息等,由于评论有关于帖子的评论和关于评论的回复,所以还需要在遍历中获得关于评论的回复信息。因此用一个List<Map<String,Object>>类型来进行存储较为合适。
每个评论都对应存储一个map结构,里面会放置user信息等,如果该评论还有回复,根据评论的entityType和entityId查询得到一个回复列表reply,创建一个replyList,也是List<Map<String,Object>>,遍历回复列表reply,将每条回复的用户信息等放入replyList的map中。
遍历结束后将replyList放入comment的map中,key值为”reply“,最后遍历结束将comment的List<Map<String,Object>>放入model中,在前端依次遍历循环拿取数据。
添加评论:
添加评论时,由于在帖子的表中有评论数量的属性,所以在添加评论时要同时更新帖子中评论数量,即构建事务。
评论成功后应跳转到帖子页面,所以还要从前端携带帖子id传回后端,便于跳转页面。(帖子详情页的路径带有帖子id)。
会话列表
会话表:id,from_id,to_id,conversationId,status,createTime。
查询会话列表总条数,且每条会话只显示最新的私信内容。先按照conversationId进行分组,当状态合法且from_id或to_id有一个当前用户id,且from_id不能为1,1是系统消息,从中筛选id最大的那条私信内容就是最新的需要显示的私信内容。
同样会话列表数为最大id的数量。
controller层先从ThreadLocal中获取当前用户信息,根据用户id查询会话列表,同样需要将会话列表遍历,将每条会话信息放入List<Map<String,Object>>中,如消息本身,每条消息的对话数量,未读数量以及target_id(不能直接用from_id,因为可能是自己发送过去的,需要把from_id与当前用户id进行比较,看from_id和to_id谁才是target)。
还需要查询总的未读私信数和会话数。
会话详情:
对于具体的会话页,可根据conversationId查询所有会话,返回一个list,同样遍历list,将信息本身和发送消息的用户存入List<Map<String,Object>>,同样由于发送消息的用户可能是自己,所以需要明确target对象,可通过conversationId比较得出,也可从某条会话中得出。
进入了会话页,说明所有消息已读,此时需要改变状态,可能需要改变多条消息的状态为已读,所以封装一个方法将用户id查询得到的消息列表传入,判断这些消息中当前用户为接收消息的用户即to_id且消息状态为未读的所有消息,返回未读消息列表。
SQL语句: