online-questioning 从零开始开发在线问答平台, 这是我模仿知乎做的一个贴吧类问答交流平台

项目github地址:https://github.com/guomzh/online-questioning , 欢迎各位star和与我交流

本文持续更新,未完待续…

使用到的技术栈:

1、spring/springboot
* intercepter拦截器实现登录权限控制
* javax.mali邮件服务,如有新评论时发邮件通知用户,注册时邮件验证
* ioc项目容器中对象管理,对容器中beans操作
* aop平台日志操作记录
* maven管理整个项目依赖
2、mybatis操作数据库主要业务数据
3、前端模板引擎freemarker ,渲染整个前端模板
4、算法设计:trie前缀树实现网站敏感词过滤
5、Redis实现异步队列,利用多线程实现异步事件处理,主要针对一些耗时操作,进行异步执行,如发邮件,评论后发站内私信通知等
6、使用 Redis 数据结构中的 set 集合实现用户对问题评论的点赞点踩功能
7、solr导入mysql数据,建立问题和标题文档库,利用ik-analyzer进行中文分词,用户可以进行站内全文搜索

开发通用的新模块流程:

1、数据库设计
2、Model:模型定义,与数据库相匹配
3、Dao层:数据操作
4、Service:服务包装
5、Controller:业务入口,数据交互
6、单元测试

注册模块:

  1. 用户名合法性检测(长度,敏感词,重复,特殊字符)
  2. 密码长度要求
  3. 密码salt加密,密码强度检查(md5库)
  4. 用户注册邮件激活

我在实现用户注册邮箱激活时自己的实现思路:
当用户提交注册表单信息时,把表单信息存到redis的hash数据结构中,同时产生一个对应的key,
这时发布一个异步事件,发送一封邮件,同时把这个key放到链接中发到用户的注册邮箱中,当用户
访问邮箱中这个链接时,在redis中查出这个key对应的注册信息,并存到数据库中完成注册

  //信息存到redis中String register_ticket=OnlineQUtil.MD5(email);redisAdapter.hset(register_ticket,"email",email);redisAdapter.hset(register_ticket,"username",username);redisAdapter.hset(register_ticket,"password", password);redisAdapter.expire(register_ticket,60*15);redisAdapter.sadd("email",email);//发布异步事件eventProducer.fireEvent(new EventModel(EventType.REGISTER).setExt("register_ticket",register_ticket).setExt("email",email));//发送邮件@Overridepublic void doHandle(EventModel model) {Map<String ,Object> map=new HashMap<>();map.put("url","http://127.0.0.1:8080/regVerify?p="+model.getExt("register_ticket"));mailSender.sendWithHTMLTemplate(model.getExt("email"),"<我的知乎——在线问答平台>注册激活邮件","mails/register_email.html", map);}//从redis中读取注册信息,完成注册if(redisAdapter.exists(p)){try {String email=redisAdapter.hget(p,"email");String username=redisAdapter.hget(p,"username");String password=redisAdapter.hget(p,"password");}...}

登录模块

1、服务器密码校验/三方校验,token(sessionId或者cookie的一个key)登记
* 服务器端token关联userId
* 客户端存储token(本地或者cookie)

2、服务器端/客户端token设置有效期(记住登录)
3、登出:服务器端/客户端token删除或者session清理

问题发布模块

  • HTML/敏感词过滤
  //html过滤question.setContent(HtmlUtils.htmlEscape(question.getContent()));敏感词过滤通过Trie树存储敏感词汇,匹配文本串,对匹配到的敏感词打码或者删除
  • 多线程

关于多线程的一些运用知识回顾如下:

  Future作用:进行线程与线程间通信1. 返回异步结果:Future<Integer>future =service.submit(new Callable<Integer>{ });2. 阻塞等待返回结果(future.get())3. timeout(future.get(100,TimeUnit.MILLISECONDS))4. 获取线程中的Exception

评论中心

消息中心(赞,评论通知,私信通知,回答采纳等)

Redis数据结构使用场景

List Set SortedSet Hash KV
用途 栈操作,双向列表,使用于最新列表,关注列表 适用于无顺序的集合,点赞点踩,抽奖,已读,共同好友 排行榜,优先队列 对象属性,不定长
api lpush sdiff zadd hset
api lpop smembers zscore hget
api blpop sinter zrange hgetAll
api lindex scard zcount hexists
api lrange zrank hkeys
api lrem zrevrank hvals
api linsert
api lset
api rpush

例如:实现PV(page views)点击量功能等

  • 点赞(Set) 操作:sadd, srem, sismembers等
  • 关注(Set)
  • 排行榜(SortedSet)
  • 验证码(KV)
  • 缓存(序列化存KV)
  • 异步队列(中间层)
  • 判断队列(中间层)

异步队列实现

例如:实现评论后给提问者发一条站内通知功能

问题评论邮件通知功能实现,手写一个异步实现代码

思路:
* 自己手动实现一个异步队列
* 用redis做异步消息队列实现,利用多线程来实现异步发送邮件
* 用javax.mail发送邮件,使用smtps协议
技术关键流程:
1、定义消息事件接口

public interface EventHandler {void doHandle(EventModel model);List<EventType> getSupportEventTypes();
}

2、定义消息模型,可以用map的数据结构来实现
3、定义生产者,发布消息到redis构建的异步队列中(利用redis的阻塞队列操作)

public class EventProducer {@Autowiredprivate RedisAdapter redisAdapter;public boolean fireEvent(EventModel eventModel) {try {String json = JSONObject.toJSONString(eventModel);String key = RedisKeyUtil.getEventQueueKey();redisAdapter.lpush(key, json);return true;} catch (Exception e) {return false;}}
}

4、发布事件
5、定义消费者,开启多线程异步处理事件

         Thread thread =new Thread(new Runnable() {@Overridepublic void run() {while (true){String key= RedisKeyUtil.getEventQueueKey();List<String> events =redisAdapter.brpop(0,key);for(String message:events){//消息队列的第一个值可能是key,返回值的原因if(message.equals(key)){continue;}EventModel eventModel= JSON.parseObject(message,EventModel.class);if(!config.containsKey(eventModel.getType())){logger.error("不能识别的事件");continue;}for(EventHandler handler :config.get(eventModel.getType())){handler.doHandle(eventModel);}}}}});thread.start();

关注服务,如A关注了某人,某问题

分一下功能点:
* 首页问题关注数
* 详情页问题关注列表
* 粉丝/关注人列表
* 关注接口设计,关注列表分页
* 关注异步事件处理

存储结构:
redis: zset / list

平台内容排序算法:

1、Score = (P-1)/(T+2)^G
P表示投票数,G表示分值根据时间降低速率,相当于重力加速度,T表示发布到现在时间间隔,单位小时
2、f(t,x,y,z)=log z + yt/45000
t等于发布到现在的时间差,如一个差86400秒
x等于赞数-踩数
如果x大于0则y=1,x小于0则y=-1,x=0则y=0
z等于x的绝对值,如果x=0,则z=1

未完待续。。。

模仿知乎——实现一个多用户在线问答平台相关推荐

  1. java计算机毕业设计在线问答平台MyBatis+系统+LW文档+源码+调试部署

    java计算机毕业设计在线问答平台MyBatis+系统+LW文档+源码+调试部署 java计算机毕业设计在线问答平台MyBatis+系统+LW文档+源码+调试部署 本源码技术栈: 项目架构:B/S架构 ...

  2. 一个书籍在线写作平台

    用过很多写作编辑的平台,例如印象笔记,有道云,简书的Markdown,还有腾讯在线文档,语雀等等,各有优缺点. 印象笔记:https://www.yinxiang.com/ 有道云:http://no ...

  3. 在线问答“三重门”:知识、营销与服务直达

    文 | 曾响铃 来源 | 科技向令说(xiangling0815) 当舆论的目光都聚焦在短视频.直播这些新潮热门领域时,内容赛道上的那些"老玩法"却默默表现出新的价值潜力,值得业界 ...

  4. springboot基于web的在线问答社区系统设计与实现毕业设计源码061628

    Springboot在线问答社区系统 摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以 ...

  5. (附源码)springboot+mysql+基于web的在线问答社区系统设计与实现 毕业设计061628

    Springboot在线问答社区系统 摘要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻 ...

  6. (附源码)Springboot在线问答社区系统 毕业设计061628

    Springboot在线问答社区系统 摘要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻 ...

  7. Springboot在线问答社区系统 毕业设计-附源码061628

    Springboot在线问答社区系统 摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以 ...

  8. springboot+mysql+基于web的在线问答社区系统设计与实现 毕业设计-附源码061628

    Springboot在线问答社区系统 摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以 ...

  9. TableStore发布多元索引功能,打造统一的在线数据平台

    什么是NoSQL "NoSQL"一词最早出现在1998年,距今刚好二十年.站在今天回头看的话,很少有人能想到在关系型数据库成熟发展了三十年,已经在数据存储领域占据了不可动摇的的地位 ...

最新文章

  1. 菜鸟学Linux命令:ssh命令 远程登录
  2. AAuto 快速开发win32小程序
  3. 二分查找算法的两种实现方式:非递归实现和递归实现
  4. golang 切片 接口_Golang简单入门教程——函数进阶使用
  5. 浅谈主流内存发展历史
  6. 事件冒泡及阻止事件冒泡 事件的触发 事件参数对象 获取用户按下键盘的键
  7. Java –手工Classloader隔离
  8. 论文浅尝 | 二维卷积知识图谱嵌入
  9. 一阶广义差分模型_贵州茅台(600519)股价预测 (ARIMA模型)
  10. 堆栈的缓冲区溢出进不了系统_一文理解缓冲区溢出
  11. 洛谷——P1046 [NOIP2005 普及组] 陶陶摘苹果
  12. 51Nod - 1051(思维)
  13. 如何用MAYA 制作人物动画 使人物动作更加真实流畅
  14. 软件界面设计思想方法
  15. 在线生成ico图标的网站
  16. C语言---数组排序
  17. bigdecimal负数变正数_Java中BigDecimal的8种舍入模式
  18. amd的服务器cpu型号大全,amdcpu型号大全
  19. C#实战之CAD二次开发002:绘制直线和绘制圆
  20. OGEM Solids Control Drilling oil fluid mud purification process

热门文章

  1. 再也不用找图源了!完美替代奥维地图,支持查看全球高清卫星地图3D地形
  2. 基于vscode安装pytorch
  3. python用mpl_finance中的candlestick_ohlc画分时图
  4. 如何做一个智能问答系统及neo4j可视化
  5. 分布式锁和分布式事务和分布式Session
  6. 字符串去重的(6)种方法
  7. MFC中Listbox控件的简单使用
  8. 004 json介绍
  9. 阿里云配置https,配置SSL证书
  10. 推荐收藏!10大程序员必备生产力工具