4 商品详情页
4.1 分析
秒杀活动中,热卖商品的详情页访问频率非常高,详情页的数据加载,我们可以采用直接从数据库查询加载,但这种方式会给数据库带来极大的压力,甚至崩溃,这种方式我们并不推荐。
商品详情页主要有商品介绍、商品标题、商品图片、商品价格、商品数量等,大部分数据几乎不变,可能只有数量会变,因此我们可以考虑把商品详情页做成静态页,每次访问只需要加载库存数量,这样就可以大大降低数据库的压力。
我们这里将采用freemarker来实现商品详情页的静态化,关于freemarker的语法我们就不在这里讲解了,大家可以自行去网上查阅相关API。
4.2 工程搭建
我们创建一个静态页生成工程,用于生成商品详情页。
pom.xml
<dependencies>
<!--依赖web-->
<dependency>
<groupId>com.seckill</groupId>
<artifactId>seckill-web</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--api-->
<dependency>
<groupId>com.seckill</groupId>
<artifactId>seckill-goods-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--freemarker-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
</dependencies>
bootstrap.yml
server:
port: 18087
spring:
application:
name: seckill-page
cloud:
nacos:
config:
file-extension: yaml
server-addr: nacos-server:8848
discovery:
#Nacos的注册地址
server-addr: nacos-server:8848
profiles:
active: dev #dev 开发环境 #test测试环境 #pro生产环境
main:
allow-bean-definition-overriding: true
#freemarker配置
freemarker:
cache: false #关闭模板缓存,方便测试
settings:
template_update_delay: 0 #检查模板更新延迟时间,设置为0表示立即检查,如果时间大于0会有缓存不方便进行模板测试
template-loader-path: classpath:/templates
charset: UTF-8
check-template-location: true
suffix: .ftl
content-type: text/html
expose-request-attributes: true
expose-session-attributes: true
request-context-attribute: request
#超时配置
ribbon:
ReadTimeout: 300000
ConnectTimeout: 30000
#静态页位置
htmlPath: D:/page/html
创建文件生成对象:
public class BaseProcess {
@Autowired
private Configuration configuration;
/***
* 生成静态页
* @param dataMap
* dataMap.templateName: 模板名字
* dataMap.path: 生成文件存储路径
* dataMap.name: 生成的文件名字
* @throws Exception
*/
public void writerPage(Map<String,Object> dataMap) throws Exception {
//获取模板名字
String templateName = dataMap.get("templateName").toString();
//文件生存的路径
String path = dataMap.get("path").toString();
//文件路径如果不存在,则创建
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
//获取文件名字
String fileName = dataMap.get("name").toString();
//获取模板对象
Template template = configuration.getTemplate(templateName);
//模板处理,获取生成的文件字符串
String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, dataMap);
//生成文件
FileUtils.writeStringToFile(new File(path,fileName),content);
}
}
BaseProcess
介绍:
该类用于生成静态文件,调用writerPage
方法即可实现,其中有3个变量,变量注释如下:
templateName:模板名字,例如item.ftl,模板放到templates目录下
path:生成文件的路径,例如D:/page/html
name:生成静态页文件的名字,例如:1.html
4.3 商品详情静态页生成
生成商品详情页,我们需要提供商品信息(sku),并且将商品数据存储到数据模型Map中,然后在页面渲染。
1)静态页生成
在seckill-page
中创建com.seckill.page.service.SkuPageService
,添加生成静态页方法,代码如下:
/***
* 生成静态页
*/
void itemPage(Map<String,Object> dataMap) throws Exception;
在seckill-page
中创建com.seckill.page.service.impl.SkuPageServiceImpl
,添加生成静态页方法,代码如下:
@Service
public class SkuPageServiceImpl extends BaseProcess implements SkuPageService {
/***
* 生成静态页
*/
@Override
public void itemPage(Map<String,Object> dataMap) throws Exception {
dataMap.put("username","王五");
//生成静态页
super.writerPage(dataMap);
}
}
在seckill-page
中创建com.seckill.page.controller.SkuPageController
,添加生成静态页方法,代码如下:
@RestController
@RequestMapping(value = "/page")
public class SkuPageController {
@Autowired
private SkuPageService skuPageService;
@Value("${htmlPath}")
private String htmlPath;
/****
* 生成商品详情静态页
*/
@PostMapping(value = "/html")
public Result html(@RequestBody Sku sku) throws Exception {
//数据模型
Map<String,Object> dataMap = new HashMap<String,Object>();
dataMap.put("name",sku.getId()+".html"); //生成静态页的文件名字
dataMap.put("path",htmlPath); //文件路径
dataMap.put("templateName","item.ftl"); //模板名字
dataMap.put("sku",sku); //商品数据
//生成静态页
skuPageService.itemPage(dataMap);
return new Result(true, StatusCode.OK,"生成成功!");
}
}
注意:其中bootstrap.yml中添加htmlPath: D:/page/html
配置。
关于Freemarker学习:FreeMarker的jar包下载引入
现在已进入面向接口编程的前后端分离时代,大概看下即可
2)Feign调用
在seckill-page-api
中创建com.seckill.page.feign.SkuPageFeign
实现调用,代码如下:
@FeignClient(value = "seckill-page")
public interface SkuPageFeign {
/****
* 生成商品详情静态页
*/
@PostMapping(value = "/page/html")
Result html(@RequestBody Sku sku) throws Exception;
}
4.4 静态页删除
当商品变成普通商品或者商品售罄的时候,需要删除详情页,因此还需要实现一个根据id删除详情页的方法。
在seckill-page
中创建com.seckill.page.service.SkuPageService
,添加删除静态页方法,代码如下:
/***
* 删除静态页
* @param id
* @param htmlPath
*/
void delItemPage(String id,String htmlPath);
在seckill-page
中创建com.seckill.page.service.impl.SkuPageServiceImpl
,添加删除静态页方法,代码如下:
/***
* 删除静态页
* @param id
* @param htmlPath
*/
@Override
public void delItemPage(String id, String htmlPath) {
File file = new File(htmlPath,id+".html");
if(file.exists()){
file.delete();
}
}
在seckill-page
中创建com.seckill.page.controller.SkuPageController
,添加删除静态页方法,代码如下:
/****
* 删除商品详情静态页
*/
@DeleteMapping(value = "/html/{id}")
public Result delHtml(@PathVariable(value = "id")String id) throws Exception {
//删除静态页
skuPageService.delItemPage(id,htmlPath);
return new Result(true, StatusCode.OK,"删除成功!");
}
2)Feign调用
在seckill-page-api
中创建com.seckill.page.feign.SkuPageFeign
实现调用,代码如下:
/****
* 删除商品详情静态页
*/
@DeleteMapping(value = "/page/html/{id}")
Result delHtml(@PathVariable(value = "id")String id) throws Exception;