Java 项目
1. 坦克大战 (停止维护)
- Repo:
2. 多用户通信系统 (暂停维护)
- Repos:
3. 从 0 实现 Tomcat (暂停维护)
- Repo: 
- Notes: - 已完结 - (详情见 JavaWeb 相关部分) 
 
4. 家居网购 (暂停维护)
- Assets: 
- Repo: 
- Notes: 
技术栈:
- 原生 Servlet / 过滤器,WEB-Service-DAO-Entity
软件项目开发流程
- 需求分析阶段 
- 设计阶段 
 
- 开发阶段
 
- 测试阶段
 
- 实施阶段
 
- 维护阶段
 
- 项目设计 - 后端三层架构 
- 项目分包方案 
- MVC - MVC 全称:Model、View、Controller
- 最早出现在 JavaEE 三层中的 Web 层,可有效指导 Web 层的代码分离,单独工作(解耦)
- View 视图:负责数据和界面显示,不接受任何与数据无关的代码
- Controller 控制器:负责接收请求,调用业务层的代码处理请求,然后派发页面(调度者)
- Model 模型:将与业务逻辑相关的数据封装为具体的 JavaBean 类,其中不掺杂与数据处理相关的代码
 
 
代码归档(Version of Git’s message)
- 开发环境搭建(1.x) 
- 会员注册前端校验与后端表设计(2.x) 
- 会员注册后端服务(3.x) 
- 会员登录(4.x) 
- 登录错误提示,表单回显用户名(5.x) 
- Servlet 瘦身优化(6.x) 
- 后台管理 - 家居显示(7.x) 
- 后台管理 - 家居添加(8.x) - 中文乱码问题解决:要在 BasicServlet(父类)中设置 req 编码
- 表单重复提交问题解决:设置重定向(重定向本质为两次请求)
- 后端数据校验:捕获异常并返回信息
 
- 后台管理 - 家居删除(9.x) 
- 后台管理 - 家居修改(10.x) 
- 后台分页 - 家居分页显示(11.x) - 数据模型:高频变化的数据封装为 Bean(如导航条数据)
 
- 首页分页(12.x) 
- 首页搜索(13.x) 
- 会员显示登录名(14.x) 
- 注销登录(15.x) 
- 注册验证码(16.x) 
- 添加家居到购物车(17.x) 
- 购物车的显示、修改、清空等界面前后端交互(18.x) 
- 添加购物车操作库存校验(19.x) 
- 过滤器权限验证(20.x) 
- 事务管理(21.x) - ThreadLocal 统一管理数据库连接
 
- 统一错误页面(22.x) 
- AJAX 重构(23.x) 
- 家居图片更新功能(24.x) 
- 项目完结 
5. 黑马点评(Redis 笔记)
短信登录(Session to Redis)
- Session 不方便进行多台 Tomcat 横向部署
- 拦截器内取 token 不能使排除页面获取 token
缓存(Cache)
- 缓存更新 - 更新策略 - 内存回收,自动更新(低一致 性需求)
- 设置超时,定时更新(低一致性 需求)
- 编码,主动更新(高一致性 需求)
 
- 缓存一致性问题 - 先删缓存,再更新数据库
- 先更新数据库,再写缓存(✅缓存更新速度快,相对影响小)
 
 
- 缓存穿透 - 指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库 - 缓存空对象 - 优:实现简单,维护方便 
- 缺: - 额外内存消耗
- 可能造成短期数据不一致
 
 
- 布隆过滤(用数据索引布尔值来做存在判断) - 优:内存占用少,无多余 key
- 缺:- 实现复杂
- 存在误判可能
 
 
 
- 缓存雪崩 - 指同一时段大量缓存 key 同时失效或 Redis 服务宕机,导致大量请求到达数据库,带来巨大压力 - 给不同的 key 的 TTL 添加随机值
- 利用 Redis 集群提高服务可用性
- 给缓存业务添加降级限流策略(如提前返回、拒绝服务)
- 给业务添加多级缓存(如 Nginx 缓存、JVM 本地缓存)
 
- 缓存击穿 - 查询过程较慢导致大量请求打到数据库 - 互斥锁 - 优:- 无额外内存消耗
- 保证一致性
- 实现简单
 
- 缺:- 线程需要等待,性能受影响
- 可能有死锁风险
 
 
- 优:
- 逻辑过期 - 优:- 线程无需等待,性能较好
 
- 缺:- 不保证一致性
- 有额外内存消耗
- 实现复杂
 
 
- 优:
 
- 缓存工具封装 
优惠券秒杀(Redisson)
- 全局唯一 ID 
- 实现优惠券下单 
- 超卖问题(JMeter 实测) - 加锁 - 乐观锁 - 不加锁,在更新时判断是否有其它线程在修改 - 版本号法 - 在表中加一个版本号字段,用于判断 
- CAS 法(比较和替换) - 库存与版本号同时变化,那么库存同时具有与版本号相同的功能 - 优:性能好 
- 缺:存在成功率低的问题 - 可分批加锁 或 低要求加锁 
 
 
- 悲观锁 - 添加同步锁,让线程串行执行 - 优:简单粗暴
- 缺:性能一般
 
 
 
- 一人一单 - 判断同人同单的订单是否存在 - 因为是插入操作而不是更新,所以采用悲观锁 - 快捷键:Ctrl + Alt + M -> 封装所选代码段为私有方法 - 加锁位置 - 对用户加锁而不是操作 - 要对同一用户加锁,故将锁加在 userId 字段上,注意以值判断是否等价(getId() 返回的是新对象,toString() 方法返回的也是新对象) 
 
- 释放锁后事务可能未提交 - 要对封装方法加锁 
 
- 非代理对象事务失效 - return 处调用的函数的对象为 this,还未被 Spring 代理,会造成事务失效 - 取得代理对象后用代理调用方法 - 使用代理对象需要的配置 - 引入依赖 org.aspectj 
- 暴露代理对象 
 
 
- 集群并发安全(⬇️分布式锁⬇️) 
 
- 分布式锁 - 满足分布式系统或集群模式下 多进程可见 并且 互斥 的锁 - 实现方案 
- 两个基本方法 - 自动拆箱注意空指针问题 
- 锁误删 - 问题剖析:释放锁时应确认锁是否属于自己(线程锁标识可用 UUID 表示) 
- 判断与释放的原子性问题(Lua 脚本) - Redis 提供了 Lua 脚本功能,在一个脚本中编写多条 Redis 命令,确保多条命令执行时的原子性 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- private static final DefaultRedisScript<Long> UNLOCK_SCRIPT; 
 static {
 UNLOCK_SCRIPT = new DefaultRedisScript<>();
 UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
 UNLOCK_SCRIPT.setResultType(Long.class);
 }
 public void unlock() {
 stringRedisTemplate.execute(
 UNLOCK_SCRIPT,
 Collections.singletonList(KEY_PREFIX + lockName),
 ID_PREFIX + Thread.currentThread().getId()
 );
 }
- Redisson - 基于 setnx 实现的分布式锁存在问题 - Redisson:在 Redis 基础上实现的 Java 驻内存数据网络(In-Memory Data Grid)。它不仅提供了一系列的分布式 Java 常用对象,还提供了许多分布式服务,其中就包含了各种分布式锁的实现 
 
6. 扎堆网(PileUp) - (伙伴匹配系统)
- Repos:
- Notes:
需求分析
- 用户添加标签,标签分类
- 搜索、标签搜索- Redis 缓存
 
- 组队
- 允许用户修改标签
- 推荐- 相似度计算算法 + 本地分布式计算
 
技术栈
前端
- Vue3(提高页面开发效率)
- Vant UI (基于 Vue 的移动端组件库)(React 版 Zent)
- Vite(打包工具)
- Nginx 单机部署
后端
- Java + SpringBoot
- SpringMVC + MyBatis + MyBatis Plus
- MySQL 数据库
- Redis 缓存
- Swagger + Knife4j 接口文档
代码归档
- 前端项目初始化(1.x) 
- 前端主页 + 组件概览(2.x) - 设计- tabbar- 首页(推荐 + 广告)- 推荐信息流(含广告)
 
- 发现页(搜索/热搜)
- 消息(邮件)
- 用户页(我)
 
- 首页(推荐 + 广告)
 
- tabbar
- 开发
 
- 设计
- 数据库表设计 - 标签表 - 性别:男、女
- 方向:Java、C++、Go、前端、网安
- 正在学:Spring
- 目标:考研、春招
- 段位:初级、中级、高级、王者
- 身份:大一、大二、大三、大四、学生、待业、已就业、研一、研二、研三
- 状态:乐观、有点丧、单身、已婚、有对象
- 用户自定义标签
- 字段- id int 主键
- 标签名 varchar 非空(必须唯一,唯一索引)
- 上传标签的用户 userId int(根据 userId 查已上传标签,普通索引)
- 父标签 id parentId int(分类)
- 是否为父标签 isParent tinyint (0 -> 不是父标签 / 1 -> 是父标签)
- 创建时间 createTime datetime
- 更新时间 updateTime datetime
- 是否删除 isDelete tinyint (0/1)
 
 
- 修改用户表(根据需求) - 补充 tags 字段,存 json 字符串 :white_check_mark: - 优:查询方便、不用新建关联表,标签是 用户的固有属性 (除该系统之外还可能用到) - 性能低可用 Redis 
- 缺:用户表多一列 
 
- 加一个关联表,记录用户和标签的关系 - 优:(应用场景:)查询灵活、可正查反查 
- 缺:要多建一个表、多维护一个表 - 企业大项目开发中尽量减少关联查询,很影响扩展性,而且影响查询性能 
 
 
 
- 后端接口开发(3.x) - 用户中心集中提供用户的检索、操作、注册、登录、鉴权 - 根据标签搜索用户
 
- 根据标签搜索用户 - 前端() 
x. 硅谷课程(SpringBoot 后)
含公众号开发、文件上传、点播、直播…
 
 
 
 
 
 
 
 
 

 
 

 
 
 
 
 
 

