实战:功能强大齐全BBS论坛项目Echo简介

项目简介

Echo 是一套前后端不分离的开源社区系统,基于目前主流 Java Web 技术栈(SpringBoot + MyBatis + MySQL + Redis + Kafka + Elasticsearch + Spring Security + ...),并提供详细的开发文档和配套教程。包含帖子、评论、私信、系统通知、点赞、关注、搜索、用户设置、数据统计等模块。

功能

图片

技术栈

后端:

  • Spring

  • Spring Boot 2.1.5 RELEASE

  • Spring MVC

  • ORM:MyBatis

  • 数据库:MySQL 5.7

  • 分布式缓存:Redis

  • 本地缓存:Caffeine

  • 消息队列:Kafka 2.13-2.7.0

  • 搜索引擎:Elasticsearch 6.4.3

  • 安全:Spring Security

  • 邮件任务:Spring Mail

  • 分布式定时任务:Spring Quartz

  • 日志:SLF4J(日志接口) + Logback(日志实现)

前端:

  • Thymeleaf

  • Bootstrap 4.x

  • Jquery

  • Ajax

功能逻辑图

注册

  • 用户注册成功,将用户信息存入 MySQL,但此时该用户状态为未激活

  • 向用户发送激活邮件,用户点击链接则激活账号(Spring Mail)

图片

登录 | 登出

登录认证模块跳过了 Spring Secuity 自带的认证机制。主要逻辑如下:

  • 进入登录界面,随机生成一个字符串来标识这个将要登录的用户,将这个字符串短暂的存入 Cookie(60 秒);

  • 动态生成验证码,并将验证码及标识该用户的字符串短暂存入 Redis(60 秒);

  • 为登录成功(验证用户名、密码、验证码)的用户随机生成登录凭证且设置状态为有效,并将登录凭证及其状态等信息永久存入 Redis,再在 Cookie 中存一份登录凭证;

  • 使用拦截器在所有的请求执行之前,从 Cookie 中获取登录凭证,只要 Redis 中该凭证有效并在有效期内,本次请求就会一直持有该用户信息(使用 ThreadLocal 持有用户信息,保证多台服务器上用户的登录状态同步);

  • 勾选记住我,则延长 Cookie 中登录凭证的有效时间;

  • 用户登出,将凭证状态设为无效,并更新 Redis 中该登录凭证的相关信息。下图是登录模块的功能逻辑图,并没有使用 Spring Security 提供的认证逻辑(我觉得这个模块是最复杂的,这张图其实很多细节还没有画全)

发布帖子(异步请求)

发布帖子(过滤敏感词),将其存入 MySQL

添加评论(事务管理)

发布对帖子的评论(过滤敏感词),将其存入 MySQL

图片

发送私信(异步请求)

图片

点赞(异步请求)

将点赞相关信息存入 Redis 的数据结构 set 中。其中,key 命名为 like:entity:entityType:entityId,value 即点赞用户的 id。比如 key = like:entity:2:246 value = 11 表示用户 11 对实体类型 2 即评论进行了点赞,该评论的 id 是 246

某个用户的获赞数量对应的存储在 Redis 中的 key 是 like:user:userId,value 就是这个用户的获赞数量

图片

搜索

  • 发布事件

  1. 发布帖子时,通过消息队列将帖子异步地提交到 Elasticsearch 服务器

  2. 为帖子增加评论时,通过消息队列将帖子异步地提交到 Elasticsearch 服务器

  • 搜索服务

  1. Elasticsearch 服务器搜索帖子

  2. 从 Elasticsearch 服务器删除帖子(当帖子从数据库中被删除时)

图片

网站数据统计

图片

预览

图片

图片

图片

开源地址:https://gitee.com/veal98/Echo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/801388.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT官方modbus_slave例子嵌入到界面

1.打开QT官方modbus_slave的例子 根据提示略微配置一下编译选项,就可以正常运行。 2.新将一个项目包含这个例子 这个例子非常简单,就是在默认的mainwindow上给个按钮,点击按钮调用这个例子的界面。 3.修改*.pro文件 serialport serialbus …

腾讯解禁 QQ 极速版,且看我收集的最全 QQ 各类版本

因为利益关系,腾讯早就限制QQ极速版的登录了,近日居然解除限制了,面对越来越臃肿的QQ,我给大伙准备了几十个版本的QQ,总有一个适合你。 QQ版本合集 给大伙们收集了QQ版本合集,分别有历史版本、精简版本、内…

第59期|GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区,集成了生成预训练Transformer(GPT)、人工智能生成内容(AIGC)以及大语言模型(LLM)等安全领域应用的知识。在这里,您可以找…

动手学深度学习——3.多层感知机

1.线性模型 线性模型可能出错 例如,线性意味着单调假设: 任何特征的增大都会导致模型输出的增大(如果对应的权重为正), 或者导致模型输出的减小(如果对应的权重为负)。 有时这是有道理的。 例…

【Java--数据结构】队列与栈的相互成就

欢迎关注个人主页:逸狼 创造不易,可以点点赞吗~ 如有错误,欢迎指出~ 目录 用队列实现栈 用栈实现队列 用队列实现栈 oj链接 一个队列是无法实现栈的 入栈push:把数据放到不为空的队列当中。 注意:第一次入栈时&…

手写new

手写new new是什么执行new会发生什么实现new new是什么 new 操作符是可以创建一个用户定义的对象的实例或具有构造函数的内置对象的实例 function Car (make, model, year) {this.make makethis.model modelthis.year year } Car.prototype.running function () {return …

R语言极值分析:GEV与GPD模型与MCMC的海洋观测数据极值模拟可视化研究

全文链接:https://tecdat.cn/?p37007 原文出处:拓端数据部落公众号 在海洋科学领域,极端天气和海洋事件如极端海浪、风暴潮和海啸等,对沿海社区、基础设施及生态环境构成了重大威胁。准确预测和评估这些极端事件的强度和频率&a…

Golang中读写锁的底层实现

目录 Sync.RWMutex 背景与机制 接口简单介绍 sync.RWMutex 数据结构 读锁流程 RLock RUnlock RWMutex.rUnlockSlow 写锁流程 Lock Unlock Sync.RWMutex 背景与机制 从逻辑上,可以把 RWMutex 理解为一把读锁加一把写锁; 写锁具有严格的排他性&…

Qt程序图标更改以及程序打包

Qt程序图标更改以及程序打包 1 windows1.1 cmake1.1.1 修改.exe程序图标1.1.2 修改显示页面左上角图标 1.2 qmake1.2.1 修改.exe程序图标1.2.2 修改显示页面左上角图标 2 程序打包2.1 MinGW2.2 Visual Studio 3 参考链接 1 windows 1.1 cmake 1.1.1 修改.exe程序图标 获得一个…

【Linux】进程控制的详细介绍

前言 在此之前,我们学过进程的概念,进程的状态,进程地址空间等一系列进程相关的问题。本章我们继续学习进程,我们要来学习一下进程的控制,关于进程等待,等问题。 目录 1.再次认识Fork函数1.1 fork()之后操…

搜集日志。

logstash 负责: 接收数据 input — 解析过滤并转换数据 filter(此插件可选) — 输出数据 output input — decode — filter — encode — output elasticsearch 查询和保存数据 Elasticsearch 去中心化集群 Data node 消耗大量 CPU、内存和 I/O 资源 分担一部分…

数据结构进阶:使用链表实现栈和队列详解与示例(C, C#, C++)

文章目录 1、 栈与队列简介栈(Stack)队列(Queue) 2、使用链表实现栈C语言实现C#语言实现C语言实现 3、使用链表实现队列C语言实现C#语言实现C语言实现 4、链表实现栈和队列的性能分析时间复杂度空间复杂度性能特点与其他实现的比较…

启动yarn后,其他节点没有NodeManager

写在前面: 这个问题虽然折磨了我两天,但是原因特别蠢,可能与各位不一定一样,我是因为ResourceManager的节点的"/etc/hadoop/workers"文件没有配置好(没有配hadoop102和hadoop104),但排…

MySQL日期和时间相关函数

目录 1. 获取当前时间和日期 2. 获取当前日期 3. 获取当前时间 4. 获取单独的年/月/日/时/分/秒 5. 添加时间间隔 date_add ( ) 6. 格式化日期 date_format ( ) 7. 字符串转日期 str_to_date () 8. 第几天 dayofxx 9. 当月最后一天 last_day ( ) 10. 日期差 datedif…

Java中的线程同步

为什么要实现线程同步 线程的同步是为了保证多个线程按照特定的顺序、协调地访问共享资源,避免数据不一致和竞争条件等问题。 线程同步的方式 1.synchronized关键字 (1)同步方法 public synchronized void save(){} 注: syn…

网络编程+文件上传操作的理解

前言: 概述:在网络通信协议下,不同计算机上运行的程序,进行数据传输 比如:通信,视频通话,网游,邮件等 只要是计算机之间通过网络进行数据传输,就有网络编程的存在 (下面单纯是在Java基础中了解了一下网络编程,感觉理…

如何保证数据库和redis的数据一致性

1、简介 在客户端请求数据时,如果能在缓存中命中数据,那就查询缓存,不用在去查询数据库,从而减轻数据库的压力,提高服务器的性能。 2、问题如何保证两者的一致性 先更新数据库在删除缓存 难点:如何保证…

Classifier-Free Guidance (CFG) Scale in Stable Diffusion

1.Classifier-Free Guidance Scale in Stable Diffusion 笔记来源: 1.How does Stable Diffusion work? 2.Classifier-Free Diffusion Guidance 3.Guide to Stable Diffusion CFG scale (guidance scale) parameter 1.1 Classifier Guidance Scale 分类器引导是…

vite配置环境变量和使用,配置正确后import.meta.env.VITE_APP_BASE_URL编译报错的解决方法

一、配置: 1.新增四个环境文件 .env.development .env.test .env.production .env.pre 内容为不同环境的不同参数变量必须以VITE_APP开头,如: #接口地址 VITE_APP_BASE_URL"¥¥¥¥&#xff…

嵌入式人工智能(6-树莓派4B按键输入控制LED)

1、按键 按键的原理都是一样,通过按键开关的按下导通,抬起断开的情况,GPIO引脚来检测其是否有电流流入。GPIO有input()方法,对于GPIO引脚检测电流,不能让其引脚悬空,否则引脚会受周边环境电磁干扰产生微弱…