100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 乐优商城day13(商品详情页 rabbitMQ安装)

乐优商城day13(商品详情页 rabbitMQ安装)

时间:2023-12-04 19:52:41

相关推荐

乐优商城day13(商品详情页 rabbitMQ安装)

所有代码发布在 [/hades0525/leyou]

Day13(rabbitmq)

2月13日

14:45

使用thymeleaf

thymeleaf基本信息

• 默认前缀:classpath:/templates/

• 默认后缀:.html

所以如果我们返回视图:users,会指向到 classpath:/templates/users.html

• Thymeleaf默认会开启页面缓存,提高页面并发能力。但会导致我们修改页面不会立即被展现,因此我们关闭缓存:

spring.thymeleaf.cache=false

• 把html 的名称空间,改成:xmlns:th=“” 会有语法提示

goodspage微服务微服务搭建

• pom

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>com.leyou.service</groupId><artifactId>ly-item-interface</artifactId><version>1.0.0-SNAPSHOT</version></dependency></dependencies>

• 启动类

@EnableDiscoveryClient@EnableFeignClients@SpringBootApplicationpublicclassLyPageApplication{publicstaticvoidmain(String[]args){SpringApplication.run(LyPageApplication.class);}}

• application.yml

server:port: 8084spring:application:name: page-servicethymeleaf:cache: falseeureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka

• 修改sku图片点击的跳转路径

<a :href="'/item/'+goods.id+'.html'" target="_blank">

• 在nginx.conf的中加入

location /item{proxy_pass http://192.168.0.6:8084}

• 编写跳转controller

@Controllerpublic class PageController{@GetMapping("item/{id}.html")public String toItemPage(@PathVariable("id")LongspuId){//准备模型数据//返回视图return "item";}}

封装模型数据

• 分析

我们已知的条件是传递来的spu的id,我们需要根据spu的id查询到下面的数据:

• spu信息(没写)

• spu的详情

• spu下的所有sku

• 品牌

• 商品三级分类

• 商品规格参数、规格参数组(没写)

• 查询spu接口

•GoodsApi/***根据spu的id查询spu*@paramid*@return*/@GetMapping("spu/{id}")SpuquerySpuById(@PathVariable("id")Longid);•GoodsService/***根据spu的id查询spu(sku,detail)*@paramid*@return*/@GetMapping("spu/{id}")publicResponseEntity<Spu>querySpuById(@PathVariable("id")Longid){returnResponseEntity.ok(goodsService.querySpuById(id));}•GoodsController/***根据spu的id查询spu(sku,detail)*@paramid*@return*/publicSpuquerySpuById(Longid){//查询spuSpuspu=spuMapper.selectByPrimaryKey(id);if(spu==null){thrownewLyException(ExceptionEnum.GOODS_NOT_FOUND);}//查询skuspu.setSkus(querySkuBySpuId(id));//查询spudetailspu.setSpuDetail(queryDetailById(id));returnspu;}

• 查询规格参数组

• 在页面展示规格时,需要按组展示。组内有多个参数,为了方便展示。我们提供一个接口,查询规格组,同时在规格组中持有组内的所有参数。

• 扩展SpecGroup类

//添加SpecParam的集合,保存组下所有规格参数@Transientprivate List<SpecParam> params; // 该组下的所有规格参数集合•SpecifictionApi/***根据cid查询规格组及组内参数*@paramcid*@return*/@GetMapping("spec/group")List<SpecGroup> queryListByCid(@RequestParam("cid")Long cid);•SpecifictionController/***根据cid查询规格组及组内参数*@paramcid*@return*/@GetMapping("group")public ResponseEntity<List<SpecGroup>>queryListByCid(@RequestParam("cid")Long cid){return ResponseEntity.ok(specificationService.queryListByCid(cid));}•SpecifictionService/***根据cid查询规格组及组内参数*@paramcid*@return*/public List<SpecGroup> queryListByCid(Long cid){//查询规格组List<SpecGroup>specGroups=queryGroupByCid(cid);//查询当前分类下的参数List<SpecParam>specParams=queryParamByList(null,cid,null);//把规格参数变为mapkey为规格组id,value为组下所有参数Map<Long,List<SpecParam>>map=newHashMap<>();for(SpecParamparam:specParams){if(!map.containsKey(param.getId())){//组id在map中不存在,新增一个listmap.put(param.getGroupId(),newArrayList<>());}map.get(param.getGroupId()).add(param);}//填充param到groupfor(SpecGroupspecGroup:specGroups){specGroup.setParams(map.get(specGroup.getId()));}returnspecGroups;}

页面静态化

• 我们的页面是通过Thymeleaf模板引擎渲染后返回到客户端。在后台需要大量的数据查询,而后渲染得到HTML页面。会对数据库造成压力,并且请求的响应时间过长,并发能力不高。

• 什么是静态化

静态化是指把动态生成的HTML页面变为静态内容保存,以后用户的请求到来,直接访问静态页面,不再经过服务的渲染。

而静态的HTML页面可以部署在nginx中,从而大大提高并发能力,减小tomcat压力。

• 如何实现静态化

•静态化页面都是通过模板引擎来生成,而后保存到nginx服务器来部署。Thymeleaf除了可以把渲染结果写入Response,也可以写到本地文件,从而实现静态化。•通过TemplateEngine解析模板引擎templateEngine.process("模板名", context, writer);三个参数:模板名称,上下文:里面包含模型数据,writer:输出目的地的流输出时,我们可以指定输出的目的地,如果目的地是Response的流,那就是网络响应。如果目的地是本地文件,那就实现静态化了。

• pageController

@Controllerpublic class PageController{@Autowiredprivate PageService pageService;@GetMapping("item/{id}.html")public String toItemPage(@PathVariable("id")Long spuId,Model model){//查询模型数据Map<String,Object> attributes = pageService.loadModel(spuId);//准备模型数据model.addAllAttributes(attributes);//返回视图return"item";}}•pageService@Slf4j@Servicepublic class PageService{@Autowiredprivate BrandClient brandClient;@AutowiredprivateCategoryClientcategoryClient;@AutowiredprivateSpecifictionClientspecClient;@AutowiredprivateGoodsClientgoodsClient;@AutowiredprivateTemplateEnginetemplateEngine;/***加载模型*@paramspuId*@return*/public Map<String,Object> loadModel(Long spuId){Map<String,Object> model = new HashMap<>();//查询spuSpu spu=goodsClient.querySpuById(spuId);//查询skusList<Sku> skus =spu.getSkus();//查询detailSpuDetail detail=spu.getSpuDetail();//查询brandBrand brand=brandClient.queryBrandById(spu.getBrandId());//查询categoriesList<Category>categories=categoryClient.queryCategoryByIds(Arrays.asList(spu.getCid1(),spu.getCid2(),spu.getCid3()));//查询specsList<SpecGroup> specs=specClient.queryListByCid(spu.getCid3());model.put("title",spu.getTitle());model.put("subTitle",spu.getSubTitle());model.put("skus",skus);model.put("detail",detail);model.put("brand",brand);model.put("categories",categories);model.put("specs",specs);return model;}/***创建静态页面*@paramspuId*/public void createHtml(LongspuId){//创建上下文,Contextcontext=newContext();//把数据加入上下文context.setVariables(loadModel(spuId));//创建输出流,关联到一个临时文件Filedest=new File("D:\\MY_IDEA\\upload",spuId+".html");try(PrintWriter writer=new PrintWriter(dest,"UTF-8")){//利用thymeleaf模板引擎生成静态页面templateEngine.process("item",context,writer);}catch(Exceptione){log.error("[静态页服务]生成静态页异常");}}}•PageServiceTest 现在只能通过test来生成静态文件@RunWith(SpringRunner.class)@SpringBootTestpublic class PageServiceTest{@Autowiredprivate PageService pageService;@Testpublic void createHtml(){pageService.createHtml(141L);}}

• 因为nginx在虚拟机里面,所以手动把物理机生成的静态页面复制到虚拟机目录(nginx/html/item)下

修改nginx.conflocation /item {# 先找本地root html;if (!-f $request_filename) { #请求的文件不存在,就反向代理proxy_pass http://192.168.0.6:8084;break;}}

消息队列

搜索与商品服务存在的问题

• 商品的原始数据保存在数据库中,增删改查都在数据库中完成。

• 搜索服务数据来源是索引库,如果数据库商品发生变化,索引库数据不能及时更新。

• 商品详情做了页面静态化,静态页面数据也不会随着数据库商品发生变化。

如果我们在后台修改了商品的价格,搜索页面和商品详情页显示的依然是旧的价格,这样显然不对。该如何解决?

• 通过另外一种方式来解决这个问题:消息队列什么是消息队列

消息队列,即MQ,Message Queue。

• 消息队列是典型的:生产者、消费者模型。生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息。因为消息的生产和消费都是异步的,而且只关心消息的发送和接收,没有业务逻辑的侵入,这样就实现了生产者和消费者的解耦。

• 现在实现MQ的有两种主流方式:AMQP、JMS。

两者间的区别和联系:

• JMS是定义了统一的接口,来对消息操作进行统一;AMQP是通过规定协议来统一数据交互的格式

• JMS限定了必须使用Java语言;AMQP只是协议,不规定实现方式,因此是跨语言的。

• JMS规定了两种消息模型;而AMQP的消息模型更加丰富

• 常见产品

• ActiveMQ:基于JMS

• RabbitMQ:基于AMQP协议,erlang语言开发,稳定性好

• RocketMQ:基于JMS,阿里巴巴产品,目前交由Apache基金会

• Kafka:分布式消息系统,高吞吐量安装RabbitMQ

• 安装erlang

$ sudo yum install epel-release -y$ yum install erlang -y

• 安装ribbitmq

rpm -ivh rabbitmq-server-3.4.1-1.noarch.rpm

• 修改配置文件

cp /usr/share/doc/rabbitmq-server-3.4.1/rabbitmq.config.example /etc/rabbitmq/rabbitmq.configvim /etc/rabbitmq/rabbitmq.config

• 启动rabbitmq出错

启动rabbitMQ出错解决方法

systemctl stop firewalldsystemctl disable firewalld vim /etc/selinux/config修改SELINUX=disabled然后重启虚拟机

• 开启web管理界面

rabbitmq-plugins enable rabbitmq_management

• 重启rabbitmq

service rabbitmq-server restart

• 访问

在主机中通过地址:http://192.168.163.128:15672即可访问到管理界面默认账号/密码:guest/guest添加了一个用户leyou/leyou

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。