Java高并发秒杀API之业务分析与DAO层


本文主要是针对慕课网的Java高并发秒杀API之业务分析与DAO层这门课程内容做一些整理,这是实现秒杀系统的第一门课程。

1. 相关技术介绍

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 基于maven创建web骨架项目

在这里插入图片描述

2.1 用命令行创建maven项目

1.创建项目

mvn archetype:generate -DgroupId=org.seckill -DartifactId=seckill -DarchetypeArtifactId=maven-archetype-webapp


[INFO] Generating project in Interactive mode (这里会卡一会儿,因为要联网获取项目模板)
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: remote -> br.com.ingenieux:elasticbeanstalk-service-webapp-archetype (A Maven Archetype Encompassing RestAssured, Jetty, Jackson, Guice and Jersey for Publishing JAX-RS-based Services on AWS' Elastic Beanstalk Service)... (这里会自动列出很多项目模板,每种模板前面会有一个数字序号)
336: remote -> org.apache.maven.archetypes:maven-archetype-quickstart (An archetype which contains a sample Maven project.)...Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 336: (这里根据每个人机器上安装的eclipse插件不同,可能默认的数字不是这个,先不管,直接回车)
Choose org.apache.maven.archetypes:maven-archetype-quickstart version: 
1: 1.0-alpha-12: 1.0-alpha-23: 1.0-alpha-34: 1.0-alpha-45: 1.06: 1.1Choose a number: 6: (直接回车)
Define value for property 'groupId': : cnblogs (可暂时先理解成类似package或namespace的名称,通常我们填写组织机构名称缩写)
Define value for property 'artifactId': : maven-hello-world (组件名称,可暂时理解成项目名称)
Define value for property 'version':  1.0-SNAPSHOT: : (版本号,直接回车,默认1.0-SNAPSHOT)
Define value for property 'package':  cnblogs: : (打包后的jar文件名,相当于.net中项目最后生成的程序集dll名称)
Confirm properties configuration:groupId: cnblogsartifactId: maven-hello-worldversion: 1.0-SNAPSHOTpackage: cnblogs Y: :  (直接回车确认)
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.1
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: cnblogs[INFO] Parameter: packageName, Value: cnblogs
[INFO] Parameter: package, Value: cnblogs[INFO] Parameter: artifactId, Value: maven-hello-world...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS (看到这个,表示项目创建成功!)
[INFO] ------------------------------------------------------------------------...
这里是摘自一篇博主的文章,但是链接忘记保存了,如有侵权请联系我。

2.修改信息

  • 增加servlet依赖
  • 提高servlet版本,由于2.3版本太低,jsp默认的el表达式不工作
    • 打开tomcat下的webapps/examples/WEB-INF目录下的web.xml进行修改
    • 用3.1版本的头替换源项目web.xml文件[外链图片转存失败在这里插入图片描述
  • 新建目录
  • 将pom.xml中junit的依赖变成4.11版本,3.0的版本默认使用编程,4.0的版本支持注解
    • junit依赖是单元测试时所需要的
  • 补全项目依赖
    • 1.日志:slf4j log4j logback common-logging
      • slf4j 是规范/接口
      • 日志实现:log4j,logback,common-logging
      • 使用:slf4j+logback
      • 通过logback实现slf4j规范
        在这里插入图片描述
      1. 数据库相关的依赖
      • 数据库链接驱动
        在这里插入图片描述
      • 数据库链接池:优化数据库操作
        在这里插入图片描述
      1. DAO框架:MyBatis依赖(数据持久化层)
      • 3.1 mybatis自身依赖
        在这里插入图片描述
      • 3.2 mybatis自身实现的spring整合依赖
        在这里插入图片描述
      1. Servlet web相关依赖
      • 4.1 servlet两个js标签库
        在这里插入图片描述
      • 4.2 jackson API
        在这里插入图片描述
      • 4.3 servlet 依赖
        在这里插入图片描述
    • 5.spring依赖
      • 5.1 spring核心依赖,核心api:core、beans(ioc)、context(扩展)
        在这里插入图片描述
      • 5.2 spring DAO层的依赖
        在这里插入图片描述
      • 5.3 spring web相关依赖
        • web工程要通过servlet容器来启动,比如Tomact、jetty,启动时sevlet容器要加载spring ioc和aop来启动spring的工厂,所以需要spring-web的api提供支持
          在这里插入图片描述
      • 5.4 spring test相关依赖 :方便做单元测试
        在这里插入图片描述
3. 秒杀业务分析
3.1 秒杀系统业务流程

在这里插入图片描述

秒杀业务的核心 -> 库存的处理

在这里插入图片描述
在这里插入图片描述

事务机制依然是目前最可靠的落地方案

3.2MySQL实现秒杀难点分析

难点问题–竞争

事务:

  • Start Transaction
  • Update库存数量
  • Insert购买明细
  • Commit

行级锁:
在这里插入图片描述

3.3 实现哪些秒杀功能

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4. DAO层设计与开发
4.1 数据库设计与编码
  1. 在src/main下新建一个sql文件夹,里面新建一个schema.sql文件
  2. 编写sql语句
--数据库初始化脚本
--创建数据库
CREATE DATABASE seckill;

--使用数据库
use seckill;

--创建秒杀库存表
CREATE TABLE seckill(

--主键(自增id),最大的int类型,自增列,注释
`seckill_id` bigint NOT NULL AUTO_INCREMENT COMMENT '商品库存id',

--库存名字
`name` varchar(120) NOT NULL COMMENT '商品名称',

--库存,int最大21
`number` int NOT NULL COMMENT '库存数量',

--库存的开始时间
`start_time` timestamp NOT NULL COMMENT '秒杀开启时间',

--秒杀结束时间,不管库存有没有都要结束
`end_time` timestamp NOT NULL  COMMENT '秒杀结束时间',

--创建时间,DEFAULT CURRENT_TIMESTAMP默认值
`create_time` timestamp NOT NULL DEFAULT 
CURRENT_TIMESTAMP COMMENT '创建时间',

--设计索引
PRIMARY KEY (seckill_id),
key idx_start_time(start_time),
key idx_end_time(end_time),
key idx_create_time(create_time)
)ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 
COMMENT='秒杀库存表';
--只有InnoDB是支持事务的引擎
--此数据库采用自增,所以要给出初始自增id为1000

--初始化数据
insert into  
     seckill(name,number,start_time,end_time)
values 
     ('1000元秒杀iphone6','100','2015-11-01 
00:00:00','2015-11-02 00:00:00'),
     ('500元秒杀ipd','200','2015-11-01 
00:00:00','2015-11-02 00:00:00'),
     ('300元秒杀小米','300','2015-11-01 
00:00:00','2015-11-02 00:00:00'),
     ('200元秒杀红米note','400','2015-11-01 
00:00:00','2015-11-02 00:00:00');     

--秒杀成功明细表
--用户登录认证相关的信息
create table success_killed(
`seckill_id` bigint NOT NULL COMMENT '秒杀商品id',
`user_phone` bigint NOT NULL COMMENT '用户手机号',
`state` tinyint NOT NULL DEFAULT -1 COMMENT '状态标识:-1:无效  0:成功  1:已付款  2:已发货',
`create_time` timestamp NOT NULL COMMENT '创建时间',
PRIMARY KEY(seckill_id,user_phone),/*联合主键*/
key idx_create_time(create_time)

)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='秒杀成功明细表';

     

--连接数据库控制台

--连接本地MySQL数据库,-p 密码为空

mysql -uroot -p



--为什么手写DDL?

--记录每次上线的DDL修改

--上线一个新的版本v1.1

ALTER TABLE seckill

DROP INDEX idx_create_time,

add index idx_c_s(start_time,create_time);

3.登录数据库

  • 下载MySQL
  • https://www.runoob.com/mysql/mysql-install.html
  • 用管理员身份打开cmd
  • 转到安装目录bin
  • 初始化数据库:mysqld --initialize --console
  • 安装数据库:mysqld install
  • 启动服务器:net start mysql
  • 修改密码:SET PASSWORD FOR root@localhost=‘123456’;
  • 登录服务器:mysql -u root -p 密码:1234567
  • 输入schema.sql文件里的命令
4.2 DAO实体和接口编码

通过Table对应到java实体Entity的概念
表对应java实体类
表中的列对应实体的属性

  1. 在main/java中创建两个包为org.seckill.entity和org.seckill.dao分别为实体包和dao层的包
  2. 创建事务:在entity中创建类为Seckill
  3. 定义完变量直接选中右键source->Generate getters and setters生成
  4. 右键source->Generate toString( ) 生成复写方法
  5. 同样的方法创建SuccessKilled类
  6. 在dao下创建Seckill的接口SeckillDao,里面放置三个接口:reduceNumberqueryByIdqueryAll
  7. 在dao下创建SuccessKilled的接口SuccessKilledDao,里面有insertSucessKilled、queryByIdWithSeckill
4.3 基于myBatis实现DAO

MyBatis用来作什么?
在这里插入图片描述

MyBatis特点

  • 参数:需要自己提供(基本类型、对象、实体…)
  • SQL(完全自己完成)
  • 在这里插入图片描述
  • entity/list完成封装

MyBatis怎么用?

  • SQL写在哪?
    • XML提供SQL(推荐使用)
    • 注解提供SQL
  • 如何实现DAO接口?
    • Mapper自动实现DAO接口(推荐使用)
    • API编程方式实现DAO接口
4.4 基于mybatis实现DAO编程
  • 在main/resources下建一个xml文件(mybatis全局映射文件),头文件是mybatis官方文档中入门的配置
  • 在main/resources下建一个mapper目录(放置mybatis的数据库映射)
  • 在main/resources/mapper下创建一个seckilldao的xml文件,头文件为xml配置例子里的头
  • 在main/resources/mapper下创建一个successkilleddao的xml文件
4.5 MyBatis整合Spring

在这里插入图片描述

更少的编码:只写接口,不写实现
在这里插入图片描述
在这里插入图片描述
只需要知道类名就行,实现自动扫描
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.6 mybatis整合Spring编码
  • 在main/resources下建一个spring目录(放置spring相关配置)
  • spring-dao.xml文件:dao相关配置
  • https://docs.spring.io/spring/docs/4.1.7.RELEASE/spring-framework-reference/找到pdf官方文档下载
  • 找到5.2容器相关,复制头文件
    • 配置spring时出现一个问题idea application context not configured for this file,只需要file->project structure->modules->spring将其配置文件加上就好
  • 新建jdbc.properties文件
5.7 单元测试与问题排查
  • 所有测试在test下的java文件夹中
  • 先对seckillDao进行测试,点击接口名称:Ctrl+shift+t --> create new Test,勾选junit4,勾选下面三个方法

运行中出现的一些问题:
https://blog.csdn.net/qq_28289405/article/details/82698856
https://www.cnblogs.com/ampl/p/10454721.html

记录调bug的路程:

  • jdbc.properties文件要放在resources下,否则会报“连接不到数据库”的错误

  • sql版本要和pom文件中的mysql版本一致

  • junit要在4.12以上版本

  • jdbc.properties文件中的语句:

    • jdbc.url =
      jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
  • MySQL jdbc 6.0 版本以上必须配置“serverTimezone”参数 UTC代表的是全球标准时间

  • 多个参数时会报错:Parameter ‘offset’ not found.因为java不保存形参,所以要在定义的方法中将其变成

    • List queryAll(@Param(“offset”) int offset, @Param(“limit”) int limit);
    • 这样能保证通过他找到真正的参数

sqlyog最开始连接时报错:1251
解决方法:https://blog.csdn.net/xxydzyr/article/details/90759013

**Error attempting to get column ‘create_time’ from result set. **

解决方法:在jdbc配置后面添加 zeroDateTimeBehavior=convertToNull,当遇到DATETIME值完全由0组成时将这个值转换为null(convertToNull)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值