zgwyfz 2020-02-22
利用服务端缓存技术,将页面和对象缓存在redis中,可以减少时间浪费,内存开销。但在每次请求的过程中,仍然会有大量静态资源的请求和返回。
使用静态页面技术,页面不必要使用页面交互技术,比如thymeleaf,jsp等。而是写一个纯的html静态页面,然后在页面端通过js的ajax请求,获得数据,并通过配置,将静态页面直接缓存到客户端,等下次请求的时候,如果页面没有发生变化,则可以不用对静态资源进行提交和返回。
当进入商品列表页面时,详情的点击不在通过controller类来将缓存的html返回,而是直接跳转到商品详情的页面,并给一个商品id的参数
<td><a th:href="‘/goods_detail.htm?goodsId=‘+${goods.id}">详情</a></td><!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>
<div class="panel-body">
<span id="userTip"> 您还没有登录,请登陆后再操作<br/></span>
<span>没有收货地址的提示。。。</span>
</div>
<table class="table" id="goodslist">
<tr>
<td>商品名称</td>
<td colspan="3" id="goodsName"></td>
</tr>
<tr>
<td>商品图片</td>
<td colspan="3"><img id="goodsImg" width="200" height="200" /></td>
</tr>
<tr>
<td>秒杀开始时间</td>
<td id="startTime"></td>
<td >
<input type="hidden" id="remainSeconds" />
<span id="miaoshaTip"></span>
</td>
<td>
<!--
<form id="miaoshaForm" method="post" action="/miaosha/do_miaosha">
<button class="btn btn-primary btn-block" type="submit" id="buyButton">立即秒杀</button>
<input type="hidden" name="goodsId" id="goodsId" />
</form>-->
<button class="btn btn-primary btn-block" type="button" id="buyButton"onclick="doMiaosha()">立即秒杀</button>
<input type="hidden" name="goodsId" id="goodsId" />
</td>
</tr>
<tr>
<td>商品原价</td>
<td colspan="3" id="goodsPrice"></td>
</tr>
<tr>
<td>秒杀价</td>
<td colspan="3" id="miaoshaPrice"></td>
</tr>
<tr>
<td>库存数量</td>
<td colspan="3" id="stockCount"></td>
</tr>
</table>
</div>
</body>
</html>删去所有与thymeleaf相关的标签,将需要展示变量的地方,设置id属性
然后提供一个入口函数
$(function () {
getDetail();
});
function getDetail() {
//获取goodsId
var goodsId=g_getQueryString("goodsId");
//设置ajax请求,得到数据
$.ajax({
url:"/goods/detail/"+goodsId,
type:"GET",
success:function (data) {
if(data.code==0){
//展示数据
}else{
//展示错误信息
layer.msg(data.msg);
}
},
error:function () {
//未请求成功信息
layer.msg("客户端请求有误")
}
});
}修改controller类,向页面发送所需要的数据
@RequestMapping(value = "/to_detail/{goodsId}")
@ResponseBody
public Result<GoodsDetailVo> detail( MiaoshaUser user,
@PathVariable("goodsId") long goodsId){
//得到商品信息
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
//得到秒杀的开始时间、结束时间、以及当前时间
long startAt = goods.getStartDate().getTime();
long endAt = goods.getEndDate().getTime();
long now = System.currentTimeMillis();
//设置剩余时间
int remainSeconds=0;
//设置秒杀状态
int miaoshaStatus=0;
//判断
if(now<startAt){
//秒杀还没开始
miaoshaStatus=0;
remainSeconds= (int) ((startAt-now)/1000);
}else if(now>endAt){
//秒杀已经结束
miaoshaStatus=2;
remainSeconds=-1;
}else {
//秒杀正在进行
miaoshaStatus=1;
remainSeconds=0;
}
//创建商品详情的类
GoodsDetailVo vo=new GoodsDetailVo();
vo.setGoods(goods);
vo.setRemainSeconds(remainSeconds);
vo.setUser(user);
vo.setMiaoshaStatus(miaoshaStatus);
//返回页面需要的信息
return Result.success(vo);
}当入口函数得到数据之后,就可以编写展示数据的js代码,一般这些代码是使用前端框架进行编写的。
function render(detail) {
//取到vo传过来的四个属性
var miaoshaStatus = detail.miaoshaStatus;
var remainSeconds = detail.remainSeconds;
var goods = detail.goods;
var user = detail.user;
//逻辑判断
//如果用户存在,则隐藏需要登录的提醒
if(user){
$("#userTip").hide();
}
//展示数据
$("#goodsName").text(goods.goodsName);
$("#goodsImg").attr("src", goods.goodsImg);
$("#startTime").text(new Date(goods.startDate).format("yyyy-MM-dd hh:mm:ss"));
$("#remainSeconds").val(remainSeconds);
$("#goodsId").val(goods.id);
$("#goodsPrice").text(goods.goodsPrice);
$("#miaoshaPrice").text(goods.miaoshaPrice);
$("#stockCount").text(goods.stockCount);
//引入倒计时
countDown();
}
function countDown() {
//获取剩余时间
var remainSeconds = $("#remainSeconds").val();
//定义超时变量
var timeout;
if(remainSeconds>0){
//秒杀还没有开始
//隐藏秒杀的按钮,展示倒计时提醒
$("#buyButton").attr("disabled", true);
$("#miaoshaTip").html("秒杀倒计时:"+remainSeconds+"秒");
//利用setTimeout进行时间控制
timeout=setTimeout(function () {
//剩余秒数减一
$("#countDown").text(remainSeconds - 1);
$("#remainSeconds").val(remainSeconds - 1);
countDown();//递归执行。
},1000)//里面函数每执行一次,就延时一秒。
}else if(remainSeconds==0){
//秒杀正在进行
//显示秒杀按钮
$("#buyButton").attr("disabled", false);
//清理设计的超时函数
if(timeout){
clearTimeout(timeout);
}
$("#miaoshaTip").html("秒杀进行中");
}else {
//秒杀已经结束
$("#buyButton").attr("disabled", true);
$("#miaoshaTip").html("秒杀已经结束");
}
}以上就将详情页静态化了
点击立即秒杀按钮,将执行doMiaosha()的js代码,又是一个ajax请求,但这次不是跳转到静态页面,而是通过Controller类来做一定的秒杀逻辑,然后返回值,如果秒杀成功,则跳转到静态页面。而静态页面也将静态化。
function doMiaosha() {
$.ajax({
url:"/miaosha/do_miaosha",
type:"POST",
data:{
goodsId:$("#goodsId").val(),
},
success:function(data){
if(data.code == 0){
window.location.href="/order_detail.htm?orderId="+data.data.id;
}else{
layer.msg(data.msg);
}
},
error:function(){
layer.msg("客户端请求有误");
}
});
}修改controller类的"/miaosha/do_miaosha"请求,将直接返回页面,到现在将结果返回来判断是否跳转到另一个静态页面。
@RequestMapping(value = "/do_miaosha",method = RequestMethod.POST)
@ResponseBody
public Result<OrderInfo> list(Model model, MiaoshaUser user,
@RequestParam("goodsId") long goodsId){
model.addAttribute("user",user);
if(user==null){
//如果没有获取到user值,报异常
return Result.error(CodeMsg.SESSION_ERROR);
}
//判断库存
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
Integer stock= goods.getStockCount();
if(stock<=0){
model.addAttribute("errmsg", CodeMsg.MIAO_SHA_OVER.getMsg());
return Result.error(CodeMsg.MIAO_SHA_OVER);
}
//判断是否已经秒杀到了
MiaoshaOrder order=orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
if(order!=null){
return Result.error(CodeMsg.REPEATE_MIAOSHA);
}
//进行秒杀逻辑
//减库存,下订单,写入秒杀订单
OrderInfo orderInfo=miaoshaService.miaosha(user, goods);
return Result.success(orderInfo);
}当秒杀成功,将返回一个订单信息的类,然后将订单id拿到作为参数跳转到订单页面
当然,订单页面也将是一个纯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">玉皇大帝</td>
</tr>
<tr>
<td>收货地址</td>
<td colspan="2">天宫一号</td>
</tr>
</table>
</div>
</body>入口函数,请求数据的逻辑
//入口函数
$(function () {
getOrderDetail();
})
function getOrderDetail() {
//一个ajax请求
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("客户端请求有误");
}
});
}控制器代码
@Controller
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderService orderService;
@Autowired
private GoodsService goodsService;
@RequestMapping("/detail")
@ResponseBody
public Result<OrderDetailVo> info(Model model, MiaoshaUser user,
@RequestParam("orderId") long orderId){
//判断用户是否存在
if(user==null){
return Result.error(CodeMsg.SESSION_ERROR);
}
//获取order
OrderInfo order = orderService.getOrderById(orderId);
if(order==null){
Result.error(CodeMsg.ORDER_NOT_EXIST);
}
//得到订单页面需要的参数
long goodsId = order.getGoodsId();
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
OrderDetailVo vo = new OrderDetailVo();
vo.setOrder(order);
vo.setGoods(goods);
return Result.success(vo);
}
}订单页面内js的数据展示代码
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 = "待发货";
$("payButton").hide();
}
$("#orderStatus").text(status);
}到此,页面的静态化就完成了