商品详情页静态化

257 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

每日英语:

You never know what you're capable of until you try.

翻译:如果不勇于尝试,你永远不知道自己有多强大。 ——《女子监狱》

前言

在做网站的时候,为了提升网站数据加载效率同时降低数据库负载,一般会将变更频率较低的数据做特殊处理,比如做成静态页、添加缓存,通常网站门户会这么做。商品详情页访问频率非常高,而且数据变更频率非常低,所以完全可以做成静态页。

静态页生成流程如下图:

静态页生成流程图.jpg

1 商品详情页静态化

1.1工程搭建

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>mall-web</artifactId>
        <groupId>com.xz</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>mall-page-web</artifactId>
    <description>
        商品详情页生成
    </description>
    <dependencies>
        <dependency>
            <groupId>com.xz</groupId>
            <artifactId>mall-goods-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

bootstrap.yml

server:
  port: 8086
spring:
  application:
    name: mall-web-page
  cloud:
    nacos:
      config:
        file-extension: yaml
        server-addr: xxx.xxx.xxx.xxx:8848
      discovery:
        #Nacos的注册地址
        server-addr: xxx.xxx.xxx.xxx:8848
  thymeleaf:
    cache: false
    encoding: UTF-8

  main:
    allow-bean-definition-overriding: true
#页面生成存储路径
pagepath: G:/xiaozhongjava/xz-mall/items/

#日志配置
logging:
  pattern:
    console: "%msg%n"
启动类:`com.xz.mall.MallPageApplication`
@SpringBootApplication
public class MallPageApplication {
​
    public static void main(String[] args) {
        SpringApplication.run(MallPageApplication.class,args);
    }
}

1.2页面数据分析

我们要想生成静态页,需要同时查询Spu和对应Sku集合以及三级分类。

1.3详情页数据加载

1)分类查询

mall-goods-servicecom.xz.mall.goods.controller.CategoryController中添加根据ID查询分类信息:

/****
 * 根据ID查询
 */
@GetMapping(value = "/{id}")
public RespResult<Category> one(@PathVariable(value = "id")Integer id){
    Category category = categoryService.getById(id);
    return RespResult.ok(category);
}

mall-goods-api中创建com.xz.goods.feign.CategoryFeign

@FeignClient(value = "mall-goods")
public interface CategoryFeign {
    /****
     * 根据ID查询
     */
    @GetMapping(value = "/category/{id}")
    RespResult<Category> one(@PathVariable(value = "id")Integer id);
}

2)Product查询

mall-goods-servicecom.xz.mall.goods.service.SpuService中添加根据SpuId查询Product

//查询商品详情
Product findBySpuId(String id);

mall-goods-servicecom.xz.mall.goods.service.impl.SpuServiceImpl实现查询Product

/***
 * 查询商品详情
 * @param id
 * @return
 */
@Override
public Product findBySpuId(String id) {
    //查询Spu
    Spu spu = spuMapper.selectById(id);
​
    //查询Sku集合
    List<Sku> skus = skuMapper.selectList(new QueryWrapper<Sku>().eq("spu_id",id));
    Product product = new Product();
    product.setSpu(spu);
    product.setSkus(skus);
    return product;
}

mall-goods-servicecom.xz.mall.goods.controller.SpuController中调用查询Product

/***
 * 根据ID查询
 */
@GetMapping(value = "/product/{id}")
public RespResult<Product> one(@PathVariable(value = "id")String id){
    Product product = spuService.findBySpuId(id);
    return RespResult.ok(product);
}

mall-goods-api中创建com.xz.mall.goods.feign.SpuFeign

@FeignClient(value = "mall-goods")
public interface SpuFeign {
​
    /***
     * 根据ID查询
     */
    @GetMapping(value = "/spu/product/{id}")
    RespResult<Product> one(@PathVariable(value = "id")String id);
}

1.4静态页生成

1)Service

mall-page-web创建com.xz.mall.page.service.PageService,代码如下:

public interface PageService {
    //生成静态页
    void html(String id) throws FileNotFoundException, UnsupportedEncodingException;
}

mall-page-web中创建com.xz.mall.page.service.impl.PageServiceImpl,代码如下:

@Service
public class PageServiceImpl implements PageService {
​
    @Autowired
    private SpuFeign spuFeign;
​
    @Autowired
    private CategoryFeign categoryFeign;
​
    @Autowired
    private TemplateEngine templateEngine;
​
    @Value("${pagepath}")
    private String pagepah;
​
    /****
     * 生成静态页
     * @param id
     */
    @Override
    public void html(String id) throws FileNotFoundException, UnsupportedEncodingException {
        //加载数据
        Map<String,Object> dataMap = dataLoad(id);
​
        //创建Thymeleaf容器对象
        Context context = new Context();
        //设置页面数据模型
        context.setVariables(dataMap);
        //文件名字  id.html
        File dest = new File(pagepah, id + ".html");
        PrintWriter writer = new PrintWriter(dest, "UTF-8");
        //生成页面
        templateEngine.process("item", context, writer);
    }
​
    /***
     * 数据加载
     * @param id
     * @return
     */
    public Map<String, Object> dataLoad(String id) {
        //查询商品数据
        RespResult<Product> respProduct = spuFeign.one(id);
        Product product = respProduct.getData();
        if (product != null) {
            //数据模型
            Map<String, Object> dataMap = new HashMap<String, Object>();
            //Spu
            dataMap.put("spu", product.getSpu());
            //图片
            dataMap.put("images", product.getSpu().getImages().split(","));
            //属性
            dataMap.put("attrs",JSON.parseObject(product.getSpu().getAttributeList()));
​
            //三级分类查询
            RespResult<Category> one = categoryFeign.one(product.getSpu().getCategoryOneId());
            RespResult<Category> two = categoryFeign.one(product.getSpu().getCategoryTwoId());
            RespResult<Category> three = categoryFeign.one(product.getSpu().getCategoryThreeId());
            dataMap.put("one", one.getData());
            dataMap.put("two", two.getData());
            dataMap.put("three", three.getData());
​
            //Sku集合转JSON
            List<Sku> skus = product.getSkus();
            List<Map<String, Object>> skuList = new ArrayList<Map<String, Object>>();
            for (Sku sku : skus) {
                Map<String, Object> skuMap = new HashMap<String, Object>();
                skuMap.put("id", sku.getId());
                skuMap.put("name", sku.getName());
                skuMap.put("price", sku.getPrice());
                skuMap.put("attr", sku.getSkuAttribute());
                //添加到集合中
                skuList.add(skuMap);
            }
            dataMap.put("skulist", skuList);
            return dataMap;
        }
        return null;
    }
}

2)Controller

mall-page-web中创建com.xz.mall.page.controller.PageController

@RestController
@RequestMapping(value = "/page")
public class PageController {
​
    @Autowired
    private PageService pageService;
​
    /***
     * 生成静态页
     */
    @GetMapping(value = "/{id}")
    public RespResult html(@PathVariable(value = "id")String id) throws Exception{
        pageService.html(id);
        return RespResult.ok();
    }
}

1.5数据绑定

1)分类

代码如下:

<div class="crumb-wrap">
   <ul class="sui-breadcrumb">
      <li>
         <a href="#" th:text="${one.name}"></a>
      </li>
      <li>
         <a href="#" th:text="${two.name}"></a>
      </li>
      <li class="active" th:text="${three.name}"></li>
   </ul>
</div>

2)图片列表

<!--放大镜效果-->
<div class="zoom">
   <!--默认第一个预览-->
   <div id="preview" class="spec-preview">
      <span class="jqzoom">
         <img th:jqimg="${images[0]}" th:src="${images[0]}" width="400" height="400" />
      </span>
   </div>
   <!--下方的缩略图-->
   <div class="spec-scroll">
       <a class="prev">&lt;</a>
       <!--左右按钮-->
       <div class="items">
           <ul>
               <li th:each="image:${images}">
                   <img th:src="${image}" th:bimg="${image}" onmousemove="preview(this)" />
               </li>
           </ul>
       </div>
       <a class="next">&gt;</a>
   </div>
</div>

3)属性列表

<div id="specification" class="summary-wrap clearfix">
    <dl th:each="attr:${attrs}">
        <dt>
            <div class="fl title">
                <i th:text="${attr.key}"></i>
            </div>
        </dt>
        <dd th:each="opt:${attr.value}">
            <a href="javascript:;" class="selected">
                <i th:text="${opt}"></i>
                <span title="点击取消选择">&nbsp;</span>
            </a>
        </dd>
    </dl>
</div>

总结

本篇文章主要详细讲述了一下商品详情页静态化处理过程中的工程搭建、页面数据分析、详情页数据加载、静态页生成、数据绑定等流程。有兴趣的可以自行去尝试一下。