内容介绍
本文介绍了使用Trea如何进行项目创建
技术点介绍
课程内容介绍
学习目标
设计一个秒杀系统
秒杀,对我们来说,都不是一个陌生的东西。每年的双11,618以及时下流行的直播等等。秒杀然而,这
对于我们系统而言是一个巨大的考验。
那么,如何才能更好地理解秒杀系统呢?我觉得作为一个程序员,你首先需要从高维度出发,从整体上
思考问题。在我看来,秒杀其实主要解决两个问题,一个是并发读,一个是并发写。并发读的核心优化
理念是尽量减少用户到服务端来“读”数据,或者让他们读更少的数据;并发写的处理原则也一样,它要
求我们在数据库层面独立出来一个库,做特殊的处理。另外,我们还要针对秒杀系统做一些保护,针对
意料之外的情况设计兜底方案,以防止最坏的情况发生。
其实,秒杀的整体架构可以概括为“稳、准、快”几个关键字。
所谓“稳”,就是整个系统架构要满足高可用,流量符合预期时肯定要稳定,就是超出预期时也同样不能
掉链子,你要保证秒杀活动顺利完成,即秒杀商品顺利地卖出去,这个是最基本的前提。
然后就是“准”,就是秒杀 10 台 iPhone,那就只能成交 10 台,多一台少一台都不行。一旦库存不对,
那平台就要承担损失,所以“准”就是要求保证数据的一致性。
最后再看“快”,“快”其实很好理解,它就是说系统的性能要足够高,否则你怎么支撑这么大的流量呢?
不光是服务端要做极致的性能优化,而且在整个请求链路上都要做协同的优化,每个地方快一点,整个
系统就完美了。
所以从技术角度上看“稳、准、快”,就对应了我们架构上的高可用、一致性和高性能的要求
- 高性能。秒杀涉及大量的并发读和并发写,因此支持高并发访问这点非常关键。对应的方案比如
动静分离方案、热点的发现与隔离、请求的削峰与分层过滤、服务端的极致优化
- 一致性。秒杀中商品减库存的实现方式同样关键。可想而知,有限数量的商品在同一时刻被很多倍的请求同时来减库存,减库存又分为“拍下减库存”“付款减库存”以及预扣等几种,在大并发更新的过程中都要保证数据的准确性,其难度可想而知
- 高可用。现实中总难免出现一些我们考虑不到的情况,所以要保证系统的高可用和正确性,我们还要设计一个 PlanB 来兜底,以便在最坏情况发生时仍然能够从容应对。
项目搭建
Trea创建项目
创建controller层,在此层下创建DemoController,增加一个hello接口。
端口被占用的情况,使用Trae CN创建springboot3 项目后修改端口
AI使用测试
根据mysql的数据库链接,在mytest数据库中创建一张 tuser的数据表
将以上直接执行在工程里
maven创建项目
工程目录
<dependencies>
<!-- web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mysql 依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- MyBatis-Plus 依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
创建 DemoController 测试
package com.yxl.seckill.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/demo")
public class DemoController
{
@GetMapping("/hello")
public String hello()
{
return "hello";
}
}
学生可以尝试创建:使用不同的注解进行方法创建,并进行访问。
@PostMapping:专门用于映射POST请求
@PutMapping:专门用于映射PUT请求
@DeleteMapping:专门用于映射DELETE请求
@PatchMapping:专门用于映射PATCH请求
RestFul风格接口
Contorller与RestController的区别:
由于配置了mysql 的依赖 需要进行数据配置
报错信息:
编写通用返回类
package com.yxl.seckill.vo;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
@ToString
@Getter
@AllArgsConstructor
public enum ResponseCode
{
//通用状态码
SUCCESS(200,"success"),
ERROR(500,"服务端异常"),
//登录模块5002xx
SESSION_ERROR(500210,"session不存在或者已经失效"),
LOGINVO_ERROR(500211,"用户名或者密码错误"),
MOBILE_ERROR(500212,"手机号码格式错误"),
REPEATE_ERROR(400212,"重复下订单"),
EMPTY_STOCK(400210,"库存不足");
private final Integer code;
private final String message;
}
package com.yxl.seckill.vo;
import lombok.Data;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CommonResult<T>
{
private Integer code;
private String message;
private T data;
// 成功但不返回数据的方法
public static <T> CommonResult<T> success() {
return success(null);
}
// 成功并返回数据的方法
public static <T> CommonResult<T> success(T data) {
CommonResult<T> result = new CommonResult<>();
result.setCode(ResponseCode.SUCCESS.getCode());
result.setMessage(ResponseCode.SUCCESS.getMessage());
result.setData(data);
return result;
}
// 错误响应的方法
public static <T> CommonResult<T> error(ResponseCode responseCode) {
CommonResult<T> result = new CommonResult<>();
result.setCode(responseCode.ERROR.getCode());
result.setMessage(responseCode.ERROR.getMessage());
return result;
}
// 通用错误响应方法
public static <T> CommonResult<T> error() {
return error(ResponseCode.ERROR);
}
}
关于提示CommonResult 需要实例化的,是lombok版本的问题,使用一下版本。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>true</scope>
</dependency>
[[1.1 Controller中不同的请求方式与返回请求体]]