.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;
}
- Apple iPhone 6s
-
Apple iPhone 6s 4GB 128GB 土豪金价 格
¥降价通知
累计评价 612188促 销
加价购
满999.00另加20.00元,或满1999.00另加30.00元,或满2999.00另加40.00元,即可在购物车换
购热销商品
支 持
以旧换新,闲置手机回收 4G套餐超值抢 礼品购
配 送 至
上海
{{o}}
<input autocomplete=“off” type=“text” disabled v-model=“num” minnum=“1”
class=“itxt”/>
<a href=“javascript:void(0)” class=“increment plus” @click=“increment”>+
<a href=“javascript:void(0)” class=“increment mins” @click=“decrement”>-
<a href=“#” @click.prevent=“addCart” target=“_blank”
class=“sui-btn btn-danger addshopcar”>加入购物车
-
相关分类
-
推荐品牌
- 手机
- 手机壳
- 内存卡
- Iphone配件
- 贴膜
- 手机耳机
- 移动电源
- 平板电脑
Apple苹果iPhone 6s (A1699)
¥
6088.00
Apple苹果iPhone 6s (A1699)
¥
6088.00
Apple苹果iPhone 6s (A1699)
¥
6088.00
Apple苹果iPhone 6s (A1699)
¥
6088.00
Apple苹果iPhone 6s (A1699)
¥
6088.00
推荐品牌
选择搭配
¥5299
+
Feless费勒斯VR
39
Feless费勒斯VR
50
Feless费勒斯VR
59
Feless费勒斯VR
99
已选购0件商品套餐价¥5299加入购物车
-
商品介绍
-
规格与包装
-
售后保障
-
商品评价
-
手机社区
- 分辨率:1920*1080(FHD)
- 后置摄像头:1200万像素
- 前置摄像头:500万像素
- 核 数:其他
- 频 率:以官网信息为准
- 品牌: Apple
- 商品名称:APPLEiPhone 6s Plus
- 商品编号:1861098
- 商品毛重:0.51kg
- 商品产地:中国大陆
- 热点:指纹识别,Apple Pay,金属机身,拍照神器
- 系统:苹果(IOS)
- 像素:1000-1600万
- 机身内存:64GB
包装清单
手机X1、快速指南X1、华为SuperCharge 充电器X1、三包凭证X1、Type-C
数字耳机X1、Type-C 数据线X1、取卡针X1、TPU保护壳X1、USB Type-C转3.5mm耳机转接线X1(备注:最终以实物为准)
售后保障
商品评价
手机社区
猜你喜欢
DELL戴尔Ins 15MR-7528SS 15英寸 银色 笔记本
¥
3699.00
已有6人评价
Apple苹果iPhone 6s/6s Plus 16G 64G 128G
¥
4388.00
已有700人评价
DELL戴尔Ins 15MR-7528SS 15英寸 银色 笔记本
¥
4088.00
已有700人评价
DELL戴尔Ins 15MR-7528SS 15英寸 银色 笔记本
¥
4088.00
已有700人评价
DELL戴尔Ins 15MR-7528SS 15英寸 银色 笔记本
¥
4088.00
已有700人评价
DELL戴尔Ins 15MR-7528SS 15英寸 银色 笔记本
¥
4088.00
已有700人评价
4、删除刚刚创建的一些测试内容
4、在resources下创建配置文件application.yml
server:
port: 8086
spring:
application:
name: page-service
thymeleaf:
cache: false #设置缓存关闭
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
instance:
lease-renewal-interval-in-seconds: 5 # 每隔5秒发送一次心跳
lease-expiration-duration-in-seconds: 10 # 10秒不发送就过期
5、nginx反向代理
server {
listen 80;
server_name www.leyou.com;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location /item {
proxy_pass http://192.168.58.2:8086; #主机地址 下的8086端口
proxy_connect_timeout 600;
proxy_read_timeout 600;
}
location / {
proxy_pass http://192.168.58.2:9002; #主机地址 下的9001端口
proxy_connect_timeout 600;
proxy_read_timeout 600;
}
}
重新加载nginx
6、完善启动类
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 LyPageApplication {
public static void main(String[] args) {
SpringApplication.run(LyPageApplication.class);
}
}
6、完善search.html页面实现对应点击商品查看详情功能
<img :src="goods.
真题解析、进阶学习笔记、最新讲解视频、实战项目源码、学习路线大纲
详情关注公中号【编程进阶路】selectedSku.images" height=“200”/>
7、创建PageController
package com.leyou.page.web;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@Controller
public class PageController {
@GetMapping(“item/{id}.html”)
public String toItemPage(@PathVariable(“id”) Long spuId, Model model){
//准备模型数据
//返回视图
return “/item”;
}
}
重新运行
点击实现页面跳转
8、封装模型数据
首先我们一起来分析一下,在这个页面中需要哪些数据
我们已知的条件是传递来的spu的id,我们需要根据spu的id查询到下面的数据:
-
spu信息
-
spu的详情
-
spu下的所有sku
-
品牌
-
商品三级分类
-
商品规格参数、规格参数组
(1)商品微服务提供接口
1)查询spu,根据页面id查询对应的sup的信息
a、完善GoodsApi
/*
根据spu的id查询spu
*/
@GetMapping(“/spu/{id}”)
Spu querySpuById(@PathVariable(“id”) Long id);
b、完善GoodsController
/*
根据spu的id查询spu
*/
@GetMapping(“/spu/{id}”)
public ResponseEntity querySpuById(@PathVariable(“id”) Long id){
return ResponseEntity.ok(goodsService.querySpuById(id));
}
c、完善goodsService
public Spu querySpuById(Long id) {
Spu spu = spuMapper.selectByPrimaryKey(id);
if(spu == null){
throw new LyException(ExceptionEnum.GOODS_NOT_FOND);
}
//查询sku
List skus = querySkuBySpuId(spu.getId());
//查询详情detail
SpuDetail spuDetail = queryDetailById(spu.getId());
spu.setSkus(skus);
spu.setSpuDetail(spuDetail);
return spu;
}
2)查询规格参数组
a、拓展SpecGroup
package com.leyou.item.pojo;
import lombok.Data;
import tk.mybatis.mapper.annotation.KeySql;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.util.List;
@Table(name = “tb_spec_group”)
@Data
public class SpecGroup {
@Id
@KeySql(useGeneratedKeys = true)
private Long id;
private Long cid;
private String name;
@Transient
private List params;
}
b、完善SpecificationApi
@GetMapping(“spec/group”)
List queryGroupByCid(@RequestParam(“cid”) Long cid);
c、完善SpecificationController,这里的方法名可以与api当中的方法名不一致,因为调用是通过路径去调用的
/*
根据父类查询规格组以及组内参数
*/
@GetMapping(“group”)
public ResponseEntity<List> queryListByCid(@RequestParam(“cid”) Long cid){
return ResponseEntity.ok(specificationService.queryListByCid(cid));
}
d、完善specificationService
public List queryListByCid(Long cid) {
//查询规格参数组
List specGroups = queryGroupByCid(cid);
//查询当前分类下的参数
List specParams = queryParamList(null, cid, null);
/*
下拉代码的目的是将specParams集合放入specGroups当中,一一对应
如果通过双层for循环性能太低
在specParams集合当中的SpecParam对应拥有SpecGroup的id
所以将SpecParam对应拥有SpecGroup的id作为键而 List做为值组合为map集合
遍历specGroups集合获取其specGroup的id到map当中查询到对应的specParams集合,然后放入到specGroup.setParams当中
*/
//先把规格参数变为map,map的key是规格组id,map的值是组下的所有参数
Map<Long,List> map = new HashMap<>();
for (SpecParam param : specParams) {
if(!map.containsKey(param.getGroupId())){//判断map当中是否已经存在param.getGroupId(),如果存在
//这一组id在map当中不存在
//新增一个list
map.put(param.getGroupId(),new ArrayList<>());
}
map.get(param.getGroupId()).add(param);//将集合添加到map当中
}
//填充param到Group当中
for (SpecGroup specGroup : specGroups) {
specGroup.setParams(map.get(specGroup.getId()));
}
return specGroups;
}
(2)实现页面数据的封装
1)在ly-page创建对应的包结构,复制之前在ly-search创建的client
2)分析页面所需要的数据
3)创建对应的Service
package com.leyou.page.service;
import org.springframework.stereotype.Service;
@Service
public class PageService {
}
4)将上述对应的数据在添加到PageController的Model当中
a、完善PageController
package com.leyou.page.web;
import com.leyou.page.service.PageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Map;
@Controller
@RequestMapping(“item”)
public class PageController {
@Autowired
private PageService pageService;
@GetMapping(“{id}.html”)
public String toItemPage(@PathVariable(“id”) Long spuId, Model model){
//查询数据
Map<String,Object> attributes = pageService.loadModel(spuId);
//准备模型数据
model.addAllAttributes(attributes);
//返回视图
return “item”;
}
}
b、完善service
package com.leyou.page.service;
import com.leyou.item.pojo.*;
import com.leyou.page.client.BrandClient;
import com.leyou.page.client.CategoryClient;
import com.leyou.page.client.GoodsClient;
import com.leyou.page.client.SpecificationClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
public class PageService {
@Autowired
private BrandClient brandClient;
@Autowired
private CategoryClient categoryClient;
@Autowired
private GoodsClient goodsClient;
@Autowired
private SpecificationClient specificationClient;
public Map<String, Object> loadModel(Long spuId) {
Map<String, Object> model = new HashMap<>();
//查询spu
Spu spu = goodsClient.querySpuById(spuId);
//查询skus
List skus = spu.getSkus();
//查询spuDetail
SpuDetail spuDetail = spu.getSpuDetail();
//查询brand
Brand brand = brandClient.queryBrandById(spu.getBrandId());
//查询商品的分类
List categories = categoryClient.queryCategoryByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));
//查询规格参数
List groups = specificationClient.queryGroupByCid(spu.getCid3());
// 查询特殊的规格参数
List params = specificationClient.queryParamList(null, spu.getCid3(), false);
Map<Long, String> paramMap = new HashMap<>();
params.forEach(param -> {
paramMap.put(param.getId(), param.getName());
});
model.put(“spu”,spu);
model.put(“skus”,skus);
model.put(“spuDetail”,spuDetail);
model.put(“detail”,spuDetail);
model.put(“brand”,brand);
model.put(“categories”,categories);
model.put(“groups”,groups);
model.put(“specs”,groups);
model.put(“paramMap”,paramMap);
return model;
}
}
1、简介
(1)问题分析
现在,我们的页面是通过Thymeleaf模板引擎渲染后返回到客户端。在后台需要大量的数据查询,而后渲染得到HTML页面。会对数据库造成压力,并且请求的响应时间过长,并发能力不高。
大家能想到什么办法来解决这个问题?
首先我们能想到的就是缓存技术,比如之前学习过的Redis。不过Redis适合数据规模比较小的情况。假如数据量比较大,例如我们的商品详情页。每个页面如果10kb,100万商品,就是10GB空间,对内存占用比较大。此时就给缓存系统带来极大压力,如果缓存崩溃,接下来倒霉的就是数据库了。
所以缓存并不是万能的,某些场景需要其它技术来解决,比如静态化。
(2)什么是静态化
静态化是指把动态生成的HTML页面变为静态内容保存,以后用户的请求到来,直接访问静态页面,不再经过服务的渲染。
而静态的HTML页面可以部署在nginx中,从而大大提高并发能力,减小tomcat压力。
(3)如何实现静态化
目前,静态化页面都是通过模板引擎来生成,而后保存到nginx服务器来部署。常用的模板引擎比如:
-
Freemarker
-
Velocity
-
Thymeleaf
其实前端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
这里再分享一个复习的路线:(以下体系的复习资料是我从各路大佬收集整理好的)
《前端开发四大模块核心知识笔记》
最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。
-