1、整体业务分析
1)展示商品所有列表;
2)点击链接进入商品详情页;

public String detail(@PathVariable("seckillId") Long seckillId, Model model) {
if (null == seckillId) {
return "redirect:/seckill/list";
}
Seckill seckill = seckillService.getById(seckillId);
if (null == seckill) {
return "forward:/seckill/list";
}
model.addAttribute("seckill", seckill);//承载最终要返回给用户的数据,返回Seckill类数据
return "detail";//view,在spring-web1里面配置
}
返回一个json(现在大部分开发使用的方法)
@RequestMapping(value = "/{seckillId}/exposer",
method = {RequestMethod.POST,RequestMethod.GET},
produces = {"application/json;charset=utf-8"})
@ResponseBody //最后数据会封装成一个json,返回json数据
public SeckillResult<Exposer> exposer (Long seckillId){
SeckillResult<Exposer> result;
try {
Exposer exposer = seckillService.exportSeckillUrl(seckillId);
result = new SeckillResult<Exposer>(true,exposer);
} catch (Exception e) {
logger.error(e.getMessage(),e);
result = new SeckillResult<Exposer>(false,e.getMessage());
}
return result;
}
cookie访问
@RequestMapping(value = "/{seckillId}/{md5}/execution",
method = {RequestMethod.POST,RequestMethod.GET},
produces = {"application/json;charset=utf-8"})
@ResponseBody
public SeckillResult<SeckillExcution> excute(@PathVariable("seckillId") Long seckillId,
@PathVariable("md5") String md5,
@CookieValue(value = "killPhone" ,required = false) Long phone )
//killPhone会放入cookie中
{
return null
}
4.2.2 Spring MVC的配置
(1)配置DispatcherServlet,文件在WEB-INF/web.xml
1、配置DispatcherServlet
2、配置springMVC需要加载的配置文件spring-*.xml, Mybatis->spring->springMVC
3、默认匹配所有的请求 /
(2)配置Spring MVC
1、开启springMVC注解模式,
1)、自动注册DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter
2)、提供一系列的功能:数字和日期的format @NumberFormat @DateTimeFormat ,XML和JSON的数据支持
2、静态资源默认servlet配置
1)、加入对静态资源的处理: js、gif、png
2)、允许使用"/"作为整体映射
3、配置jsp 显示ViewResolver
4、扫描web相关的bean
4.3 Controller开发
与前端进行交互,返回一个界面或者json给前端,现在公司多都会使用返回json给前端。
一般使用一个统一的数据返回格式,在本项目中采用org.seckill.dto.SeckillResult
4.4 前端设计
使用bootstrap+jquery这里不多赘述
包括jQuery的一些插件:jQuery cookie插件、jQuery countDown倒计时插件
5、高并发
5.1高并发点和高并发分析
(1)高并发主要发生在:查看详情页、获取系统时间(不需要优化)、查看暴露接口、执行秒杀操作。
(2)CDN是一个内容分发网络,用于加速用户获取数据,部署在离用户最近的节点上,不需要去访问互联网服务器,一般针对的是内容不变化的界面,导致获取秒杀接口不可以使用CDN,因为它会随着时间推移而改变,比如获取到接口执行秒杀等等,这种操作就适合用***后端的缓存redis缓存***。
get from cache
if null
get db
put cache
locgoin
(3)
分析:
NoSQL , MQ等运维成本和稳定性不高;
开发成本:数据一致性、回滚方案等需要手动实现;
幂等性难保证:重复秒杀问题;
不适合新手的架构。
(4)为什么不用Mysql解决?
当java控制事务进行事务行为时会有行级锁
1)update减库存:网络延迟问题和GC操作
2)insert购买明细:网络延迟问题和GC操作
3)commit/rollback
优化方向:减少行级锁的持有时间
(5)优化总结
5.2优化思路并实现
5.2.1redis后端缓存优化
redis实现秒杀接口暴露优化:
1)在pom.xml 文件中添加依赖:redis客户端 Jedis,protostuff序列化依赖;
2)创建RedisDao实现redis存取方法,具体实现:org.seckill.dao.cache.RedisDao
3)优化在SeckillService中exportSeckillUrl方法:
//1、访问redis
Seckill seckill = redisDao.getSeckill(seckillId);
if (seckill == null){
//2访问数据库
seckill = seckillDao.queryById(seckillId);
if (null==seckill){
return new Exposer(false,seckillId);
}else{
//放入redis
redisDao.putSeckill(seckill);
}
}
5.2.2 秒杀操作优化
(1)如何判断update更新库存成功:
条件:update自身没报错、客户端确认update影响行数
优化思路:把客户端逻辑放在MySql 服务器端,避免网络延迟和GC
两种解决方案:定制SQL方案,修改SQL源码,update /* + [auto commit] */
***使用存储过程整个操作在Mysql端完成. resources/sql/seckill.sql
(2)mybatis+spring实现存储过程操作
1)在SeckillDao接口中添加一个方法 void killByProcedure(Map<String,Object> paramMap);
2) 在对应的Mapper SeckillDao.xml文件中添加;
<!-- 使用mybatis调用存储过程-->
<select id="killByProcedure" statementType="CALLABLE">
call execute_seckill(
#{seckillId,jdbcType=BIGINT,mode=IN},
#{phone,jdbcType=BIGINT,mode=IN},
#{killTime,jdbcType=TIMESTAMP,mode=IN},
#{result,jdbcType=INTEGER,mode=OUT}
);
</select>
3)实现service层和controller层编码
热门评论
感觉少了好多关键代码。不过还是能看懂。我慕课网看过这期视频