完成乐优商城商品详情页
com.leyou.service
ly-page
<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>parentartifactId>
<groupId>com.leyougroupId>
<version>1.0.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<groupId>com.leyou.servicegroupId>
<artifactId>ly-pageartifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>com.leyou.servicegroupId>
<artifactId>ly-item-interfaceartifactId>
<version>${leyou.latest.version}version>
dependency>
dependencies>
project>
server:
port: 8004
spring:
application:
name: page-service
thymeleaf:
cache: false # 关闭thymeleaf缓存
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:9999/eureka
instance:
lease-renewal-interval-in-seconds: 5 # 每隔5秒发送一次心跳
lease-expiration-duration-in-seconds: 10 # 10秒不发送就过期
package com.leyou;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class LyPageService {
public static void main(String[] args) {
SpringApplication.run(LyPageService.class, args);
}
}
将下面的代码放入resources/templates
下。
这个模板为最终模板,即内部逻辑已经全部完成,只需要放入数据即可。
<html xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<title>乐优商城--商品详情页title>
<link rel="icon" href="/assets/img/favicon.ico">
<link rel="stylesheet" type="text/css" href="/css/webbase.css" />
<link rel="stylesheet" type="text/css" href="/css/pages-item.css" />
<link rel="stylesheet" type="text/css" href="/css/pages-zoom.css" />
<link rel="stylesheet" type="text/css" href="/css/widget-cartPanelView.css" />
<style type="text/css">
.goods-intro-list li {
display: inline-block;
width: 300px;
}
.Ptable {
margin: 10px 0;
}
.Ptable-item {
padding: 12px 0;
line-height: 220%;
color: #999;
font-size: 12px;
border-bottom: 1px solid #eee;
}
.Ptable-item h3 {
width: 110px;
text-align: right;
}
.Ptable-item h3, .package-list h3 {
font-weight: 400;
font-size: 12px;
float: left;
}
h3 {
display: block;
font-size: 1.17em;
-webkit-margin-before: 1em;
-webkit-margin-after: 1em;
-webkit-margin-start: 0px;
-webkit-margin-end: 0px;
font-weight: bold;
}
.Ptable-item dl {
margin-left: 110px;
}
dl {
display: block;
-webkit-margin-before: 1em;
-webkit-margin-after: 1em;
-webkit-margin-start: 0px;
-webkit-margin-end: 0px;
}
.Ptable-item dt {
width: 160px;
float: left;
text-align: right;
padding-right: 5px;
}
.Ptable-item dd {
margin-left: 210px;
}
dd {
display: block;
-webkit-margin-start: 40px;
}
.package-list {
padding: 12px 0;
line-height: 220%;
color: #999;
font-size: 12px;
margin-top: -1px;
}
.package-list h3 {
width: 130px;
text-align: right;
}
.package-list p {
margin-left: 155px;
padding-right: 50px;
}
style>
head>
<body>
<div id="itemApp">
<div id="nav-bottom">
<ly-top />
div>
<div class="py-container">
<div id="item">
<div class="crumb-wrap">
<ul class="sui-breadcrumb">
<li th:each="category : ${categories}">
<a href="#" th:text="${category.name}">手机a>
li>
<li>
<a href="#" th:text="${brand.name}">Applea>
li>
<li class="active" th:text="${spu.title}">Apple iPhone 6sli>
ul>
div>
<div class="product-info">
<div class="fl preview-wrap">
<div class="zoom">
<div id="preview" class="spec-preview">
<span class="jqzoom">
<img :jqimg="images[0]" :src="images[0]" width="400px" height="400px"/>
span>
div>
<div class="spec-scroll">
<a class="prev"><a>
<div class="items">
<ul>
<li v-for="(image, i) in images" :key="i">
<img :src="image" :bimg="image" onmousemove="preview(this)" />
li>
ul>
div>
<a class="next">>a>
div>
div>
div>
<div class="fr itemInfo-wrap">
<div class="sku-name">
<h4 v-text="sku.title">h4>
div>
<div class="news"><span th:utext="${spu.subTitle}">span>div>
<div class="summary">
<div class="summary-wrap">
<div class="fl title"><i>价 格i>div>
<div class="fl price">
<i>¥i><em v-text="ly.formatPrice(sku.price)">em><span>降价通知span>
div>
<div class="fr remark"><i>累计评价i><em>612188em>div>
div>
<div class="summary-wrap">
<div class="fl title">
<i>促 销i>
div>
<div class="fl fix-width">
<i class="red-bg">加价购i>
<em class="t-gray">满999.00另加20.00元,或满1999.00另加30.00元,或满2999.00另加40.00元,即可在购物车换
购热销商品em>
div>
div>
div>
<div class="support">
<div class="summary-wrap">
<div class="fl title">
<i>支 持i>
div>
<div class="fl fix-width">
<em class="t-gray">以旧换新,闲置手机回收 4G套餐超值抢 礼品购em>
div>
div>
<div class="summary-wrap">
<div class="fl title">
<i>配 送 至i>
div>
<div class="fl fix-width">
<em class="t-gray">上海 <span>有货span>em>
div>
div>
div>
<div class="clearfix choose">
<div id="specification" class="summary-wrap clearfix">
<dl v-for="(value,key) in specialSpec" :key="key">
<dt>
<div class="fl title">
<i>{{key}}i>
div>
dt>
<dd v-for="(str, index) in value" :key="index">
<a href="javascript:;" :class="{selected: index===indexes[key]}" @click="indexes[key]=index">
{{str}}<span v-if="index===indexes[key]" title="点击取消选择"> span>
a>
dd>
dl>
div>
<div class="summary-wrap">
<div class="fl title">
<div class="control-group">
<div class="controls">
<input autocomplete="off" type="text" disabled value="1" minnum="1" class="itxt" />
<a href="javascript:void(0)" class="increment plus">+a>
<a href="javascript:void(0)" class="increment mins">-a>
div>
div>
div>
<div class="fl">
<ul class="btn-choose unstyled">
<li>
<a href="success-cart.html" target="_blank" class="sui-btn btn-danger addshopcar">加入购物车a>
li>
ul>
div>
div>
div>
div>
div>
<div class="clearfix product-detail">
<div class="fl aside">
<ul class="sui-nav nav-tabs tab-wraped">
<li class="active">
<a href="#index" data-toggle="tab">
<span>相关分类span>
a>
li>
<li>
<a href="#profile" data-toggle="tab">
<span>推荐品牌span>
a>
li>
ul>
<div class="tab-content tab-wraped">
<div id="index" class="tab-pane active">
<ul class="part-list unstyled">
<li>手机li>
<li>手机壳li>
<li>内存卡li>
<li>Iphone配件li>
<li>贴膜li>
<li>手机耳机li>
<li>移动电源li>
<li>平板电脑li>
ul>
<ul class="goods-list unstyled">
<li>
<div class="list-wrap">
<div class="p-img">
<img src="/img/_/part01.png" />
div>
<div class="attr">
<em>Apple苹果iPhone 6s (A1699)em>
div>
<div class="price">
<strong>
<em>¥em>
<i>6088.00i>
strong>
div>
<div class="operate">
<a href="javascript:void(0);" class="sui-btn btn-bordered">加入购物车a>
div>
div>
li>
<li>
<div class="list-wrap">
<div class="p-img">
<img src="/img/_/part02.png" />
div>
<div class="attr">
<em>Apple苹果iPhone 6s (A1699)em>
div>
<div class="price">
<strong>
<em>¥em>
<i>6088.00i>
strong>
div>
<div class="operate">
<a href="javascript:void(0);" class="sui-btn btn-bordered">加入购物车a>
div>
div>
li>
<li>
<div class="list-wrap">
<div class="p-img">
<img src="/img/_/part03.png" />
div>
<div class="attr">
<em>Apple苹果iPhone 6s (A1699)em>
div>
<div class="price">
<strong>
<em>¥em>
<i>6088.00i>
strong>
div>
<div class="operate">
<a href="javascript:void(0);" class="sui-btn btn-bordered">加入购物车a>
div>
div>
<div class="list-wrap">
<div class="p-img">
<img src="/img/_/part02.png" />
div>
<div class="attr">
<em>Apple苹果iPhone 6s (A1699)em>
div>
<div class="price">
<strong>
<em>¥em>
<i>6088.00i>
strong>
div>
<div class="operate">
<a href="javascript:void(0);" class="sui-btn btn-bordered">加入购物车a>
div>
div>
<div class="list-wrap">
<div class="p-img">
<img src="/img/_/part03.png" />
div>
<div class="attr">
<em>Apple苹果iPhone 6s (A1699)em>
div>
<div class="price">
<strong>
<em>¥em>
<i>6088.00i>
strong>
div>
<div class="operate">
<a href="javascript:void(0);" class="sui-btn btn-bordered">加入购物车a>
div>
div>
li>
ul>
div>
<div id="profile" class="tab-pane">
<p>推荐品牌p>
div>
div>
div>
<div class="fr detail">
<div class="clearfix fitting">
<h4 class="kt">选择搭配h4>
<div class="good-suits">
<div class="fl master">
<div class="list-wrap">
<div class="p-img">
<img src="/img/_/l-m01.png" />
div>
<em>¥5299em>
<i>+i>
div>
div>
<div class="fl suits">
<ul class="suit-list">
<li class="">
<div id="">
<img src="/img/_/dp01.png" />
div>
<i>Feless费勒斯VRi>
<label data-toggle="checkbox" class="checkbox-pretty">
<input type="checkbox"><span>39span>
label>
li>
<li class="">
<div id=""><img src="/img/_/dp02.png" /> div>
<i>Feless费勒斯VRi>
<label data-toggle="checkbox" class="checkbox-pretty">
<input type="checkbox"><span>50span>
label>
li>
<li class="">
<div id=""><img src="/img/_/dp03.png" />div>
<i>Feless费勒斯VRi>
<label data-toggle="checkbox" class="checkbox-pretty">
<input type="checkbox"><span>59span>
label>
li>
<li class="">
<div id=""><img src="/img/_/dp04.png" />div>
<i>Feless费勒斯VRi>
<label data-toggle="checkbox" class="checkbox-pretty">
<input type="checkbox"><span>99span>
label>
li>
ul>
div>
<div class="fr result">
<div class="num">已选购0件商品div>
<div class="price-tit"><strong>套餐价strong>div>
<div class="price">¥5299div>
<button class="sui-btn btn-danger addshopcar">加入购物车button>
div>
div>
div>
<div class="tab-main intro">
<ul class="sui-nav nav-tabs tab-wraped">
<li class="active">
<a href="#one" data-toggle="tab">
<span>商品介绍span>
a>
li>
<li>
<a href="#two" data-toggle="tab">
<span>规格与包装span>
a>
li>
<li>
<a href="#three" data-toggle="tab">
<span>售后保障span>
a>
li>
<li>
<a href="#four" data-toggle="tab">
<span>商品评价span>
a>
li>
<li>
<a href="#five" data-toggle="tab">
<span>手机社区span>
a>
li>
ul>
<div class="clearfix">div>
<div class="tab-content tab-wraped">
<div id="one" class="tab-pane active">
<div class="intro-detail">
<div th:utext="${detail.description}">div>
div>
div>
<div id="two" class="tab-pane">
<div class="Ptable">
<div class="Ptable-item" v-for="(group, i) in specs" :key="i">
<h3 v-text="group.group">h3>
<dl>
<span v-for="(param,j) in group.params" :key="j">
<dt v-text="param.k">dt>
<dd v-text="param.v ? param.v + (param.unit || '') : JSON.parse(sku.ownSpec)[param.k]">dd>
span>
dl>
div>
div>
<div class="package-list">
<h3>包装清单h3>
<p th:text="${detail.packingList}">p>
div>
div>
<div id="three" class="tab-pane">
<p>售后保障p>
<p th:text="${detail.afterService}">p>
div>
<div id="four" class="tab-pane">
<p>商品评价p>
div>
<div id="five" class="tab-pane">
<p>手机社区p>
div>
div>
div>
div>
div>
<div class="clearfix">div>
<div class="like">
<h4 class="kt">猜你喜欢h4>
<div class="like-list">
<ul class="yui3-g">
<li class="yui3-u-1-6">
<div class="list-wrap">
<div class="p-img">
<img src="/img/_/itemlike01.png" />
div>
<div class="attr">
<em>DELL戴尔Ins 15MR-7528SS 15英寸 银色 笔记本em>
div>
<div class="price">
<strong>
<em>¥em>
<i>3699.00i>
strong>
div>
<div class="commit">
<i class="command">已有6人评价i>
div>
div>
li>
<li class="yui3-u-1-6">
<div class="list-wrap">
<div class="p-img">
<img src="/img/_/itemlike02.png" />
div>
<div class="attr">
<em>Apple苹果iPhone 6s/6s Plus 16G 64G 128Gem>
div>
<div class="price">
<strong>
<em>¥em>
<i>4388.00i>
strong>
div>
<div class="commit">
<i class="command">已有700人评价i>
div>
div>
li>
<li class="yui3-u-1-6">
<div class="list-wrap">
<div class="p-img">
<img src="/img/_/itemlike03.png" />
div>
<div class="attr">
<em>DELL戴尔Ins 15MR-7528SS 15英寸 银色 笔记本em>
div>
<div class="price">
<strong>
<em>¥em>
<i>4088.00i>
strong>
div>
<div class="commit">
<i class="command">已有700人评价i>
div>
div>
li>
<li class="yui3-u-1-6">
<div class="list-wrap">
<div class="p-img">
<img src="/img/_/itemlike04.png" />
div>
<div class="attr">
<em>DELL戴尔Ins 15MR-7528SS 15英寸 银色 笔记本em>
div>
<div class="price">
<strong>
<em>¥em>
<i>4088.00i>
strong>
div>
<div class="commit">
<i class="command">已有700人评价i>
div>
div>
li>
<li class="yui3-u-1-6">
<div class="list-wrap">
<div class="p-img">
<img src="/img/_/itemlike05.png" />
div>
<div class="attr">
<em>DELL戴尔Ins 15MR-7528SS 15英寸 银色 笔记本em>
div>
<div class="price">
<strong>
<em>¥em>
<i>4088.00i>
strong>
div>
<div class="commit">
<i class="command">已有700人评价i>
div>
div>
li>
<li class="yui3-u-1-6">
<div class="list-wrap">
<div class="p-img">
<img src="/img/_/itemlike06.png" />
div>
<div class="attr">
<em>DELL戴尔Ins 15MR-7528SS 15英寸 银色 笔记本em>
div>
<div class="price">
<strong>
<em>¥em>
<i>4088.00i>
strong>
div>
<div class="commit">
<i class="command">已有700人评价i>
div>
div>
li>
ul>
div>
div>
div>
div>
div>
<script src="/js/vue/vue.js">script>
<script src="/js/axios.min.js">script>
<script src="/js/common.js">script>
<script th:inline="javascript">
// sku集合
const skus = /*[[${skus}]]*/ [];
// 规格参数id与name对
const paramMap = /*[[${specs}]]*/ {};
// 特有规格参数集合
const specialSpec = JSON.parse(/*[[${detail.specTemplate}]]*/ "");
// 初始化特有规格参数默认选中一个
const indexes = {};
const initIndex = skus[0].indexes.split("_");
Object.keys(specialSpec).forEach((key, i) => {
indexes[key] = parseInt(initIndex[i]);
});
const indexArr = skus.map(s => s.indexes);
const specs = JSON.parse(/*[[${detail.specifications}]]*/ "");
script>
<script>
var itemVm = new Vue({
el:"#itemApp",
data:{
ly,
skus,
paramMap,
specialSpec,
indexes,
specs
},
components:{
lyTop: () => import('/js/pages/top.js')
},
computed: {
sku(){
const index = Object.values(this.indexes).join("_");
return this.skus.find(s=>s.indexes==index);
},
images(){
return this.sku.images ? this.sku.images.split(",") : [''];
}
},
});
script>
<script type="text/javascript" src="/js/plugins/jquery/jquery.min.js">script>
<script type="text/javascript">
$(function(){
$("#service").hover(function(){
$(".service").show();
},function(){
$(".service").hide();
});
$("#shopcar").hover(function(){
$("#shopcarlist").show();
},function(){
$("#shopcarlist").hide();
});
})
script>
<script type="text/javascript" src="/js/model/cartModel.js">script>
<script type="text/javascript" src="/js/plugins/jquery.easing/jquery.easing.min.js">script>
<script type="text/javascript" src="/js/plugins/sui/sui.min.js">script>
<script type="text/javascript" src="/js/plugins/jquery.jqzoom/jquery.jqzoom.js">script>
<script type="text/javascript" src="/js/plugins/jquery.jqzoom/zoom.js">script>
<script type="text/javascript" src="index/index.js">script>
body>
html>
分别创建 BrandClient,CategoryClient,GoodsClient和SpecificationClient接口并继承item-interface
中对应的API接口类即可。
提供api,基本上所有的api已经在之前就准备好了,只需要在GoodsController
中新增一个api。
/**
* 查询spu信息
*
* @param spuId 商品ID
* @return Spu
*/
@GetMapping("/{spuId}")
public ResponseEntity<SpuBO> queryGoodsById(@PathVariable("spuId") Long spuId) {
return ResponseEntity.ok(goodsService.queryGoodsById(spuId));
}
goodsService.queryGoodsById(spuId)在之前已经实现,只需要将api对外提供即可。
这是我的常量类,PageService用到的一些字符串常量,我都定义在这里面的
package com.leyou.page.util;
/**
* page service 常量类
*/
public final class PageServiceConstants {
/**
* template name
*/
public static final String TEMPLATE_NAME_ITEM = "item";
/**
* Model field
*/
public static final String MODEL_CATEGORIES = "categories";
public static final String MODEL_BRAND = "brand";
public static final String MODEL_SPU = "spu";
public static final String MODEL_DETAIL = "detail";
public static final String MODEL_SKUS = "skus";
public static final String MODEL_SPECS = "specs";
}
package com.leyou.page.controller;
import com.leyou.page.service.PageService;
import com.leyou.page.util.PageServiceConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.Map;
@Controller
public class PageController {
@Autowired
private PageService pageService;
/**
* 生成数据并返回到item视图
*/
@GetMapping("item/{id}.html")
public String spuPageInfo(@PathVariable("id") Long spuId, Model model) {
// 获取数据
Map<String, Object> attributes = pageService.loadModel(spuId);
// 封装数据
model.addAllAttributes(attributes);
return PageServiceConstants.TEMPLATE_NAME_ITEM;
}
}
package com.leyou.page.service;
import com.alibaba.fastjson.JSON;
import com.leyou.BO.SpuBO;
import com.leyou.client.item.BrandClient;
import com.leyou.client.item.CategoryClient;
import com.leyou.client.item.GoodsClient;
import com.leyou.client.item.SpecificationClient;
import com.leyou.page.util.PageServiceConstants;
import com.leyou.pojo.Brand;
import com.leyou.pojo.Category;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class PageService {
@Autowired
private GoodsClient goodsClient;
@Autowired
private CategoryClient categoryClient;
@Autowired
private BrandClient brandClient;
@Autowired
private SpecificationClient specificationClient;
public Map<String, Object> loadModel(Long spuId) {
Map<String, Object> model = new HashMap<>();
// 获取spu信息
SpuBO spuBO = goodsClient.queryGoodsById(spuId);
// 分类数据
List<Category> categories = categoryClient.queryCategoryListByIds(Arrays.asList(spuBO.getCid1(), spuBO.getCid2(), spuBO.getCid3()));
// 品牌数据
Brand brand = brandClient.queryBrandById(spuBO.getBrandId());
model.put(PageServiceConstants.MODEL_BRAND, brand);
model.put(PageServiceConstants.MODEL_CATEGORIES, categories);
model.put(PageServiceConstants.MODEL_DETAIL, spuBO.getSpuDetail());
model.put(PageServiceConstants.MODEL_SKUS, spuBO.getSkuList());
model.put(PageServiceConstants.MODEL_SPECS, JSON.parseObject(spuBO.getSpuDetail().getSpecTemplate()));
model.put(PageServiceConstants.MODEL_SPU, spuBO);
return model;
}
}
之前所有的
www.leyou.com
域名下的地址都会转发到9002端口,现在我们需要将/item
的请求转发到8004端口,也就是我们的page-service
的端口
启动nginx,即可测试啦。
静态化是指把动态生成的HTML页面变为静态内容保存,以后用户的请求到来,直接访问静态页面,不再经过服务的渲染。
而静态的HTML页面可以部署在nginx中,从而大大提高并发能力,减小服务器访问压力。
目前,静态化页面都是通过模板引擎来生成,而后保存到nginx服务器来部署。常用的模板引擎比如:
我们之前就使用的Thymeleaf,来渲染html返回给用户。Thymeleaf除了可以把渲染结果写入Response,也可以写到本地文件,从而实现静态化。
用来保存模型数据,当模板引擎渲染时,可以从Context上下文中获取数据用于渲染。
当与SpringBoot结合使用时,我们放入Model的数据就会被处理到Context,作为模板渲染的数据使用。
用来读取模板相关的配置,例如:模板存放的位置信息,模板文件名称,模板文件的类型等等。
当与SpringBoot结合时,TemplateResolver已经由其创建完成,并且各种配置也都有默认值,比如模板存放位置,其默认值就是:templates。比如模板文件类型,其默认值就是html。
模板引擎:用来解析模板的引擎,需要使用到上下文、模板解析器。分别从两者中获取模板中需要的数据,模板文件。然后利用内置的语法规则解析,从而输出解析后的文件。
通过templateEngine.process方法执行解析和页面生成过程
在PageService
中新增代码
@Autowired
private TemplateEngine templateEngine;
@Value("ly.page.destPath")
private String pagePath;
/**
* 生成商品详情页并保存到指定目录
*
* @param spuId 商品ID
*/
public void createHtml(Long spuId) {
Context context = new Context();
context.setVariables(loadModel(spuId));
// 输出流
File file = new File(pagePath + "/" + spuId + ".html");
try(PrintWriter printWriter = new PrintWriter(file)) {
// 生成页面
templateEngine.process(PageServiceConstants.TEMPLATE_NAME_ITEM, context, printWriter);
} catch (FileNotFoundException e) {
log.error("[生成商品详情页失败,商品ID = {}]", spuId, e);
}
}
修改PageController
中的spuPageInfo
方法
修改之前代理到8004端口的配置信息
采用静态页和tomcat加载两种方式,静态页目录未找到该静态页,就从数据库加载数据。
生成商品详情页,使用线程池去执行生成静态页,进一步提高效率。
新增工具类
package com.leyou.page.util;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadUtils {
private static final ExecutorService es = Executors.newFixedThreadPool(10);
public static void execute(Runnable runnable) {
es.submit(runnable);
}
}
PageService新增方法
/**
* 新建线程处理页面静态化
*
* @param spuId 商品ID
*/
public void asyncExcute(Long spuId) {
ThreadUtils.execute(() -> createHtml(spuId));
}
然后修改controller中的生成静态页方法的调用为 asyncExcute(spuId)
即可。
做到这里,会想到,这个静态页生成了就一直不会变了,万一我的商品有了修改,或者下架了怎么办,怎么去完成商品信息的同步呢?使用服务间的调用?还是其他方式?
这个问题在下一个笔记中详细处理,会使用到消息中间件去完成商品信息的一个同步过程。