秒杀系统Web实践——05页面优化(页面缓存+url缓存+对象缓存、页面静态化+前后端分离、静态资源优化、CDN优化)

第五章 页面优化技术

1.页面缓存

1.1页面缓存(商品列表页面)

1.2 URL缓存(商品详情)

1.3 对象缓存

2.页面静态化

2.1前后端分离

2.2浏览器缓存

3.静态资源优化

综述


1.页面缓存

我们在优化之前,接口返回的大多是页面名称,或响应数据,在这里我们对页面进行缓存处理,接口将返回静态页面的代码。

步骤:1 取缓存;2 手动渲染模板;3 输出结果

经过取缓存、手动渲染模板、输出结果三个步骤完善商品列表页、商品详细。

1.1页面缓存(商品列表页面)

    @RequestMapping(value="/to_list", produces="text/html")
    @ResponseBody
    public String list(Model model, MiaoshaUser user, HttpServletRequest request, HttpServletResponse response){
//        System.out.println(user);
        model.addAttribute("user",user);
        //取缓存
        String html = redisService.get(GoodsKey.getGoodsList, "", String.class);
        if(!StringUtils.isEmpty(html)) {
            return html;
        }
        //取数据库
        List goodsList = goodsService.listGoodsVo();
        model.addAttribute("goodsList",goodsList);
        //return "goods_list";

        //手动渲染
        //https://blog.csdn.net/ouzhuangzhuang/article/details/84839266
        IWebContext ctx =new WebContext(request,response, request.getServletContext(),request.getLocale(),model.asMap());
        html = thymeleafViewResolver.getTemplateEngine().process("goods_list", ctx);
        if(!StringUtils.isEmpty(html)) {
            redisService.set(GoodsKey.getGoodsList, "", html);
        }
        return html;
    }


public class GoodsKey extends BasePrefix{
    private GoodsKey(int expireSeconds, String prefix) {
        super(expireSeconds, prefix);
    }
    public static GoodsKey getGoodsList = new GoodsKey(60, "gl");
    public static GoodsKey getGoodsDetail = new GoodsKey(60, "gd");
}

1.2 URL缓存(商品详情)

    @RequestMapping(value="/to_detail2/{goodsId}",produces="text/html")
    @ResponseBody
    public String detai2(HttpServletRequest request, HttpServletResponse response, Model model, MiaoshaUser user,
                         @PathVariable("goodsId")long goodsId){


        model.addAttribute("user",user);


        //取缓存
        String html = redisService.get(GoodsKey.getGoodsDetail, ""+goodsId, String.class);
        if(!StringUtils.isEmpty(html)) {
            return html;
        }

        //手动渲染
        GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
        //System.out.println(goods.toString());
        model.addAttribute("goods",goods);
        
        //
        long startAt = goods.getStartDate().getTime();
        long endAt = goods.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);
        //return "goods_detail";

        //手动渲染
        IWebContext ctx =new WebContext(request,response,
                request.getServletContext(),request.getLocale(),model.asMap());
        html = thymeleafViewResolver.getTemplateEngine().process("goods_detail", ctx);
        if(!StringUtils.isEmpty(html)) {
            redisService.set(GoodsKey.getGoodsDetail, ""+goodsId, html);
        }
        return html;
    }

1.3 对象缓存

使用对象缓存重写MaioshaService里面的getById方法,使得不直接访问数据库,同时也要重写updatePassword方法。

    public MiaoshaUser getById(long id){
        //取缓存
        MiaoshaUser user = redisService.get(MiaoshaUserKey.getById, ""+id, MiaoshaUser.class);
        if(user != null) {
            return user;
        }
        //取数据库
        user = miaoshaUserDao.getById(id);
        //加缓存
        if(user != null) {
            redisService.set(MiaoshaUserKey.getById, ""+id, user);
        }
        return user;
    }

    public boolean updatePassword(String token, long id, String formPass) {
        //取user
        MiaoshaUser user = getById(id);
        if(user == null) {
            throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
        }
        //更新数据库
        MiaoshaUser toBeUpdate = new MiaoshaUser();
        toBeUpdate.setId(id);
        toBeUpdate.setPassword(MD5Util.formPassToDBPass(formPass, user.getSalt()));
        miaoshaUserDao.update(toBeUpdate);
        //处理缓存
        redisService.delete(MiaoshaUserKey.getById, ""+id);
        user.setPassword(toBeUpdate.getPassword());
        redisService.set(MiaoshaUserKey.token, token, user);
        return true;
    }

2.页面静态化

2.1前后端分离

页面优化使用前后端分离,具体的在该项目中在商品列表跳转到商品详情可以体现,在静态页面初始化的时候,调用后端接口,获取商品详情,实现页面静态化

  @RequestMapping(value="/detail/{goodsId}")
    @ResponseBody
    public Result detail(HttpServletRequest request, HttpServletResponse response, Model model, 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 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;
        }
        GoodsDetailVo vo = new GoodsDetailVo();
        vo.setGoods(goods);
        vo.setUser(user);
        vo.setRemainSeconds(remainSeconds);
        vo.setMiaoshaStatus(miaoshaStatus);
        return Result.success(vo);
    }
//列表页
详情



//goods_detail.htm



    商品详情
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    



秒杀商品详情
您还没有登录,请登陆后再操作
没有收货地址的提示。。。
商品名称
商品图片
秒杀开始时间
商品原价
秒杀价
库存数量

2.2浏览器缓存

添加配置

#static
#启用静态资源处理
spring.resources.add-mappings=true
#客户端缓存时间
spring.resources.cache.period=3600
spring.resources.chain.cache=true 
spring.resources.chain.enabled=true
#启用html5的application-cache
spring.resources.chain.html-application-cache=true
spring.resources.static-locations=classpath:/static/

秒杀系统Web实践——05页面优化(页面缓存+url缓存+对象缓存、页面静态化+前后端分离、静态资源优化、CDN优化)_第1张图片

3.静态资源优化

下面我们来了一下静态资源优化常用的手段

1 JS/CSS压缩,减少流量

2 多个JS/CSS组合,减少连接数

3 CDN就近访问

工具有

Tengine:http://tengine.taobao.org/

webback

CDN

秒杀系统Web实践——05页面优化(页面缓存+url缓存+对象缓存、页面静态化+前后端分离、静态资源优化、CDN优化)_第2张图片

秒杀系统Web实践——05页面优化(页面缓存+url缓存+对象缓存、页面静态化+前后端分离、静态资源优化、CDN优化)_第3张图片

秒杀系统Web实践——05页面优化(页面缓存+url缓存+对象缓存、页面静态化+前后端分离、静态资源优化、CDN优化)_第4张图片


综述

优化完成后,我们可以再次用JMeter进行性能测试,看看QPS是否变大了

你可能感兴趣的:(秒杀项目实战)