javaweb商城秒杀系统--页面级高并发秒杀优化Redis缓存+静态化分离(四)
程序员文章站
2022-06-20 08:46:01
...
因为并发的瓶颈最大就是出现在数据库上,所以我们最有效的方式就是缓存
一、页面缓存
1.取缓存
2.手动渲染模版
3.结果输出
//商品列表
@RequestMapping(value = "/to_list",produces = "text/html")
@ResponseBody
public String toLogin(HttpServletRequest request,HttpServletResponse response
, Model model, MiaoshaUser user ){
//return "goods_list";
//先从缓存中去页面代码
String html=redisService.get(GoodsKey.getGoodsList,"",String.class);
//如果不是空就把取出来的页面直接返回去
if(!StringUtils.isEmpty(html)){
return html;
}
//第一步查询商品列表
List<GoodsVo> goodsVoList=goodsService.getGoodsVoList();
model.addAttribute("goodsList",goodsVoList);
SpringWebContext swc=new SpringWebContext(request,response
,request.getServletContext(),request.getLocale(),model.asMap(),applicationContext);
//手动渲染
html=thymeleafViewResolver.getTemplateEngine().process("goods_list",swc);
if(!StringUtils.isEmpty(html)){
redisService.set(GoodsKey.getGoodsList,"",html);
}
return html;
}
//使用了缓存的详情页
//使用了缓存的详情页
/* @RequestMapping(value = "/to_detail/{goodsId}",produces = "text/html")
@ResponseBody
public String toDetail(HttpServletRequest request,HttpServletResponse response
,Model model, MiaoshaUser user, @PathVariable("goodsId") Long goodsId){
//首先取缓存
String html=redisService.get(GoodsKey.getGoodsList,""+goodsId,String.class);
if(!StringUtils.isEmpty(html)){
return html;
}
//手动渲染
model.addAttribute("user",user);
//得到商品id然后通过id获取商品的详情
GoodsVo goodsVo=goodsService.getGoosVoByGoodsId(goodsId);
model.addAttribute("goods",goodsVo);
//获取一个秒杀开始时间
long startAt=goodsVo.getStartDate().getTime();
//获取一个秒杀结束时间
long endAt=goodsVo.getEndDate().getTime();
//获取当前时间
long now=System.currentTimeMillis();
int miaoshaStatus=0;//设置一个状态
int remainSeconds=0;//还剩多少时间
if(now<startAt){
//秒杀还没有开始
miaoshaStatus=0;
remainSeconds= (int) ((startAt-now)/1000);
}else if(now>endAt){
//秒杀结束
miaoshaStatus=2;
remainSeconds=-1;
}else {
//秒杀进行时
miaoshaStatus=1;
remainSeconds=0;
}
//秒杀时的状态和时间传入到前端页面
model.addAttribute("miaoshaStatus",miaoshaStatus);
model.addAttribute("remainSeconds",remainSeconds);
SpringWebContext swc=new SpringWebContext(request,response
,request.getServletContext(),request.getLocale(),model.asMap(),applicationContext);
//手动渲染
html=thymeleafViewResolver.getTemplateEngine().process("goods_detail",swc);
if(!StringUtils.isEmpty(html)){
redisService.set(GoodsKey.getGoodsDetail,""+goodsId,html);
}
return html;
// return "goods_detail";
}
二、对象缓存
失效:应用程序先从缓存中取数据,没有得到,则从数据库中取,成功后,放到缓存中;
命中:应用程序从缓存中取数据,取得后返回;
更新:先将数据存到数据库中,成功后,再让缓存失效;
对象缓存之后,若有数据更新,一定要更新缓存,否则会出现缓存不一致的情况
三、页面静态化
简单来说,就是使用html进行页面展示,ajax进行前后端交互,流行的框架有Vue、Angular。静态化可以使html代码在客户端缓存,不需要去请求服务器。
<!DOCTYPE HTML>
<html>
<head>
<title>订单详情</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- jquery -->
<script type="text/javascript" src="/js/jquery.min.js"></script>
<!-- bootstrap -->
<link rel="stylesheet" type="text/css" href="/bootstrap/css/bootstrap.min.css" />
<script type="text/javascript" src="/bootstrap/js/bootstrap.min.js"></script>
<!-- jquery-validator -->
<script type="text/javascript" src="/jquery-validation/jquery.validate.min.js"></script>
<script type="text/javascript" src="/jquery-validation/localization/messages_zh.min.js"></script>
<!-- layer -->
<script type="text/javascript" src="/layer/layer.js"></script>
<!-- md5.js -->
<script type="text/javascript" src="/js/md5.min.js"></script>
<!-- common.js -->
<script type="text/javascript" src="/js/common.js"></script>
</head>
<body>
<div class="panel panel-default">
<div class="panel-heading">秒杀订单详情</div>
<table class="table" id="goodslist">
<tr>
<td>商品名称</td>
<td colspan="3" id="goodsName"></td>
</tr>
<tr>
<td>商品图片</td>
<td colspan="2"><img id="goodsImg" width="200" height="200" /></td>
</tr>
<tr>
<td>订单价格</td>
<td colspan="2" id="orderPrice"></td>
</tr>
<tr>
<td>下单时间</td>
<td id="createDate" colspan="2"></td>
</tr>
<tr>
<td>订单状态</td>
<td id="orderStatus">
</td>
<td>
<button class="btn btn-primary btn-block" type="submit" id="payButton">立即支付</button>
</td>
</tr>
<tr>
<td>收货人</td>
<td colspan="2">小张 1735342429</td>
</tr>
<tr>
<td>收货地址</td>
<td colspan="2">杭州市滨江区</td>
</tr>
</table>
</div>
</body>
</html>
<script>
function render(detail){
var goods = detail.goods;
var order = detail.order;
$("#goodsName").text(goods.goodsName);
$("#goodsImg").attr("src", goods.goodsImg);
$("#orderPrice").text(order.goodsPrice);
$("#createDate").text(new Date(order.createDate).format("yyyy-MM-dd hh:mm:ss"));
var status = "";
if(order.status == 0){
status = "未支付"
}else if(order.status == 1){
status = "待发货";
}
$("#orderStatus").text(status);
}
$(function(){
getOrderDetail();
})
function getOrderDetail(){
var orderId = g_getQueryString("orderId");
$.ajax({
url:"/order/detail",
type:"GET",
data:{
orderId:orderId
},
success:function(data){
if(data.code == 0){
render(data.data);
}else{
layer.msg(data.msg);
}
},
error:function(){
layer.msg("客户端请求有误");
}
});
}
///////////////////////////////////
// 获取url参数
function g_getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if(r != null) return unescape(r[2]);
return null;
};
//设定时间格式化函数,使用new Date().format("yyyyMMddhhmmss");
Date.prototype.format = function (format) {
var args = {
"M+": this.getMonth() + 1,
"d+": this.getDate(),
"h+": this.getHours(),
"m+": this.getMinutes(),
"s+": this.getSeconds(),
};
if (/(y+)/.test(format))
format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var i in args) {
var n = args[i];
if (new RegExp("(" + i + ")").test(format))
format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? n : ("00" + n).substr(("" + n).length));
}
return format;
};
///////////////////////////////////
</script>