秒杀项目之细节随笔记录————
秒杀项目具有很多的重要知识点,本片博客记录在解决秒杀项目中产生的各种问题时,遇到的一些小知识点和问题以及解决方案。
一、ssm框架中一些注解
1.@Component
根据项目中的使用和网上的一些贴子,我个人总结以下内容
@Component,就是把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>
如果在项目中遇到需要把一个类实例化注入到spring容器中,但是此类不在一些扫描的包下,比如controller、service,就可以加上次注解,进行注入
此处是秒杀项目中,通过消息中间件获取消息的类GetMessageUtils,它不在被扫描的包下,加上此注解,就可注入spring容器中
2.@ControllerAdvice
次注解作用的类是全局捕获异常类,只要作用在@RequestMapping上,所有的异常都会被捕获
项目中使用了异常捕获返回json给前端的方法,后台报异常,同时返回给前端,本项目中使用了自定义异常,包含各种失败信息,而使用次注解就能捕获所有异常类
二、html页面中获取请求参数的方法
可以获取当前url中的参数,通过名称即可获取
function GetQueryString(name){
var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);//search,查询?后面的参数,并匹配正则
if(r!=null)return unescape(r[2]); return null;
}
项目使用前后端分离,页面在跳转时带有参数,就可以使用该方法,在获取是调用该方法,直接通过名称课可以获取
三、倒计时插件countdown的使用
秒杀项目中会用到倒计时插件,在这里记录一下我使用的倒计时插件以及使用
引入js: <script src="http://cdn.bootcss.com/jquery.countdown/2.1.0/jquery.countdown.min.js"></script>
代码中使用:
seckillBox.countdown(beginTime, function (event) { -----------此处beginTime为活动开始时间,从后台获取服务器时间
//时间格式
var format = event.strftime('秒杀倒计时: %D天 %H时 %M分 %S秒 '); ---------------此处初始化倒计时时间格式
seckillBox.html(format); ------------------此处为把此时间格式添加到页面中
}).on('finish.countdown', function () { -------------------此处为倒计时插件的倒计时结束后执行方法 ,倒计时结束执行此方法
seckillStart(itemPromo.id,itemPromo.itemId,token,username); -----------此处为倒计时结束后执行的方法,可自己根据业务需求编写方法
});
四、获取商品详情使用guava cache作为一级缓存,redis作为二级缓存
在获取商品详情页面中,由于用户数量多,刷新页面频繁,导致访问量大,我们采取redis作为缓存,但是即使如此,访问量也是很大,所以采用guava cache作为一级缓存,缓存到本地,用户访问详情页面,先从本地获取,如果没有,在从redis缓存中获取,如果还没有,则访问数据库,点击此链接获取guava具体使用方法:https://www.cnblogs.com/blogofbin/p/11703685.html
具体代码:(该方法在service层中实现)
public ItemPromoDetail getItemById(int itemId) {
ItemPromoDetail promo = null;
//因为活动未开始时,用户会一直刷新详情页,所以加一个缓存
//Guava Cache 做一级缓存,用redis做二级缓存
//商品详情和库存分别存放
Object obj = localCacheService.getFromCommonCache("ITEMID:" + itemId);
if (obj == null) {
//从redis中获取
if (jedisClient.exists("ITEMID:"+ itemId )){
String jsonObj = jedisClient.get("ITEMID:"+itemId);
promo = JsonUtils.jsonToPojo(jsonObj, ItemPromoDetail.class);
}else {
promo = promoMapper.getItemById(itemId);
//将库存也存放如redis中
int stockNum = promo.getStock();
jedisClient.set("ITEM_STOCK:"+itemId,stockNum+"");
//获取商品时,根据库存可以设置大闸的数量
jedisClient.set("ITEM_DAZHA:"+itemId,(stockNum*5)+"");
String json = JsonUtils.objectToJson(promo);
jedisClient.set("ITEMID:"+itemId, json);
localCacheService.setCommonCache("ITEMID:"+itemId,promo);
}
}else {
promo = (ItemPromoDetail) obj;
}
promo.setStock(Integer.valueOf(jedisClient.get("ITEM_STOCK:"+itemId)));
return promo;
}