本文目录导读:

- 核心案例:《云书城》在线图书商城系统
- 阶段一:基础语法训练(JDK 8+新特性)
- 阶段二:数据库设计实战
- 阶段三:高并发与缓存
- 阶段四:Spring Boot实战
- 阶段五:分布式微服务
- 阶段六:项目冲刺(最后2周)
- 阶段七:面试题库(学员痛点常问)
- 给你的培训建议
我来给你设计一套有含金量、贴近真实工作的Java全栈培训案例,不只是"循环打印星星"那种初级练习,而是贯穿整个培训周期的完整项目。
核心案例:《云书城》在线图书商城系统
这是培训最经典的电商类项目,因为它涵盖了Java开发中90%的核心技术点。
项目技术架构
前端:Vue2 + ElementUI + Axios
后端:SpringBoot + MyBatis-Plus + SpringSecurity + JWT
数据库:MySQL + Redis
中间件:RabbitMQ + ElasticSearch
部署:Docker + Nginx
基础语法训练(JDK 8+新特性)
案例1:图书库存管理API
理解面向对象和集合框架。
/**
* 需求:实现图书库存的增删改查、按价格排序、模糊搜索
* 重点展示:Lambda表达式、Stream流、Optional判空
*/
public class BookInventory {
private static List<Book> books = new ArrayList<>();
// 使用Stream API实现复杂查询
public List<Book> searchBooks(String keyword, BigDecimal minPrice, BigDecimal maxPrice) {
return books.stream()
.filter(b -> b.getTitle().contains(keyword)) // 过滤关键词
.filter(b -> b.getPrice().compareTo(minPrice) >= 0) // 价格下限
.filter(b -> b.getPrice().compareTo(maxPrice) <= 0) // 价格上限
.sorted(Comparator.comparing(Book::getPrice).reversed()) // 按价格降序
.collect(Collectors.toList());
}
// 使用Optional防止空指针
public Optional<Book> findBookById(Long id) {
if (id == null || id <= 0) {
return Optional.empty();
}
return books.stream()
.filter(b -> id.equals(b.getId()))
.findFirst();
}
}
数据库设计实战
案例2:图书订单表结构设计
面试常问:订单状态机的设计
-- 订单主表
CREATE TABLE t_order (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(32) NOT NULL COMMENT '订单编号',
user_id BIGINT NOT NULL COMMENT '用户ID',
total_amount DECIMAL(10,2) NOT NULL COMMENT '订单总金额',
status TINYINT NOT NULL DEFAULT 0 COMMENT '订单状态:0待付款 1已付款 2已发货 3已完成 4已取消 5退款中',
-- 时间字段全部加索引(面试必问)
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_user_id (user_id),
INDEX idx_status (status),
INDEX idx_create_time (create_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';
高并发与缓存
案例3:图书热点数据缓存(重点)
需求:图书详情页QPS 5000+,直接从数据库会死,改造成:Redis缓存 + 本地缓存 +数据库三级架构。
@Service
public class BookDetailService {
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private BookMapper bookMapper;
// 使用Caffeine本地缓存(一级缓存)
private Cache<Long, Book> localCache = Caffeine.newBuilder()
.maximumSize(10000)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
// 缓存穿透解决方案:缓存空值
public Book getBookById(Long id) {
// 1. 查本地缓存
Book book = localCache.getIfPresent(id);
if (book != null) return book;
// 2. 查Redis(加锁防止缓存击穿)
String key = "book:detail:" + id;
String json = redisTemplate.opsForValue().get(key);
if (StringUtils.hasText(json)) {
Book cached = JSON.parseObject(json, Book.class);
localCache.put(id, cached); // 回填本地缓存
return cached;
}
// 3. 查数据库(使用分布式锁)
String lockKey = "lock:book:" + id;
boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", Duration.ofSeconds(3));
if (locked) {
try {
book = bookMapper.selectById(id);
if (book == null) {
// 缓存空值,防止穿透(设置较短过期时间)
redisTemplate.opsForValue()
.set(key, "", Duration.ofSeconds(60));
} else {
redisTemplate.opsForValue()
.set(key, JSON.toJSONString(book),
Duration.ofSeconds(600));
localCache.put(id, book);
}
} finally {
redisTemplate.delete(lockKey); // 释放锁
}
} else {
// 没拿到锁,短暂等待后重查缓存
Thread.sleep(100);
return getBookById(id); // 递归重试
}
return book;
}
// 缓存更新策略:删除缓存而非更新(面试重点)
public void updateBook(Book book) {
bookMapper.updateById(book);
// 直接删除缓存,下次请求时重建
localCache.invalidate(book.getId());
redisTemplate.delete("book:detail:" + book.getId());
}
}
Spring Boot实战
案例4:实现一个完整的下单流程
这涵盖了事务管理、分布式锁、消息队列:
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private StockService stockService;
@Autowired
private RabbitTemplate rabbitTemplate;
@Transactional(rollbackFor = Exception.class)
public Long createOrder(OrderCreateDTO createDTO) {
// 1. 校验用户和图书
BookSnapshot book = bookService.getBookById(createDTO.getBookId());
if (book == null) {
throw new BusinessException("图书不存在");
}
// 2. 预减库存(使用Redis Lua脚本防止超卖)
boolean success = stockService.decrementStock(
createDTO.getBookId(), createDTO.getQuantity());
if (!success) {
throw new BusinessException("库存不足");
}
try {
// 3. 创建订单
Order order = new Order();
order.setOrderNo(generateOrderNo());
order.setUserId(createDTO.getUserId());
order.setBookId(createDTO.getBookId());
order.setQuantity(createDTO.getQuantity());
order.setTotalAmount(book.getPrice().multiply(
BigDecimal.valueOf(createDTO.getQuantity())));
order.setStatus(OrderStatus.PENDING_PAYMENT);
orderMapper.insert(order);
// 4. 发送延迟消息,30分钟后未支付自动取消
rabbitTemplate.convertAndSend(
"order.exchange",
"order.delay",
order.getId(),
message -> {
message.getMessageProperties()
.setDelay(30 * 60 * 1000); // 延迟30分钟
return message;
});
return order.getId();
} catch (Exception e) {
// 5. 失败回滚库存
stockService.incrementStock(
createDTO.getBookId(), createDTO.getQuantity());
throw e;
}
}
private String generateOrderNo() {
// 生成唯一订单号:时间戳 + 用户随机
return "ORD" + System.currentTimeMillis()
+ String.format("%04d", (int)(Math.random()*10000));
}
}
分布式微服务
案例5:基于Spring Cloud Alibaba微服务拆分
把单体拆成这些服务:
| 服务名 | 端口 | 职责 | 关键接口 |
|---|---|---|---|
| cloud-book-gateway | 8080 | API网关、限流熔断 | 统一入口 |
| cloud-book-user | 8081 | 用户登录/注册/JWT | /api/user/** |
| cloud-book-product | 8082 | 图书信息/库存 | /api/book/** |
| cloud-book-order | 8083 | 订单/购物车 | /api/order/** |
| cloud-book-search | 8084 | ES搜索 | /api/search/** |
服务注册发现 + 负载均衡:
@Configuration
public class LoadBalancerConfig {
// 配置Nacos注册中心 + Ribbon负载均衡
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
// 自定义负载均衡策略(权重轮询)
@Bean
public IRule ribbonRule() {
return new WeightedResponseTimeRule();
}
}
项目冲刺(最后2周)
最终答辩版:完整的《云书城》系统
学员需要独立完成这些东西:
功能需求清单:
- 用户模块:登录/注册/JWT刷新token/手机号验证码登录
- 商品模块:图书上传(OSS存储)、商品详情页SKU选择
- 购物车模块:加入购物车 / 删除 / 批量下单
- 订单模块:提交订单(事务)/ 订单列表 / 取消订单
- 支付模块:微信支付模拟 / 支付宝沙箱对接
- 搜索模块:ElasticSearch分词搜索 / 高亮显示 / 筛选
- 后台管理:RBAC权限 / 数据报表(ECharts)/ 用户封禁
技术加分项(拿高薪的关键):
# 按这个标准要求自己 高并发处理: - Redis缓存热点数据(QPS提升10倍) - 使用MQ削峰填谷(下单高峰期) - 库存使用Lua脚本原子操作 代码质量: - 统一异常处理Handler - 全局日志切面AOP - 通一响应体Result<T> - 加密存储密码(BCrypt) 上线部署: - 接入阿里云OSS - Docker Compose一键部署 - 使用Nginx反向代理 - 配置HTTPS证书
面试题库(学员痛点常问)
案例延伸出的核心面试题:
| 问题 | 答案要点 |
|---|---|
| 你怎么解决缓存穿透? | 缓存空对象 + 布隆过滤器 |
| 库存超卖怎么处理? | Redis+Lua原子操作 / 乐观锁version字段 |
| 为什么用MQ延迟队列? | 订单超时自动取消 + 失败重试 |
| 索引失效的场景? | 违反最左前缀 / 隐式类型转换 / like以%开头 |
| 分布式事务怎么办? | Seata (AT模式) / 本地消息表 / MQ最终一致性 |
| JVM调优过吗? | 视情况说CMS→G1、堆内存设置、GC日志分析 |
给你的培训建议
核心教学原则:每个阶段都围绕《云书城》推进,前期读代码、中期改bug、后期开发新功能,这比做5个毫无关联的小项目有效得多。
每周时间分配:
- 60%编码 + 20%理论知识 + 20%每日串讲/技术分享
- 每学一个新技术,都要求嵌入到项目里
- 第一天新知识、第二天应用、第三天扩展,循环递进
最终案例要当成作品集来打磨 —— 代码规范、丰富README、录制演示视频、准备50个面试问答,才能从培训学校顺利入职拿Offer。