当前位置: 首页 > news >正文

尚品汇-ES(三十一)

目录:

(1)封装搜索相关实体对象

(2)搜索接口封装

(3)在service-list-client模块添加远程接口

(1)封装搜索相关实体对象

搜索参数实体:SearchParam

搜索参数实体:SearchParam
package com.atguigu.gmall.model.list;
/*** 商品搜索参数* 参数说明:*      1,商标品牌:trademark=2:华为  *              2:为品牌id,搜索字段*              华为:品牌名称,页面回显属性*      2,平台属性:props=23:4G:运行内存*              23:平台属性id,搜索字段*              运行内存:平台属性名称,页面回显属性*              4G:平台属性值,搜索字段与页面回显属性* </p>**/
@Data
public class SearchParam {// ?category3Id=61&trademark=2:华为&props=23:4G:运行内存&order=1:desc//category3Id=61private Long category1Id;;//三级分类idprivate Long category2Id;private Long category3Id;//trademark=2:华为private String trademark;//品牌idprivate String keyword;//检索的关键字// order=1:asc  排序规则   0:ascprivate String order = "";// 1:综合排序/热点  2:价格//props=23:4G:运行内存private String[] props;//页面提交的数组private Integer pageNo = 1;//分页信息private Integer pageSize = 12;
}

 搜索结果集实体:SearchResponseVo

搜索结果集实体:SearchResponseVopackage com.atguigu.gmall.model.list;@Data
public class SearchResponseVo implements Serializable {//品牌 此时vo对象中的id字段保留(不用写) name就是“品牌” value: [{id:100,name:华为,logo:xxx},{id:101,name:小米,log:yyy}]private List<SearchResponseTmVo> trademarkList;//所有商品的顶头显示的筛选属性private List<SearchResponseAttrVo> attrsList = new ArrayList<>();//检索出来的商品信息private List<Goods> goodsList = new ArrayList<>();private Long total;//总记录数private Integer pageSize;//每页显示的内容private Integer pageNo;//当前页面private Long totalPages;}

结果集品牌实体:SearchResponseTmVo

package com.atguigu.gmall.model.list;@Data
public class SearchResponseTmVo implements Serializable {//当前属性值的所有值private Long tmId;//属性名称private String tmName;//网络制式,分类//图片urlprivate String tmLogoUrl;
}

结果集平台属性实体:SearchResponseAttrVo

package com.atguigu.gmall.model.list;@Data
public class SearchResponseAttrVo implements Serializable {private Long attrId;//1//当前属性值的所有值private List<String> attrValueList = new ArrayList<>();//属性名称private String attrName;//网络制式,分类
}

(2)搜索接口封装

SearchService接口

/*** 搜索列表* @param searchParam* @return* @throws IOException*/
SearchResponseVo search(SearchParam searchParam) throws IOException;

接口实现类

api参考文档:

Java REST Client [7.8] | Elastic

Java REST Client [7.8] | Elastic

@Autowired
private RestHighLevelClient restHighLevelClient;
@Override
public SearchResponseVo search(SearchParam searchParam) throws IOException {// 构建dsl语句SearchRequest searchRequest = this.buildQueryDsl(searchParam);SearchResponse response = this.restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);System.out.println(response);SearchResponseVo responseVO = this.parseSearchResult(response);responseVO.setPageSize(searchParam.getPageSize());responseVO.setPageNo(searchParam.getPageNo());long totalPages = (responseVO.getTotal()+searchParam.getPageSize()-1)/searchParam.getPageSize();responseVO.setTotalPages(totalPages);return responseVO;
}//封装查询条件
// 制作dsl 语句  
private SearchRequest buildQueryDsl(SearchParam searchParam) {// 构建查询器SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();// 构建多条件对象boolQueryBuilderBoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();// 判断查询条件是否为空 关键字if (!StringUtils.isEmpty(searchParam.getKeyword())){// 小米手机  小米and手机// MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("title",searchParam.getKeyword()).operator(Operator.AND);MatchQueryBuilder title = QueryBuilders.matchQuery("title", searchParam.getKeyword()).operator(Operator.AND);boolQueryBuilder.must(title);}// 构建品牌查询String trademark = searchParam.getTrademark();if (!StringUtils.isEmpty(trademark)){// trademark=2:华为String[] split = StringUtils.split(trademark, ":");if (split != null && split.length == 2) {//构建过滤品牌TermQueryBuilder tmId=QueryBuilders.termQuery("tmId", split[0]);// 根据品牌Id过滤  添加到多条件对象boolQueryBuilder.filter(tmId);}}// 构建分类过滤 用户在点击的时候,只能点击一个值,所以此处使用termif(null!=searchParam.getCategory1Id()){boolQueryBuilder.filter(QueryBuilders.termQuery("category1Id",searchParam.getCategory1Id()));}// 构建分类过滤if(null!=searchParam.getCategory2Id()){boolQueryBuilder.filter(QueryBuilders.termQuery("category2Id",searchParam.getCategory2Id()));}// 构建分类过滤if(null!=searchParam.getCategory3Id()){boolQueryBuilder.filter(QueryBuilders.termQuery("category3Id",searchParam.getCategory3Id()));}// 构建平台属性查询// 23:4G:运行内存String[] props = searchParam.getProps();if (props!=null && props.length>0){// 循环遍历for (String prop : props) {// 23:4G:运行内存  平台属性id:平台属性值名称:平台属性名String[] split = StringUtils.split(prop, ":");if (split!=null && split.length==3){// 构建嵌套查询  创建多条件对象BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();// 嵌套查询子查询BoolQueryBuilder subBoolQuery = QueryBuilders.boolQuery();// 构建子查==询中的过滤条件subBoolQuery.must(QueryBuilders.termQuery("attrs.attrId",split[0]));subBoolQuery.must(QueryBuilders.termQuery("attrs.attrValue",split[1]));// ScoreMode.None ?boolQuery.must(QueryBuilders.nestedQuery("attrs",subBoolQuery, ScoreMode.None));// 添加到整个过滤对象中,外层对象boolQueryBuilder.filter(boolQuery);}}}// 执行查询方法searchSourceBuilder.query(boolQueryBuilder);// 构建分页int from = (searchParam.getPageNo()-1)*searchParam.getPageSize();searchSourceBuilder.from(from);searchSourceBuilder.size(searchParam.getPageSize());// 排序  1:hotScore 2:price   1:综合排序/热度  2:价格//1:ascString order = searchParam.getOrder();if (!StringUtils.isEmpty(order)){// 判断排序规则String[] split = StringUtils.split(order, ":");if (split!=null && split.length==2){// 排序的字段String field = null;// 数组中的第一个参数switch (split[0]){case "1":field="hotScore";break;case "2":field="price";break;}searchSourceBuilder.sort(field,"asc".equals(split[1])? SortOrder.ASC:SortOrder.DESC);}else {// 没有传值的时候给默认值searchSourceBuilder.sort("hotScore",SortOrder.DESC);}}// 构建高亮HighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.field("title");highlightBuilder.postTags("</span>");highlightBuilder.preTags("<span style=color:red>");searchSourceBuilder.highlighter(highlightBuilder);//  设置品牌聚合TermsAggregationBuilder termsAggregationBuilder =        AggregationBuilders.terms("tmIdAgg").field("tmId").subAggregation(AggregationBuilders.terms("tmNameAgg").field("tmName")).subAggregation(AggregationBuilders.terms("tmLogoUrlAgg").field("tmLogoUrl"));searchSourceBuilder.aggregation(termsAggregationBuilder);//  设置平台属性聚合searchSourceBuilder.aggregation(AggregationBuilders.nested("attrAgg", "attrs").subAggregation(AggregationBuilders.terms("attrIdAgg").field("attrs.attrId").subAggregation(AggregationBuilders.terms("attrNameAgg").field("attrs.attrName")).subAggregation(AggregationBuilders.terms("attrValueAgg").field("attrs.attrValue"))));// 结果集过滤searchSourceBuilder.fetchSource(new String[]{"id","defaultImg","title","price"},null);SearchRequest searchRequest = new SearchRequest("goods");//searchRequest.types("_doc");//将构建对象添加到请求中searchRequest.source(searchSourceBuilder);System.out.println("dsl:"+searchSourceBuilder.toString());return searchRequest;
}// 制作返回结果集
private SearchResponseVo parseSearchResult(SearchResponse response) {SearchHits hits = response.getHits();//声明对象SearchResponseVo searchResponseVo = new SearchResponseVo();//获取品牌的集合Map<String, Aggregation> aggregationMap = response.getAggregations().asMap();//ParsedLongTerms ?ParsedLongTerms tmIdAgg = (ParsedLongTerms) aggregationMap.get("tmIdAgg");List<SearchResponseTmVo> trademarkList = tmIdAgg.getBuckets().stream().map(bucket -> {SearchResponseTmVo trademark = new SearchResponseTmVo();//获取品牌Idtrademark.setTmId((Long.parseLong(((Terms.Bucket) bucket).getKeyAsString())));//trademark.setTmId(Long.parseLong(bucket.getKeyAsString()));//获取品牌名称Map<String, Aggregation> tmIdSubMap = ((Terms.Bucket) bucket).getAggregations().asMap();ParsedStringTerms tmNameAgg = (ParsedStringTerms) tmIdSubMap.get("tmNameAgg");String tmName = tmNameAgg.getBuckets().get(0).getKeyAsString();trademark.setTmName(tmName);
ParsedStringTerms tmLogoUrlAgg = (ParsedStringTerms) tmIdSubMap.get("tmLogoUrlAgg");
String tmLogoUrl = tmLogoUrlAgg.getBuckets().get(0).getKeyAsString();
trademark.setTmLogoUrl(tmLogoUrl);return trademark;}).collect(Collectors.toList());searchResponseVo.setTrademarkList(trademarkList);//赋值商品列表SearchHit[] subHits = hits.getHits();List<Goods> goodsList = new ArrayList<>();if (subHits!=null && subHits.length>0){//循环遍历for (SearchHit subHit : subHits) {// 将subHit 转换为对象Goods goods = JSONObject.parseObject(subHit.getSourceAsString(), Goods.class);//获取高亮if (subHit.getHighlightFields().get("title")!=null){Text title = subHit.getHighlightFields().get("title").getFragments()[0];goods.setTitle(title.toString());}goodsList.add(goods);}}searchResponseVo.setGoodsList(goodsList);//获取平台属性数据ParsedNested attrAgg = (ParsedNested) aggregationMap.get("attrAgg");ParsedLongTerms attrIdAgg = attrAgg.getAggregations().get("attrIdAgg");List<? extends Terms.Bucket> buckets = attrIdAgg.getBuckets();if (!CollectionUtils.isEmpty(buckets)){List<SearchResponseAttrVo> searchResponseAttrVOS = buckets.stream().map(bucket -> {//声明平台属性对象SearchResponseAttrVo responseAttrVO = new SearchResponseAttrVo();//设置平台属性值IdresponseAttrVO.setAttrId(((Terms.Bucket) bucket).getKeyAsNumber().longValue());ParsedStringTerms attrNameAgg = bucket.getAggregations().get("attrNameAgg");List<? extends Terms.Bucket> nameBuckets = attrNameAgg.getBuckets();responseAttrVO.setAttrName(nameBuckets.get(0).getKeyAsString());//设置规格参数列表ParsedStringTerms attrValueAgg = ((Terms.Bucket) bucket).getAggregations().get("attrValueAgg");List<? extends Terms.Bucket> valueBuckets = attrValueAgg.getBuckets();List<String> values = valueBuckets.stream().map(Terms.Bucket::getKeyAsString).collect(Collectors.toList());responseAttrVO.setAttrValueList(values);return responseAttrVO;}).collect(Collectors.toList());searchResponseVo.setAttrsList(searchResponseAttrVOS);}// 获取总记录数searchResponseVo.setTotal(hits.getTotalHits().value);return searchResponseVo;
}

 

 

控制器ListApiController

/*** 搜索商品* @param searchParam* @return* @throws IOException*/
@PostMapping
public Result list(@RequestBody SearchParam searchParam) throws IOException {SearchResponseVo response = searchService.search(searchParam);return Result.ok(response);
}

在service-list 模块中配置logstash

首先在service模块中添加依赖

<dependency>

            <groupId>net.logstash.logback</groupId>

            <artifactId>logstash-logback-encoder</artifactId>

            <version>5.1</version>

        </dependency>

其次,将日志配置文件放入到resources目录下!

(3)在service-list-client模块添加远程接口

package com.atguigu.gmall.list.client;
@FeignClient(value = "service-list", fallback = ListDegradeFeignClient.class)
public interface ListFeignClient {/*** 搜索商品* @param listParam* @return*/@PostMapping("/api/list")Result list(@RequestBody SearchParam listParam);/*** 上架商品* @param skuId* @return*/@GetMapping("/api/list/inner/upperGoods/{skuId}")Result upperGoods(@PathVariable("skuId") Long skuId);/*** 下架商品* @param skuId* @return*/@GetMapping("/api/list/inner/lowerGoods/{skuId}")Result lowerGoods(@PathVariable("skuId") Long skuId);}
package com.atguigu.gmall.list.client.impl;@Component
public class ListDegradeFeignClient implements ListFeignClient {@Overridepublic Result list(SearchParam searchParam) {return Result.fail();}@Overridepublic Result upperGoods(Long skuId) {return null;}@Overridepublic Result lowerGoods(Long skuId) {return null;}
}

相关文章:

尚品汇-ES(三十一)

目录&#xff1a; &#xff08;1&#xff09;封装搜索相关实体对象 &#xff08;2&#xff09;搜索接口封装 &#xff08;3&#xff09;在service-list-client模块添加远程接口 &#xff08;1&#xff09;封装搜索相关实体对象 搜索参数实体&#xff1a;SearchParam 搜索参…...

NC 跳台阶

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 一只青蛙一次…...

linux 文件编程

1. 标准IO 也称为标准输入输出&#xff08;Standard Input/Output&#xff09;&#xff0c;是计算机编程中一种常见的IO操作方式&#xff0c;特别是在C语言及其衍生语言中广泛使用。它主要通过标准C库中的函数来实现&#xff0c;提供了丰富的接口用于数据的输入和输出。 文本文…...

【后端速成 Vue】实现动态表白墙

前言&#xff1a; 通过前面几篇的文章的讲解&#xff0c;已经学习到了很多的 Vue 指令了&#xff0c;那么现在就将学习到的指令利用起来&#xff0c;做一个小的 demo。 最终效果图&#xff1a; 通过效果图可以发现&#xff0c;一共有这几个功能&#xff1a; ● 渲染列表&…...

【日常开发】 java返回ECharts数据结构封装

java返回ECharts数据结构封装 一、前端页面示例图如下&#xff1a; 二、准备测试数据&#xff1a; 三、后端 格式封装代码&#xff1a; 四、最终结果&#xff1a; &#x1f388;边走、边悟&#x1f388;迟早会好 一、前端页面示例图如下&#xff1a; 二、准备测试数据&am…...

Table表格控件实现单选功能

Table表格控件实现单选功能 <el-tableref"tableRef"height"385"style"--el-table-border-color: none"row-key"contractId"highlight-current-rowsingle-selectselect"handleSelect":data"contractInfo">&l…...

AI技术加速落地 港科广联手思谋打开智能缺陷检测新纪元

AI 技术应用落地的元年&#xff0c;工业是主战场&#xff0c;尤其是工业缺陷检测。 在“生产制造-缺陷检测-工艺优化-生产制造”的智能制造闭环链条中&#xff0c;基于AI的智能缺陷检测扮演着“把关者”的角色。但这个把关者长期以来却缺少一个称手的工具——样本量大、精度高…...

Python爬虫开发:BeautifulSoup、Scrapy入门

在现代网络开发中&#xff0c;网络爬虫是一个非常重要的工具。它可以自动化地从网页中提取数据&#xff0c;并且可以用于各种用途&#xff0c;如数据收集、信息聚合和内容监控等。在Python中&#xff0c;有多个库可以用于爬虫开发&#xff0c;其中BeautifulSoup和Scrapy是两个非…...

数据科学、数据分析、人工智能必备知识汇总-----常用数据分析方法-----持续更新

数据科学、数据分析、人工智能必备知识汇总-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/140174015 文章目录 一、对比分析法1. 按时间和地区2. 同比和环比 二、分组分析法三、结构分析法四、交叉分析法五、矩阵分…...

学习vue Router 一 起步,编程式导航,历史记录,路由传参

目录 起步&#xff0c;安装 1. 安装 2. 使用 命名路由 编程式导航 1. 字符串模式 2. 对象模式 3. 命名路由模式 历史记录 replace的使用 横跨历史 路由传参 1. query路由传参 2. 动态路由传参 3. 二者的区别 起步&#xff0c;安装 router 路由 因为vue是单页应用…...

Qt/C++最新地图组件发布/历时半年重构/同时支持各种地图内核/包括百度高德腾讯天地图

一、前言说明 最近花了半年时间&#xff0c;专门重构了整个地图组件&#xff0c;之前写的比较粗糙&#xff0c;有点为了完成功能而做的&#xff0c;没有考虑太多拓展性和易用性。这套地图自检这几年大量的实际项目和用户使用下来&#xff0c;反馈了不少很好的建议和意见&#…...

Laravel + Thinkphp 生成二维码

安装依赖 composer require endroid/qr-code 编写ThinkPhP代码 public function index() {// 创建二维码内容$qrCode new QrCode(Hello World);// 设置二维码的配置$qrCode->setSize(300);$qrCode->setMargin(10);// 获取二维码图像$writer new PngWriter();$result…...

2408C++,C++20的无侵入式反射

原文 C17基于结构绑定的编译期反射 事实上不需要宏的编译期反射在C17中已用得很多了,比如struct_pack的编译期反射就不需要宏,因为C17结构绑定可直接得到一个聚集类的成员的引用. struct person {int id;std::string name;int age; }; int main() {person p{1, "tom&qu…...

抽象工厂模式(Abstract factory pattern)- python实现

抽象工厂模式的通俗示例 想象一下&#xff0c;你正在经营一家家具店&#xff0c;你需要从不同的供应商那里采购不同的家具系列。有的供应商提供的是现代风格家具&#xff0c;包括现代沙发、现代椅子和现代桌子&#xff1b;而有的供应商提供的是古典风格家具&#xff0c;包括古…...

adb Connection reset by peer的解决方法

本文同步发于&#xff1a;https://www.cnblogs.com/yeshen-org/p/18350232 最近在编译一个老项目&#xff0c;项目中依赖了很多第三方库&#xff0c;用gradle编译要20-30分钟&#xff0c;而且内存开销很大。 公司配的15G内存的电脑&#xff0c;一次编译能用到14G。 编译的时候&…...

111111111

1111111111111111111...

搜维尔科技:Varjo XR-4使用UE5 打造最具沉浸感的混合现实环境

Varjo XR-4使用UE5打造最具沉浸感的混合现实环境 搜维尔科技&#xff1a;Varjo XR-4使用UE5 打造最具沉浸感的混合现实环境...

从分散到集中:TSINGSEE青犀EasyCVR视频汇聚网关在视频整体监控解决方案中的整合作用

边缘计算视频汇聚网关是基于开放式、大融合、全兼容、标准化的设计架构理念&#xff0c;依据《安全防范视频监控联网系统信息传输、交换、控制技术要求》&#xff08;GB/T28181-2011&#xff09;标准开发&#xff0c;集流媒体转发、视频编码、视频管理、标准通信协议、网络穿透…...

React学习-jsx语法

jsx语法&#xff0c;浏览器不认识&#xff0c;需要经过babel编译 https://babeljs.io/ 面试题&#xff1a;jsx的作用&#xff1f; 普通回答&#xff1a;可以在js中返回dom&#xff0c;经过babel编译成js认识的代码import { jsx as _jsx, jsxs as _jsxs } from "react/j…...

uniapp多图上传uni.chooseImage上传照片uni.uploadFile

uniapp多图上传uni.chooseImage上传照片uni.uploadFile 代码示例&#xff1a; /**上传照片 多图*/getImage() {uni.chooseImage({count: 9, //默认9sizeType: [original, compressed], //可以指定是原图还是压缩图&#xff0c;默认二者都有sourceType: [album], //从相册选择/…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

python打卡第47天

昨天代码中注意力热图的部分顺移至今天 知识点回顾&#xff1a; 热力图 作业&#xff1a;对比不同卷积层热图可视化的结果 def visualize_attention_map(model, test_loader, device, class_names, num_samples3):"""可视化模型的注意力热力图&#xff0c;展示模…...