1.商品详情页面生成
1.1 实现思路
1). 为什么商品详情页需要静态化处理
由于电商中商品详情页, 在商品一旦审核通过并上架之后, 商品就不会再变化; 所有用户访问到该商品都是相同信息 , 不需要再请求微服务查询数据库 , 效率低 ;
实现静态化, 生成静态页面 , 访问时通过nginx 访问静态页面 , 效率高 ;
2). 实现流程
1.2 页面微服务搭建
1). pom.xml
com.changgou
changgou_common
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-amqp
com.changgou
changgou_service_goods_api
1.0-SNAPSHOT
2). application.yml
server:
port: 9011
spring:
application:
name: page
rabbitmq:
host: 192.168.200.128
main:
allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:6868/eureka
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: false
client:
config:
default: #配置全局的feign的调用超时时间 如果 有指定的服务配置 默认的配置不会生效
connectTimeout: 600000 # 指定的是 消费者 连接服务提供者的连接超时时间 是否能连接 单位是毫秒
readTimeout: 600000 # 指定的是调用服务提供者的 服务 的超时时间() 单位是毫秒
#hystrix 配置
hystrix:
command:
default:
execution:
timeout:
#如果enabled设置为false,则请求超时交给ribbon控制
enabled: true
isolation:
strategy: SEMAPHORE
生成静态页的位置
pagepath: D:\items
3). 引导类
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {“com.changgou.goods.feign”})
public class PageApplication {
public static void main(String[] args) {
SpringApplication.run(PageApplication.class,args);
}
}
1.3 Feign接口
商品详情页面中, 展示的商品信息 包含 : 分类的信息 , spu 信息 , sku信息 ;
@FeignClient(name = “goods”)
public interface CategoryFeign {
@GetMapping("/category/{id}")
public Result findById(@PathVariable(“id”) Integer id);
}
@FeignClient(name = “goods”)
public interface SkuFeign {
@GetMapping("/sku/spu/{spuId}")
public List findSkuListBySpuId(@PathVariable(“spuId”) String spuId);
}
@FeignClient(name = “goods”)
public interface SpuFeign {
@GetMapping("/spu/findSpuById/{id}")
public Result findSpuById(@PathVariable(“id”) String id);
}
1.4 业务层逻辑实现
1). 静态页面的名称
D:/items/{spuId}.html -------------> D:/items/10000001.html , D:/items/10000002.html , D:/items/10000003.html
2). Thymeleaf生成静态页面整体代码结构
Context context = new Context();
context.setVariables(dataModel); //组装数据模型, 封装到Context对象中 ;
templateEngine.process(“templatename” , context , new FileWriter(new File(“D:/items/10000001.html”))); //生成静态页面 ;
3). 获取数据模型
需求:
A. 商品三级分类信息 ;
B. 商品SPU信息 ;
C. 商品SKU列表信息 ;
@Service
public class PageServiceImpl implements PageService {
/**
* 注入templateEngine用于生成html页面
*/
@Autowired
private TemplateEngine templateEngine;
@Value("${pagepath}")
private String pagepath;
/**
* 生成商品详情页面
*
* @param spuId 商品id
*/
@Override
public void generateItemPage(String spuId) {
// 2.构建数据模型,封装到context中
Context context = new Context();
// 2.1 设置数据
context.setVariables(getItemData(spuId));
// 3.使用输出流进行写出页面
FileWriter fileWriter = null;
try {
// 3.1指定文件创建的位置
File dir = new File(pagepath);
// 3.2 对文件的位置进行判断, 如果目录不存在就进行创建
if (!dir.exists()) {
dir.mkdirs();
}
// 3.3 定义文件的名称
File file = new File(dir + "/" + spuId + ".html");
fileWriter = new FileWriter(file);
// 1.调用templateEngine进行生成html页面。
templateEngine.process("item", context, fileWriter);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileWriter != null) {
fileWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Autowired
private SpuFeign spuFeign;
@Autowired
private SkuFeign skuFeign;
@Autowired
private CategoryFeign categoryFeign;
/**
* 用来封装数据模型
*
* @return 封装好的数据模型
*/
private Map<String, Object> getItemData(String spuId) {
// 0. 创建map用来封装数据
Map<String, Object> dataMap = new HashMap<>();
// 1.通过spuFeign远程调用生成spu
Spu spu = spuFeign.findSpuById(spuId).getData();
dataMap.put("spu", spu);
// 2.调用skuFeign生成sku列表
List<Sku> skuList = skuFeign.findSkuListBySpuId(spuId);
dataMap.put("skuList", skuList);
// 3.通过分类feign获取分类的信息
Category category1 = categoryFeign.findById(spu.getCategory1Id()).getData();
dataMap.put("category1", category1);
Category category2 = categoryFeign.findById(spu.getCategory2Id()).getData();
dataMap.put("category2", category2);
Category category3 = categoryFeign.findById(spu.getCategory3Id()).getData();
dataMap.put("category3", category3);
// 4.通过spu获取图片数据
if (spu != null) {
if (StringUtils.isNotEmpty(spu.getImages())) {
String[] imageList = spu.getImages().split(",");
dataMap.put("imageList", imageList);
// 5.获取封装规格的数据,并转换为Map
Map specificationList = JSON.parseObject(spu.getSpecItems(), Map.class);
dataMap.put("specificationList", specificationList);
}
}
return dataMap;
}
}
1.5 监听消息队列
1). MQ 中队列及绑定关系声明
@Bean(PAGE_CREATE_QUEUE)
public Queue PAGE_CREATE_QUEUE(){
return new Queue(PAGE_CREATE_QUEUE);
}
@Bean
public Binding PAGE_CREATE_QUEUE_BINDING(@Qualifier(PAGE_CREATE_QUEUE)Queue queue,@Qualifier(GOODS_UP_EXCHANGE)Exchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("").noargs();
}
2). 监听类
@Component
public class PageListener {
@Autowired
private PageService pageService;
@RabbitListener(queues = RabbitMQConfig.PAGE_CREATE_QUEUE)
public void receiveMessage(String spuId){
System.out.println("获取静态化页面的商品id,id的值为: "+spuId);
//条用业务层完成静态化页面生成
pageService.generateHtml(spuId);
}
}
1.6 基于Nginx访问静态页面
1). 上传
需要将本地测试生成的静态页面 ---------------------------------> nginx/html
2). 访问测试
http://192.168.192.152/10000000616300.html