天机学堂3-ES+Caffeine

news2025/3/1 0:18:11

文章目录

  • day05-问答系统
  • 用户端分页查询问题
    • 目标效果
    • 代码实现
  • 3.6.管理端分页查询问题
      • ES相关
    • 管理端互动问题分页实现
    • 三级分类
      • 3.6.5.2.多级缓存
      • 3.6.5.3.Caffeine
  • 4.评论相关接口
    • 目标效果
    • 新增回答或评论

day05-问答系统

效果:
在这里插入图片描述

互动提问的问题表:

CREATE TABLE IF NOT EXISTS `interaction_question` (
  `id` bigint NOT NULL COMMENT '主键,互动问题的id',
  `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '互动问题的标题',
  `description` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '问题描述信息',
  `course_id` bigint NOT NULL COMMENT '所属课程id',
  `chapter_id` bigint NOT NULL COMMENT '所属课程章id',
  `section_id` bigint NOT NULL COMMENT '所属课程节id',
  `user_id` bigint NOT NULL COMMENT '提问学员id',
  `latest_answer_id` bigint DEFAULT NULL COMMENT '最新的一个回答的id',
  `answer_times` int unsigned NOT NULL DEFAULT '0' COMMENT '问题下的回答数量',
  `anonymity` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否匿名,默认false',
  `hidden` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否被隐藏,默认false',
  `status` tinyint DEFAULT '0' COMMENT '管理端问题状态:0-未查看,1-已查看',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '提问时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_course_id` (`course_id`) USING BTREE,
  KEY `section_id` (`section_id`),
  KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='互动提问的问题表';

回答或评论表:

CREATE TABLE IF NOT EXISTS `interaction_reply` (
  `id` bigint NOT NULL COMMENT '互动问题的回答id',
  `question_id` bigint NOT NULL COMMENT '互动问题问题id',
  `answer_id` bigint DEFAULT '0' COMMENT '回复的上级回答id',
  `user_id` bigint NOT NULL COMMENT '回答者id',
  `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '回答内容',
  `target_user_id` bigint DEFAULT '0' COMMENT '回复的目标用户id',
  `target_reply_id` bigint DEFAULT '0' COMMENT '回复的目标回复id',
  `reply_times` int NOT NULL DEFAULT '0' COMMENT '评论数量',
  `liked_times` int NOT NULL DEFAULT '0' COMMENT '点赞数量',
  `hidden` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否被隐藏,默认false',
  `anonymity` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否匿名,默认false',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_question_id` (`question_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='互动问题的回答或评论';

KEY 关键字用于定义索引,而 USING BTREE 是一个可选的子句,用于显式指定索引的存储类型。如果不指定 USING BTREE,MySQL 会默认使用 B-Tree 索引结构

用户端分页查询问题

目标效果

在这里插入图片描述

代码实现

在这里插入图片描述

3.6.管理端分页查询问题

ES相关

Feign接口

package com.tianji.api.client.search;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@FeignClient("search-service")
public interface SearchClient {

    @GetMapping("/courses/name")
    List<Long> queryCoursesIdByName(
            @RequestParam(value = "keyword", required = false) String keyword);
}

Controller:

package com.tianji.search.controller;

import com.tianji.common.domain.dto.PageDTO;
import com.tianji.search.domain.query.CoursePageQuery;
import com.tianji.search.domain.vo.CourseVO;
import com.tianji.search.service.ICourseService;
import com.tianji.search.service.ISearchService;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;


@RestController
@RequestMapping("courses")
@Api(tags = "课程搜索接口")
@RequiredArgsConstructor
public class CourseController {

    private final ISearchService searchService;
    private final ICourseService courseService;

    @ApiOperation("用户端课程搜索接口")
    @GetMapping("/portal")
    public PageDTO<CourseVO> queryCoursesForPortal(CoursePageQuery query){
        return searchService.queryCoursesForPortal(query);
    }

    @ApiIgnore
    @GetMapping("/name")
    public List<Long> queryCoursesIdByName(@RequestParam("keyword") String keyword){
        return searchService.queryCoursesIdByName(keyword);
    }

在这里插入图片描述

管理端互动问题分页实现

管理端互动问题分页: Admin可以通过关键字搜索课程,但由于问题表中没有课程名称字段,所以通过
课程ID获取课程名字,课程ID可以从Feign获取
QuestionAdminPageQuery.getCourseName是课程名称的关键字
课程ID可以从Feign获取:接受课程关键字,搜ES

public PageDTO<QuestionAdminVO> getInterationQuestionByAdminPage(QuestionAdminPageQuery pageQuery) {
        // 如果用户传了课程名称参数,则从es中获取该名称对应的课程id
        List<Long> courseIdList = null;
        if (StringUtils.isNotBlank(pageQuery.getCourseName())) {
            // feign远程调用,从es中获取该名称对应的课程id
            courseIdList = searchClient.queryCoursesIdByName(pageQuery.getCourseName());
            // 判断查询结果是否为空
            if (CollUtil.isEmpty(courseIdList)) {
                return PageDTO.empty(0L, 0L);
            }
        }
        // 查询互动问题表
        Page<InteractionQuestion> questionPage = lambdaQuery()
                .eq(pageQuery.getStatus() != null, InteractionQuestion::getStatus, pageQuery.getStatus())
                .ge(pageQuery.getBeginTime() != null, InteractionQuestion::getCreateTime, pageQuery.getBeginTime())
                .le(pageQuery.getEndTime() != null, InteractionQuestion::getCreateTime, pageQuery.getEndTime())
                .in(!CollUtil.isEmpty(courseIdList), InteractionQuestion::getCourseId, courseIdList)   // 实现课程名称模糊查询
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());
        // 查询到的列表为空,则返回空集
        List<InteractionQuestion> records = questionPage.getRecords();
        if (CollUtil.isEmpty(records)) {
            return PageDTO.of(questionPage, Collections.emptyList());
        }
        // 这里用for循环而不是Stream流,减少循环次数
        Set<Long> userIds = new HashSet<>();
        Set<Long> courseIds = new HashSet<>();
        Set<Long> chapterAndSections = new HashSet<>();
        for (InteractionQuestion question : records) {
            userIds.add(question.getUserId());
            courseIds.add(question.getCourseId());
            chapterAndSections.add(question.getChapterId());
            chapterAndSections.add(question.getSectionId());
        }
        // feign远程调用用户服务,获取用户信息
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        if (CollUtil.isEmpty(userDTOS)) {
            throw new BizIllegalException("用户不存在");
        }
        Map<Long, UserDTO> userMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, userDTO -> userDTO));
        // feign远程调用课程服务,获取课程信息
        List<CourseSimpleInfoDTO> courseDTOs = courseClient.getSimpleInfoList(courseIds);
        if (CollUtil.isEmpty(courseDTOs)) {
            throw new BizIllegalException("课程不存在");
        }
        Map<Long, CourseSimpleInfoDTO> courseMap = courseDTOs.stream()
                .collect(Collectors.toMap(CourseSimpleInfoDTO::getId, courseDTO -> courseDTO));
        // feign远程调用课程服务,获取章节信息
        List<CataSimpleInfoDTO> catalogueDTOs = catalogueClient.batchQueryCatalogue(chapterAndSections);
        if (CollUtil.isEmpty(catalogueDTOs)) {
            throw new BizIllegalException("章节不存在");
        }
        // 封装为章节id,章节名称(需要根据章节id赋值章节名称)
        Map<Long, String> catalogueMap = catalogueDTOs.stream()
                .collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        // 封装VO并返回
        List<QuestionAdminVO> voList = new ArrayList<>();
        for (InteractionQuestion record : records) {
            QuestionAdminVO questionAdminVO = BeanUtils.copyBean(record, QuestionAdminVO.class);
            UserDTO userDTO = userMap.get(record.getUserId());
            if (userDTO != null) {
                questionAdminVO.setUserName(userDTO.getName());  // 用户昵称
            }
            CourseSimpleInfoDTO courseDTO = courseMap.get(record.getCourseId());
            if (courseDTO != null) {
                questionAdminVO.setCourseName(courseDTO.getName());    // 课程名称
                // 获取课程的三级分类id,根据三级分类id拼接分类名称
                String categoryName = categoryCache.getCategoryNames(courseDTO.getCategoryIds());
                questionAdminVO.setCategoryName(categoryName);  // 课程所述分类名称
            }
            // 使用getOrDefault防止异常
            questionAdminVO.setChapterName(catalogueMap.getOrDefault(record.getChapterId(), ""));   // 章节名称
            questionAdminVO.setSectionName(catalogueMap.getOrDefault(record.getSectionId(), ""));   // 小节名称
            voList.add(questionAdminVO);
        }
        return PageDTO.of(questionPage, voList);
    }

三级分类

在这里插入图片描述
表里设置parent_id代表上级是谁
在这里插入图片描述
都是IT-互联网下面的二级分类(红框里的)
因为分类信息的改动量比较小,一般都不会动了,所以就缓存起来

  • 课程分类数据在很多业务中都需要查询,这样的数据如此频繁的查询,有没有性能优化的办法呢?

3.6.5.2.多级缓存

相信很多同学都能想到借助于Redis缓存来提高性能,减少数据库压力。非常好!不过,Redis虽然能提高性能,但每次查询缓存还是会增加网络带宽消耗,也会存在网络延迟。

而分类数据具备两大特点:

  • 数据量小
  • 长时间不会发生变化。

像这样的数据,除了建立Redis缓存以外,还非常适合做本地缓存(Local Cache)。这样就可以形成多级缓存机制:

  • 数据查询时优先查询本地缓存
  • 本地缓存不存在,再查询Redis缓存
  • Redis不存在,再去查询数据库。

本地缓存简单来说就是JVM内存的缓存,比如你建立一个HashMap,把数据库查询的数据存入进去。以后优先从这个HashMap查询,一个本地缓存就建立好了。

3.6.5.3.Caffeine

当然,我们真正创建本地缓存的时候并不是直接使用HashMap之类的集合,因为维护起来不太方便。而且内存淘汰机制实现起来也比较麻烦。
所以,我们会使用成熟的框架来完成,比如Caffeine:
Caffeine是一个基于Java8开发的,提供了近乎最佳命中率的高性能的本地缓存库。目前Spring内部的缓存使用的就是Caffeine。
在这里插入图片描述
在这里插入图片描述
第二次get就不会执行了

Caffeine提供了三种缓存驱逐策略:

  • 基于容量:设置缓存的数量上限
// 创建缓存对象
Cache<String, String> cache = Caffeine.newBuilder()
    .maximumSize(1) // 设置缓存大小上限为 1
    .build();
  • 基于时间:设置缓存的有效时间
// 创建缓存对象
Cache<String, String> cache = Caffeine.newBuilder()
    // 设置缓存有效期为 10 秒,从最后一次写入开始计时 
    .expireAfterWrite(Duration.ofSeconds(10)) 
    .build();
Caffeine.newBuilder()
        .initialCapacity(1) // 初始容量 缓存初始化时会分配足够的内存来存储1个键值对。
        .maximumSize(10_000) // 最大容量 缓存最多可以存储10,000个键值对。
        .expireAfterWrite(Duration.ofMinutes(30)) // 指定了缓存项在写入后多长时间过期。Duration.ofMinutes(30)是一个静态方法,用于创建一个表示30分钟的时间持续对象
        .build();

和上面明星例子一样,如果缓存没有则远程调用获取放到缓存中 下次30分钟查 直接返回【一级分类id、二级分类id、三级分类id】:

public Map<Long, CategoryBasicDTO> getCategoryMap() {
    return categoryCaches.get("CATEGORY", key -> {
        // 1.从CategoryClient查询
        List<CategoryBasicDTO> list = categoryClient.getAllOfOneLevel();
        if (list == null || list.isEmpty()) {
            return CollUtils.emptyMap();
        }
        return list.stream().collect(Collectors.toMap(CategoryBasicDTO::getId, Function.identity()));
    });
}

拼接三级分类名称,用/分隔:

 /**
     * 根据三级分类id拼接三级分类名称
     * @param ids   一级分类id、二级分类id、三级分类id
     * @return  拼接三级分类名称,用/分隔
     */
    public String getCategoryNames(List<Long> ids) {
        if (ids == null || ids.size() == 0) {
            return "";
        }
        // 1.读取分类缓存
        Map<Long, CategoryBasicDTO> map = getCategoryMap();
        // 2.根据id查询分类名称并组装
        StringBuilder sb = new StringBuilder();
        for (Long id : ids) {
            sb.append(map.get(id).getName()).append("/");
        }
        // 3.返回结果
        return sb.deleteCharAt(sb.length() - 1).toString();
    }

调用:

questionAdminVO.setCourseName(courseDTO.getName());    // 课程名称
// 获取课程的三级分类id,根据三级分类id拼接分类名称
String categoryName = categoryCache.getCategoryNames(courseDTO.getCategoryIds());
questionAdminVO.setCategoryName(categoryName);  // 课程所述分类名称

启动缓存生效这一系列流程:

在这里插入图片描述

Feign客户端的实现类是由Feign在运行时动态生成的,你不需要手动编写实现类。只要你的项目配置正确,Feign会自动处理接口的实现,并通过HTTP请求调用远程服务。

在这里插入图片描述

4.评论相关接口

目标效果

回答
评论是 回答下面的
在这里插入图片描述

新增回答或评论

在这里插入图片描述

@Data
@ApiModel(description = "互动回答信息")
public class ReplyDTO {
    @ApiModelProperty("回答内容")
    @NotNull(message = "回答内容不能为空")
    private String content;

    @ApiModelProperty("是否匿名提问")
    private Boolean anonymity;

    @ApiModelProperty("互动问题id")
    @NotNull(message = "问题id不能为空")
    private Long questionId;

    // 该字段为null,表示是回答;否则表示评论
    @ApiModelProperty("回复的上级回答id,没有可不填")
    private Long answerId;

    @ApiModelProperty("回复的目标回复id,没有可不填")
    private Long targetReplyId;

    @ApiModelProperty("回复的目标用户id,没有可不填")
    private Long targetUserId;

    @ApiModelProperty("标记是否是学生提交的回答,默认true")
    private Boolean isStudent = true;
}
@Transactional
public void addReply(ReplyDTO replyDTO) {
    // 拷贝实体
    InteractionReply reply = BeanUtil.toBean(replyDTO, InteractionReply.class);
    if (reply.getAnswerId() == null) {   // 当前是回答的话,不需要target_user_id字段
        reply.setTargetUserId(null);
    }
    // 获取当前登录用户
    Long userId = UserContext.getUser();
    reply.setUserId(userId);
    // 保存评论或回答
    this.save(reply);
    // 查询关联的问题
    InteractionQuestion question = questionMapper.selectById(reply.getQuestionId());
    if (question == null) {
        throw new BizIllegalException("参数异常");
    }
    // 根据answerId是否为null判断是回答还是评论,如果是需要在`interaction_question`中记录最新一次回答的id
    if (reply.getAnswerId() == null) {    // answerId为null表示当前是回答
        question.setLatestAnswerId(reply.getId());  // 更新问题的最新回答id
        question.setAnswerTimes(question.getAnswerTimes() + 1);   // 该问题的回答数量+1
    } else {     // 如果是评论
        // 获取评论关联的回答
        InteractionReply interactionReply = this.getById(reply.getAnswerId());
        interactionReply.setReplyTimes(interactionReply.getReplyTimes() + 1);   // 该回答的评论数量+1
        // 更新评论关联的回答
        this.updateById(interactionReply);
    }
    // 如果是学生提交,则需要更新问题状态为未查看
    if (replyDTO.getIsStudent()) {
        question.setStatus(QuestionStatus.UN_CHECK);
    }
    // 更新问题
    questionMapper.updateById(question);
    // 发送MQ消息,新增积分
    rabbitMqHelper.send(MqConstants.Exchange.LEARNING_EXCHANGE,
            MqConstants.Key.WRITE_REPLY,
            SignInMessage.of(userId,5));    // 一个问题+5积分

}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2276979.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Docker】Docker部署多种容器

关于docker&#xff0c;Windows上使用Powershell/CMD执行指令&#xff0c;Linux系统直接使用终端执行指令。 docker安装MySQL 拉取MySQL 也可以跳过拉取步骤&#xff0c;直接run&#xff0c;这样本地容器不存在的话&#xff0c;会自动拉取最新/指定的版本。 # 默认拉取最新…

【Flink】Flink内存管理

Flink内存整体结构图&#xff1a; JobManager内存管理 JVM 进程总内存(Total Process Memory)Flink总内存(Total Flink Memory)&#xff1a;JVM进程总内存减去JVM Metaspace(元空间)和JVM Overhead(运行时开销)上图解释&#xff1a; JVM进程总内存为2G;JVM运行时开销(JVM Overh…

如何规模化实现完全自动驾驶?Mobileye提出解题“新”思路

在CES 2025上&#xff0c;Mobileye展示了端到端自动驾驶系统Mobileye Drive™&#xff0c;通过高度集成的传感器、算法和计算平台&#xff0c;可以实现自动驾驶功能的全覆盖。 Mobileye创始人兼首席执行官Amnon Shashua教授 期间&#xff0c;Mobileye创始人兼首席执行官Amnon …

Qt 5.14.2 学习记录 —— 십일 QLCDNumber、QProgressBar、QCalendarWidget

文章目录 1、QLCDNumber2、ProgressBar3、QCalendarWidget 1、QLCDNumber 写一个倒计时程序。拖一个LCD Number到界面&#xff1a; 定时器用Qt的QTimer类&#xff0c;这个类的对象会产生一个timeout信号&#xff0c;通过start方法来开启定时器&#xff0c;并且参数中设定触发ti…

简要认识JAVAWeb技术三剑客:HTMLCSSJavaScript

目录 一、web标准二、什么是HTML三、什么是CSS四、什么是JavaScript 黑马JAVAWeb飞书在线讲义地址&#xff1a; https://heuqqdmbyk.feishu.cn/wiki/LYVswfK4eigRIhkW0pvcqgH9nWd 一、web标准 Web标准也称网页标准&#xff0c;由一系列的标准组成&#xff0c;大部分由W3C&…

sosadmin相关命令

sosadmin命令 以下是本人翻译的官方文档&#xff0c;如有不对&#xff0c;还请指出&#xff0c;引用请标明出处。 原本有个对应表可以跳转的&#xff0c;但是CSDN的这个[](#)跳转好像不太一样&#xff0c;必须得用html标签&#xff0c;就懒得改了。 sosadmin help 用法 sosadm…

【C语言】字符串函数详解

文章目录 Ⅰ. strcpy -- 字符串拷贝1、函数介绍2、模拟实现 Ⅱ. strcat -- 字符串追加1、函数介绍2、模拟实现 Ⅲ. strcmp -- 字符串比较1、函数介绍2、模拟实现 Ⅳ. strncpy、strncat、strncmp -- 可限制操作长度Ⅴ. strlen -- 求字符串长度1、函数介绍2、模拟实现&#xff08…

IO进程day6

一、思维导图 二、练习题1 有一个隧道&#xff0c;长1000m&#xff0c;有一辆高铁&#xff0c;每秒100米&#xff0c;有一辆快车&#xff0c;每秒50m 要求模拟这两列火车通过隧道的场景。 #include <stdio.h> #include <unistd.h> #include <pthread.h>pthre…

手撕代码: C++实现按位序列化和反序列化

目录 1.需求 2.流程分析 3.实现过程 4.总结 1.需求 在我们正在开发的项目&#xff0c;有这样一种需求&#xff0c;实现固定格式和自由格式的比特流无线传输。解释一下&#xff0c;固定格式形如下面表格&#xff1a; 每个字段都有位宽、类型等属性&#xff0c;这种固定格式一…

期望最大化算法:机器学习中的隐变量与参数估计的艺术

引言 在机器学习和统计学领域&#xff0c;许多实际问题涉及到含有隐变量的概率模型。例如&#xff0c;在图像识别中&#xff0c;图像的语义信息往往是隐变量&#xff0c;而我们能观测到的只是图像的像素值&#xff1b;在语音识别中&#xff0c;语音对应的文本内容是隐变量&…

2025封禁指定国家ip-安装xtables-addons记录

如何安装和使用 安装lux仓库(该仓库包含xtables-addons所需的依赖环境) # wget http://repo.iotti.biz/CentOS/7/noarch/lux-release-7-1.noarch.rpm # rpm -ivh lux-release-7-1.noarch.rpm 安装xtables-addons。注意&#xff1a;必须先安装kmod-xtables-addons&#xff0c;再…

使用C语言实现栈的插入、删除和排序操作

栈是一种后进先出(LIFO, Last In First Out)的数据结构,这意味着最后插入的元素最先被删除。在C语言中,我们可以通过数组或链表来实现栈。本文将使用数组来实现一个简单的栈,并提供插入(push)、删除(pop)以及排序(这里采用一种简单的排序方法,例如冒泡排序)的操作示…

【Go】Go Gin框架初识(一)

1. 什么是Gin框架 Gin框架&#xff1a;是一个由 Golang 语言开发的 web 框架&#xff0c;能够极大提高开发 web 应用的效率&#xff01; 1.1 什么是web框架 web框架体系图&#xff08;前后端不分离&#xff09;如下图所示&#xff1a; 从上图中我们可以发现一个Web框架最重要…

【深度学习】Windows系统Anaconda + CUDA + cuDNN + Pytorch环境配置

在做深度学习内容之前&#xff0c;为GPU配置anaconda CUDA cuDNN pytorch环境&#xff0c;在网络上参考了很多帖子&#xff0c;但pytorch的安装部分都有些问题或者比较复杂繁琐&#xff0c;这里总结了相对简单快速的配置方式 文章目录 AnacondaCUDAcuDNNpytorchtorchtorchau…

提供的 IP 地址 10.0.0.5 和子网掩码位 /26 来计算相关的网络信息

网络和IP地址计算器 https://www.sojson.com/convert/subnetmask.html提供的 IP 地址 10.0.0.5 和子网掩码位 /26 来计算相关的网络信息。 子网掩码转换 子网掩码 /26 的含义二进制表示:/26 表示前 26 位是网络部分&#xff0c;剩下的 6 位是主机部分。对应的子网掩码为 255…

js中的Object.defineProperty()详解

文章目录 一、Object.defineProperty()二、descriptor属性描述符2.1、数据描述符2.2、访问器描述符2.3、descriptor属性2.3.1、value2.3.2、writable2.3.3、enumerable &#xff08;可遍历性&#xff09;2.3.4、configurable &#xff08;可配置性&#xff09; 三、注意事项 一…

单细胞组学大模型(8)--- scGenePT,scGPT和GenePT的结合,实验数据和文本数据的交融模型

–https://doi.org/10.1101/2024.10.23.619972 研究团队和单位 Theofanis Karaletsos–Head Of AI - Science at Chan Zuckerberg Initiative &#xff08;Chan Zuckerberg Initiative是扎克伯格和他妻子Chan成立的科研&教育机构&#xff09; 研究简介 研究背景&…

微信原生小程序自定义封装组件(以导航navbar为例)

封装 topnav.js const App getApp(); Component({// 组件的属性列表properties: {pageName: String, //中间的titleshowNav: { //判断是否显示左上角的按钮 type: Boolean,value: true},showHome: { //判断是否显示左上角的home按钮type: Boolean,value: true},showLocat…

day06_Spark SQL

文章目录 day06_Spark SQL课程笔记一、今日课程内容二、DataFrame详解&#xff08;掌握&#xff09;5.清洗相关的API6.Spark SQL的Shuffle分区设置7.数据写出操作写出到文件写出到数据库 三、Spark SQL的综合案例&#xff08;掌握&#xff09;1、常见DSL代码整理2、电影分析案例…

HarmonyOS NEXT应用开发边学边玩,从零实现一影视APP(四、最近上映电影滚动展示及加载更多的实现)

在HarmonyOS NEXT开发环境中&#xff0c;我们可以使用多种组件和库来构建丰富且交互友好的应用。本文将展示如何使用HarmonyOS NEXT框架和nutpi/axios库&#xff0c;从零开始实现一个简单的影视APP的首页&#xff0c;主要关注最近上映电影的滚动展示及加载更多功能的实现。 安装…