当前位置: 首页 > news >正文

项目篇:Echo论坛系统项目

一、登录注册模块

1、注册功能

1.1、注册流程图

 

1.2、注册代码

/*** 用户注册* @param user* @return Map<String, Object> 返回错误提示消息,如果返回的 map 为空,则说明注册成功*/public Map<String, Object> register(User user) {Map<String, Object> map = new HashMap<>();if (user == null) {throw new IllegalArgumentException("参数不能为空");}if (StringUtils.isBlank(user.getUsername())) {map.put("usernameMsg", "账号不能为空");return map;}if (StringUtils.isBlank(user.getPassword())) {map.put("passwordMsg", "密码不能为空");return map;}if (StringUtils.isBlank(user.getEmail())) {map.put("emailMsg", "邮箱不能为空");return map;}// 验证账号是否已存在User u = userMapper.selectByName(user.getUsername());if (u != null) {map.put("usernameMsg", "该账号已存在");return map;}// 验证邮箱是否已存在u = userMapper.selectByEmail(user.getEmail());if (u != null) {map.put("emailMsg", "该邮箱已被注册");return map;}// 注册用户user.setSalt(CommunityUtil.generateUUID().substring(0, 5)); // saltuser.setPassword(CommunityUtil.md5(user.getPassword() + user.getSalt())); // 加盐加密user.setType(0); // 默认普通用户user.setStatus(0); // 默认未激活user.setActivationCode(CommunityUtil.generateUUID()); // 激活码// 随机头像(用户登录后可以自行修改)user.setHeaderUrl(String.format("http://images.nowcoder.com/head/%dt.png", new Random().nextInt(1000)));user.setCreateTime(new Date()); // 注册时间userMapper.insertUser(user);// 给注册用户发送激活邮件Context context = new Context();context.setVariable("email", user.getEmail());// http://localhost:8080/echo/activation/用户id/激活码String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActivationCode();context.setVariable("url", url);String content = templateEngine.process("/mail/activation", context);mailClient.sendMail(user.getEmail(),"激活 Echo 账号", content);return map;}

2、登录模块

2.1、登录页面

2.2、登录验证码问题

        首先,登录的时候会随机生成验证码,如何把这个验证码和当前用户对应起来,实现验证码的校验呢?

        显然,由于这个时候用户还没有登录,我们是没有办法通过用户的 id 来唯一的对应它的验证码的。所以这个时候我们考虑生成一个随机的 id 来暂时的代替这个用户,将其id和对应的验证码暂时存入 Redis 中(60s)。并且在 Cookie中暂时存一份为这个用户生成的随机 id(60s)。

        其中生成验证码和进行校验分别是两个URL请求地址。

        这样,当用户点击登录按钮后,就会去 Redis中获取这个随机 id和验证码,去Cookie查询对应的验证码,判断用户输入的验证码是否一致。

2.3、登录认证并持有用户状态问题

        用户输入用户名和密码并且校验完验证码之后,就登录成功了,那我们如何在一次请求中去保存这个用户的状态?如何回显用户的信息呢?

做法可以设计一个类如下图:

        解释一下,每个用户登录成功后,我们都会为其生成一个随机的唯一的登录凭证实体类对象 LoginTicket(包含用户 id、登录凭证字符串 ticket、是否有效、过期时间),我们把这个登录凭证实体类对象永久的存储在 Redis 中(key 就是登录凭证字符串 ticket)。而所谓登录凭证的无效,就是指用户登出后,这个凭证就会被设置为无效状态;凭证的默认过期时间是 30分。

        存储完 LoginTicket 后,我们就可以根据它来获取用户的状态了。我们定义了一个拦截器 LoginTicketInterceptor每次请求之前都会从 Redis获取到 ticket,然后根据 ticket 去 Redis 中查看这个用户的登录凭证 LoginTicket 是否过期和是否有效,只有登录凭证有效且没有过期才会执行请求,不然就会跳转到登录界面。

        如果该用户的登录凭证有效且没有过期,那我们就可以在本次请求中持有这个用户的信息了。如何持有呢?这里我们考虑使用 ThreadLocal 保存用户信息,ThreadLocal 在每个线程中都创建了一个用户信息副本,也就是说每个线程都可以访问自己内部的用户信息副本变量,从而实现了线程隔离,来看下 HostHolder 类:

        所以将登录成功后要保存的信息为:

        将生成的凭证保存到Redis上,并且设置过期时间,置state为1,其中key为凭证,value为LoginTicket 类。

       然后每次请求首先经过拦截器,通过Cookie获取ticket凭证。凭借ticket凭证从Redis获取LoginTicket 类的信息。如果存在就将通过LoginTicket 类的用户id查询用户信息其保存到ThreadLocal中,否则拦截。

2.4、退出功能

        从Redis删除凭证信息,执行ThreadLocal的remove()方法清空用户信息,删除Cookie保存的凭证信息。

2.5、性能优化

        因为每次请求需要在拦截器中通过通过Cookie获取凭证,然后去Redis获取LoginTicket 类。如果通过验证则会每次去数据库查询用户信息,这样导致每一次请求访问都会去数据库查询造成巨大的访问压力。

        为了避免这种情况,所以拦截器首先去Redis查询用户信息,如果有则直接保存到ThreadLocal,否则再去数据库查询用户信息,再保存到Redis中。

2.5、流程

  • 用户登录 —> 生成登录凭证作为key存入 Redis,value是凭证类信息,Cookie 中存一份 ticket凭证
  • 每次执行请求之前,拦截器都会通过 Cookie 去 Redis 中查询该用户的登陆凭证是否过期和是否有效。点击记住我可以延长登录凭证的过期时间,用户退出则其登录凭证变为无效状态
  • 根据这个登录凭证对应的用户 id,去数据库中查询这个用户信息
  • 使用 ThreadLocal 在本次请求中一直持有这个用户信息
  • 优化点:每次请求前都需要去数据库查询这个用户信息,访问频率比较高,所以我们考虑把登录成功的用户信息在 Redis 中保存一会,拦截器每次查询前先去 Redis 中查询

 流程图如下图:

二、帖子模块

三、评论模块

四、私信模块

五、点赞模块

六、系统通知模块

相关文章:

项目篇:Echo论坛系统项目

一、登录注册模块 1、注册功能 1.1、注册流程图 1.2、注册代码 /*** 用户注册* param user* return Map<String, Object> 返回错误提示消息&#xff0c;如果返回的 map 为空&#xff0c;则说明注册成功*/public Map<String, Object> register(User user) {Map&l…...

数据可视化(2)

1.柱状图 #柱状图 #bar(x,height,width,*,aligncenter,**kwargs) #height柱子的高度&#xff0c;即y轴上的数据 #width数组的宽度&#xff0c;默认值0.8 #*表示后面的参数为匿名关键字&#xff0c;必须传入参数 #kwargs关键字参数x[1,2,3,4,5] height[random.randint(10,100)f…...

MD-MTSP:斑马优化算法ZOA求解多仓库多旅行商问题MATLAB(可更改数据集,旅行商的数量和起点)

一、斑马优化算法ZOA 斑马优化算法&#xff08;Zebra Optimization Algorithm&#xff0c;ZOA&#xff09;Eva Trojovsk等人于2022年提出&#xff0c;其模拟斑马的觅食和对捕食者攻击的防御行为。斑马优化算法&#xff08;Zebra Optimization Algorithm&#xff0c;ZOA&#x…...

【笔试强训选择题】Day32.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01; 文章目录 前言 一、Da…...

抖音seo账号矩阵系统源码如何开发布局?

目录 一、 抖音SEO账号矩阵系统源码的开发布局步骤如下&#xff1a; 二。 开发部署源码 三、 开发部署功能设计 1. 短视频AI智能创作 2. 托管式账号管理: 3. 数据分析 4. 智能营销获客 四。 抖音seo源码开发部署交付技术文档包含 五。 开发代码展示&#xff1a; 一、 抖…...

vue项目cdn打包优化

0.用vue ui可以查看项目打包后的情况。 1.定义包的排除 let externals {axios: axios,element-ui: ELEMENT,echarts: echarts,} configureWebpack: {externals: externals }2.配置cdn包资源 // 配置 let cdn {css: [// element-ui csshttps://unpkg.com/element-ui/lib/th…...

Android 之 MediaPlayer 播放音频与视频

本节引言&#xff1a; 本节带来的是Android多媒体中的——MediaPlayer&#xff0c;我们可以通过这个API来播放音频和视频 该类是Androd多媒体框架中的一个重要组件&#xff0c;通过该类&#xff0c;我们可以以最小的步骤来获取&#xff0c;解码 和播放音视频。它支持三种不同的…...

React中事件处理器的基本使用

在React中&#xff0c;为了提高性能&#xff0c;跨浏览器兼容性和开发体验&#xff0c;React实现了一套自己的事件机制&#xff0c;利用事件委托和合成事件的方式统一管理事件订阅和分发。 为了让组件能够响应用户的交互行为&#xff0c;React提供了一系列的事件处理器&#xf…...

RobotFramework

一、RobotFramework的简介和特点 1、关键字驱动&#xff1a; 把项目中的业务逻辑封装成一个一个的关键字&#xff0c;然后调用不同的关键字组成不同的业务 2、数据驱动 把测试数据放到excel&#xff1a;yaml文件中 通过改变文件中的数据去驱动测试用例执行 3、特点&#xff…...

【Matplotlib 绘制折线图】

使用 Matplotlib 绘制折线图 在数据可视化中&#xff0c;折线图是一种常见的图表类型&#xff0c;用于展示随着变量的变化&#xff0c;某个指标的趋势或关系。Python 的 Matplotlib 库为我们提供了方便易用的功能来绘制折线图。 绘制折线图 下面的代码展示了如何使用 Matplo…...

ARM汇编基本变量的定义和使用

一、ARM汇编中基本变量是什么? 数字变量: GBLA LCLA SETA 逻辑变量:GBLL LCLL SETL 字符串:GBLS LCLS SETLS 注意需要TAB键定义变量和行首改变值 二、使用步骤 1.引入库 代码如下(示例): GBLA led_num Reset_Handler PROCEXPORT Reset_Handler [WEA…...

排序算法汇总

每日一句&#xff1a;你的日积月累终会成为别人的望尘莫及 目录 常数时间的操作 选择排列 冒泡排列 【异或运算】 面试题&#xff1a; 1&#xff09;在一个整形数组中&#xff0c;已知只有一种数出现了奇数次&#xff0c;其他的所有数都出现了偶数次&#xff0c;怎么找到…...

cocos2d 中UserDefault在windows平台下的路径问题

在使用cocos2dx c开发项目时&#xff0c;通常使用cocos自带的UserDefault来存储一些项目所用到的一些配置信息&#xff1a;如游戏的音量&#xff0c;游戏的闯关数等... 但是windows平台下&#xff0c;测试发现如果用户的帐户名使用是中文&#xff0c;在启动程序时会报错&#…...

ChatGPT与高等教育变革:价值、影响及未来发展

最近一段时间&#xff0c;ChatGPT吸引了社会各界的目光&#xff0c;它可以撰写会议通知、新闻稿、新年贺信&#xff0c;还可以作诗、写文章&#xff0c;甚至可以撰写学术论文。比尔盖茨、马斯克等知名人物纷纷为此发声&#xff0c;谷歌、百度等知名企业纷纷宣布要提供类似产品。…...

Matlab Image Processing toolbox 下载安装方法

当安装好Matlab之后&#xff0c;发现没有Image Processing toolbox这个图像处理工具箱 从新安装一遍&#xff0c; 选上 Image Processing toolbox 但是不用选matlab即可 1.找到之前安装时的Setup安装程序包&#xff0c;按照之前安装Matlab步骤&#xff0c;到选择需要安装的Ma…...

什么是消息键(Key)?如何使用消息键进行消息顺序性保证?

消息键&#xff08;Key&#xff09;是Kafka消息的一个可选属性&#xff0c;用于标识消息的逻辑关联关系。每条消息可以携带一个关键字作为其键&#xff0c;这个键可以是字符串、整数等数据类型。 使用消息键可以在Kafka中实现消息的顺序性保证&#xff0c;具体方式如下&#x…...

慎思笃行,兴业致远:金融行业的数据之道

《中庸》中说&#xff0c;“博学之&#xff0c;审问之&#xff0c;慎思之&#xff0c;明辨之&#xff0c;笃行之”。这段话穿越千年&#xff0c;指引着中国千行百业的发展。对于金融行业来说&#xff0c;庞大的数据量可以说是“博学”的来源。但庞大的数据体量&#xff0c;既是…...

Git-分支管理

文章目录 1.分支管理2.合并冲突3.合并模式4.补充 1.分支管理 Git分支管理是指在Git版本控制系统中&#xff0c;使用分支来管理项目的不同开发线路和并行开发的能力。通过分支&#xff0c;开发者可以在独立的环境中进行功能开发、bug修复等工作&#xff0c;而不会影响到主分支上…...

[Ubuntu 22.04] containerd配置HTTP方式拉取私仓Harbor

文章目录 1. 基础环境配置2. Docker安装3. 部署Harbor&#xff0c;HTTP访问4. 部署ContainerD5. 修改docker配置文件&#xff0c;向harbor中推入镜像6. 配置containerd6.1. 拉取镜像验证6.2. 推送镜像验证 1. 基础环境配置 [Ubuntu 22.04] 安装K8S基础环境准备脚本 2. Docker安…...

入门指南:深入解析OpenCV的copyTo函数及其与rect的应用场景

文章目录 导言copyTo函数的示例copyTo函数与rect的应用场景结论 导言 OpenCV是一个功能强大的开源计算机视觉库&#xff0c;广泛应用于图像处理和计算机视觉任务。在OpenCV中&#xff0c;copyTo函数是一个重要的图像处理函数&#xff0c;它允许我们在不同的图像之间复制像素数…...

Playwright MCP配置决策树:企业级浏览器自动化选型指南

1. 这不是又一篇“选型对比”&#xff0c;而是我在三个真实项目里踩出来的配置决策树你点开这篇&#xff0c;大概率正被一个问题卡住&#xff1a;团队刚决定用 Playwright 做浏览器自动化&#xff0c;但没人能说清——到底该用它自带的 test runner&#xff1f;还是套一层 MCP&…...

Unity序列化三要素:Serializable、SerializeField与SerializeReference详解

1. 为什么Unity序列化总让人困惑——从一个真实报错说起 刚接手一个老项目时&#xff0c;我遇到个特别典型的场景&#xff1a;美术同事在Inspector里调好了角色的装备配置&#xff0c;保存后切到另一台机器打开&#xff0c;所有装备栏全空了。Debug发现&#xff0c; List<E…...

基于PSO的多目标优化匿名化模型MO-OBAM:平衡隐私保护与数据效用的实战指南

1. 项目概述&#xff1a;当数据共享遇上隐私红线&#xff0c;我们如何破局&#xff1f;在数据驱动的时代&#xff0c;无论是医疗研究中的患者电子病历、金融风控中的信用记录&#xff0c;还是商业分析中的用户行为数据&#xff0c;其共享与分析都蕴含着巨大的价值。然而&#x…...

告别打包焦虑:UE5 Windows与安卓打包速度优化与稳定性提升全攻略

告别打包焦虑&#xff1a;UE5 Windows与安卓打包速度优化与稳定性提升全攻略在虚幻引擎5&#xff08;UE5&#xff09;开发流程中&#xff0c;打包环节往往是开发者体验的分水岭——顺畅的打包过程能保持创作心流&#xff0c;而频繁的报错和漫长等待则会严重消耗开发热情。本文将…...

Unity InputField组件避坑指南:从登录框到聊天室,这8个属性配置错了真头疼

Unity InputField组件深度避坑手册&#xff1a;从基础配置到高阶实战在Unity项目开发中&#xff0c;InputField组件看似简单却暗藏玄机。许多开发者都曾遇到过这样的场景&#xff1a;明明按照文档配置了所有属性&#xff0c;运行时却出现虚拟键盘遮挡输入框、密码输入时光标消失…...

西安家谱印刷厂哪家好

你知道吗&#xff1f;我走访了全国20多个宗亲会&#xff0c;发现一个扎心的事实——超过70%的家庭在第一次修谱时&#xff0c;都踩过同样的坑。有位陕西的陈姓宗长&#xff0c;花了整整3年时间收集家族资料&#xff0c;结果找了一家小印刷厂&#xff0c;拿到手的家谱&#xff0…...

CD-GraB算法:协调数据顺序,加速分布式机器学习收敛

1. 分布式机器学习中的收敛瓶颈与数据顺序的隐秘关联在分布式机器学习的世界里&#xff0c;我们每天都在和数据、算力、时间赛跑。当你把训练任务拆分到多个GPU或服务器节点上并行执行时&#xff0c;一个看似不起眼的问题往往会成为性能提升的“暗礁”&#xff1a;数据以什么顺…...

今日算法(组合问题III)(回溯的使用)

题目描述找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a;只使用数字 1 到 9每个数字 最多使用一次返回所有可能的有效组合的列表&#xff0c;列表不能包含相同的组合两次&#xff0c;组合可以以任何顺序返回核心思路&#xff1a;带双重剪枝的回溯…...

2026年AI论文写作工具实测认证:5款神器从文献到降重一站式避坑指南

写论文的焦虑&#xff0c;是每个科研人和学生绕不开的“必修课”。选题无从下手&#xff0c;文献检索耗时费力&#xff0c;格式调整反复修改&#xff0c;查重降重更是让人抓耳挠腮。2026年的AI工具早已不是当年的“辅助软件”&#xff0c;而是升级为能理解学术逻辑、生成高质量…...

面向实时决策Agent的Harness微秒级调度

面向实时决策Agent的Harness微秒级调度:从原理到落地,打造低于10us延迟的智能决策系统 副标题:适配量化交易、自动驾驶、工业控制等高实时性场景,确定性延迟保障99.999%调度成功率 摘要/引言 你有没有遇到过这些场景:量化交易策略的决策逻辑晚了5us,原本可以盈利的订单…...