Springboot整合redis实现缓存

news2024/12/28 3:45:58

此次笔记是在实现了数据库的增删改查操作的基础上进行的,因此需要准备数据库、数据表,以及实现相对应的服务层、持久层、控制层。可参考之前的笔记Spring Boot整合 druid、Mybatis-plus

一、Redis安装

Redis 是完全开源免费的,遵守BSD协议,是一个高性能(NOSQL)的key-value数据库,Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

1.redis下载,

在GitHub上下载redis,下载地址:https://github.com/tporadowski/redis/releases,如图所示
在这里插入图片描述

2. Redis服务开启与连接配置

Redis安装文件为压缩文件,不需要安装,解压缩到自定义目录即可,不需要额外配置。
2.1 开启服务。进入解压目录,双击运行redis-server.exe,即可开启服务
2.2 打开终端。双击运行 redis-cli.exe,即可开启客户端工具。

3. Redis可视化工具安装。

由于redis-cli.exe打开的终端界面不友好,官方和第三放均推出了可视化管理工具。
Redis DeskTop Manager官方版是一款开源软件,支持通过SSH Tunnel连接,支持windows、mac等多平台。自从进入了0.9.9版本就开始付费使用或者贡献代码获得免费使用期限。
Another Redis DeskTop Manager作为一款基于nodejs开发的免费的Redis可视化管理工具,可以运行在Windows、Linux、Mac平台,而且是开源免费应用,=推荐使用。官方地址:https://gitee.com/qishibo/AnotherRedisDesktopManager,下载安装后,打开界面如下。
!](https://img-blog.csdnimg.cn/b64b319e43ff4bc7b15e647eeab3560c.png)

二、使用springboot整个redis

1. 添加依赖。

在项目的pom.xml文件中添加Redis依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
</dependency>

2. Redis服务连接配置

在项目的全局配置文件application.properties中添加redis服务的连接配置,这些配置与可视化工具连接时的参数基本一致。代码如下

#redis服务地址
spring.redis.host=127.0.0.1
#redis服务器连接端口
spring.redis.port=6379
#redis服务器连接密码,默认为空
spring.redis.password=

三、使用注解方式实现Redis缓存

1 添加缓存注解

在项目的启动类上添加注解,开启基于注解的的缓存支持

@EnableCaching
@SpringBootApplication
// 加载 properties 配置文件
@PropertySource(value = {"classpath:/application-druid.properties",
        "classpath:/application-mybatisp.properties"})
public class   CrudApplication {
    public static void main(String[] args) {
        SpringApplication.run(CrudApplication.class, args);
    }
}

2 实体类序列化

实体类Stu必须实现序列化 implements Serializable implements Serializable

package dzxx.crud.pojo;

import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;

@Data
@TableName(value = "stu")
@NoArgsConstructor
@AllArgsConstructor
public class Stu implements Serializable {
    @TableId(value = "id",type = IdType.AUTO)
    // Integer默认值是null,可以区分未赋值和值为0的情况.需要区分未赋值的情况下用Integer
    private Integer id;
    private String name;
    private String pass;
    private int age;    
    @TableField( fill=FieldFill.INSERT)
    private Date currenttime;  
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date modifytime;
    //注解@version ,用于测试乐观锁,
    @Version
    private Integer version;
}

3.在service类或者方法上添加注解。

创建service包,并创建接口StuService.java 及实现类StuServiceImpl.java

在查找方法、更新方法和删除方法上添加@Cacheable、@CachePut、@CacheEvict注解实现缓存存储、缓存更新和缓存删除使。
1.@Cacheable ,作用与类或者方法上,通常用在数据查询方法上。用于对方法的返回结果进行缓存存储。执行顺序是:先进行缓存查询,如果为空则执行方法查询数据库,并以形参:返回结果的键值对形式将返回结果缓存;如果缓存中有数据,不执行方法查询,直接使用缓存数据。
通过刷新浏览器,在idea终端查看是否多次执行sql语句进行验证

  1. @CachePut ,作用于类上或者方法上,通常用在数据更新上,用于更新缓存数据。执行顺序是:首先执行方法将新的数据更新到数据库,然后将新的数据更新到缓存中
  2. @CacheEvict ,作用于类上或者方法上,通常用在数据删除上,作用是删除缓存数据。执行顺序是:首先执行方法删除数据库中的数据,然后再清除缓存中的数据
package dzxx.crud.service;
import com.baomidou.mybatisplus.extension.service.IService;
import dzxx.crud.pojo.Stu;
import java.util.List;
public interface StuService extends IService<Stu> {
    public Stu findById(int id);
    public Stu updateStu(Stu stu);
}
package dzxx.crud.service.serviceImpl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import dzxx.crud.pojo.Stu;
import dzxx.crud.repository.StuMapper;
import dzxx.crud.service.StuService;
import io.github.ms100.cacheasmulti.cache.annotation.CacheAsMulti;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;

@Service
public class StuServiceImpl extends ServiceImpl<StuMapper,Stu> implements StuService {
    @Autowired(required = false)
    StuMapper stuMapper;
    @Override
    @Cacheable(cacheNames = "stu")
    public Stu findById(int id) {  
    // //用 id 生成缓存 key ,用 Stu 为缓存值
    //如果没有形参则key的值为默认的SimpleKey[]
        Stu stu = stuMapper.selectById(id);
        return stu;
    }
    @CachePut(cacheNames = "stu",key = "#result.id")
    @Override
    public Stu updateStu(Stu stu) {
        UpdateWrapper<Stu> wrapper=new UpdateWrapper<>();
        wrapper.eq("id", stu.getId());
        int update = stuMapper.update(stu,wrapper);   //将新的数据更新到数据库中
        return stu;   //将新的数据存入缓存中,
    }
}

4.在controller包中创建控制类

创建控制类StuController.java 文件并添加方法和映射路径,调用service方法。

package dzxx.crud.controller;
import dzxx.crud.pojo.Stu;
import dzxx.crud.service.StuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class StuController {
    @Autowired(required = false)
    private StuService stuService;
    @GetMapping("/getbyId")
    public Stu findById() {
        Stu stu = stuService.findById(2);
        return stu;
    }
    @GetMapping("/updateStu")
    public Stu updateStu() {
        Stu stu=new Stu(2,"zhangsan","rewr",22,null,null,1);
        stuService.updateStu(stu);
        return stu;
    }
}

5.批量缓存

SpringBoot 的缓存注解实现只能操作单个缓存,并不支持批量。想要实现批量操作,可以引入一个依赖 cache-as-multi。通过在形参上添加注解 @CacheAsMuti,指明要生成批量缓存key的参数,就可以实现缓存的批量操作。 详细用法参考Git:https://github.com/ms100/cache-as-multi

5.1 在项目的pom.xml文件中添加cache-as-multi依赖

        <dependency>
            <groupId>io.github.ms100</groupId>
            <artifactId>cache-as-multi</artifactId>
            <version>1.1.3</version>
        </dependency>

5.2 在service包中的接口和实现类中添加方法

由于要批量生成key,所以需要通过getIds()接口来获取所有的id, getAll(List ids)和getAll();作为对比。

    public List<String> getIds();
    public List<Stu> getAll(List<String> ids);
    public List<Stu> getAll();
 @Cacheable(cacheNames = "stu")
    @Override
    public List<Stu> getAll() {
        //查询的结果列表作为value存入缓存,key为SimpleKey[]
        return stuMapper.selectList(null);
    }
    @Cacheable(cacheNames = "stu")
    public List<String> getIds(){
        List<String> ids=new ArrayList<>();
        List<Stu> lists = stuMapper.selectList(new QueryWrapper<Stu>().select("id"));
        lists.forEach(i->{
            ids.add(i.getId().toString());
        });
        return ids;
    }
   @Cacheable(cacheNames = "stu")
    public List<Stu> getAll(@CacheAsMulti List<String> ids) {
       //@CacheAsMulti注解 为 ids 集合中每个元素分别生成缓存 key
       // 用 List 中对应的值作为缓存值
        return stuMapper.selectList(null);
    }

5.3在控制层添加映射路径,并调用service方法。

    @GetMapping("/getAll")
    public List<Stu> getAll(){
        return stuService.getAll();
    }
    @GetMapping("/getAllBatch")
    public List<Stu> getAABatch(){
        List<String> ids = stuService.getIds();
        return stuService.getAll(ids);
    }

5.4 运行效果图对比

注解实现只能操作单个缓存,返回的对象列表作为value值。
在这里插入图片描述
在形参上添加注解 @CacheAsMuti,指明要生成批量缓存key的参数,就可以实现缓存的批量操作。在这里插入图片描述

6 自定义序列化

从上图可以看出,数据存储的格式是Hex,不便于使用查看和管理,因为默认的序列化方式是JDK序列化机制。所以我们可以自定义Json格式的序列化机制进行数据缓存管理
新建config包,并创建自定义配置类RedisConfig.java文件。

package dzxx.crud.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import javax.annotation.Resource;
import java.time.Duration;

@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    @Resource
    private RedisConnectionFactory connectionFactory;

    //缓存管理器,针对基于注解的RedisTemplate进行自定义序列化机制改进
    @Bean
    public RedisCacheManager cacheManager(){
        RedisSerializer<String> stringRedisSerializer=new StringRedisSerializer();

        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(1))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer()))
                .disableCachingNullValues();
        return RedisCacheManager
                .builder(connectionFactory)
                .cacheDefaults(config)
                .build();
    }
    //缓存序列化策略
    private Jackson2JsonRedisSerializer<Object> jsonSerializer(){
        //使用json方式格式序列化对象,对缓存数据的key和value进行转换
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer<Object>(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om=new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        return jackson2JsonRedisSerializer;
    }
}

运行效果如图所示,可以看到以json格式存储到了缓存中。
在这里插入图片描述

四、使用API的方式实现Redis缓存

除了基于注解的方式实现缓存,也可以使用基于API的方式实现缓存

1. 创建service接口和实现类

新建接口ApiStuService.java和实现类ApiStuServiceImp.java

package dzxx.crud.service;

import com.baomidou.mybatisplus.extension.service.IService;
import dzxx.crud.pojo.Stu;
import java.util.List;
public interface ApiStuService extends IService<Stu> {
    public Stu findById(int id);
    public Stu updateStu(Stu stu);
    public List<String> getIds();
    public List<Stu> getAll(List<String> ids);
    public List<Stu> getAll();
}
package dzxx.crud.service.serviceImpl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import dzxx.crud.pojo.Stu;
import dzxx.crud.repository.StuMapper;
import dzxx.crud.service.ApiStuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


public class ApiStuServiceImp extends ServiceImpl<StuMapper,Stu> implements ApiStuService {
    
    StuMapper stuMapper;
    
    private RedisTemplate redisTemplate;
    
    public Stu findById(int id) {
        Object object=redisTemplate.opsForValue().get(id);
        // Object object=redisTemplate.opsForValue().get("stu_"+id);
        if (object!=null) {
            return (Stu)object;
        }
        else{//缓存中没有此信息,进入数据库查询
            Stu stu=stuMapper.selectById(id);
            if (!Objects.isNull(stu)){
                redisTemplate.opsForValue().set("stu_"+id, stu,1,TimeUnit.DAYS);
                return stu;
            }else
                return null;
        }
    }
    
    public Stu updateStu(Stu stu) {
        UpdateWrapper<Stu> wrapper=new UpdateWrapper<>();
        wrapper.eq("id", stu.getId());
        int update = stuMapper.update(stu,wrapper);
        redisTemplate.opsForValue().set("stu_"+stu.getId(), stu);
        return stu;
    }
    
    public List<String> getIds() {
        return null;
    }
    
    public List<Stu> getAll(List<String> ids) {
        return null;
    }
   
    public List<Stu> getAll() {
        List<Stu> redisStuList= (List<Stu>) redisTemplate.opsForValue().get("AllStu");
        if(redisStuList!=null){   //redis缓存中有全部数据
            System.out.println("redis。。。");
            return  redisStuList;
        }else{ //缓存中没有此信息,进入数据库查询
            List<Stu> stuList = stuMapper.selectList(null);
            //全部数据作为value缓存
            redisTemplate.opsForValue().set("AllStu", stuList);
            // 遍历全部数据中的每行数据单独缓存,以便单独修改某条数据
            stuList.forEach(stu -> {
                redisTemplate.opsForValue().set("Stu_"+stu.getId(),stu );
            });
            System.out.println("数据库。。。");
            return stuList;
        }
    }
}

2. 创建controller方法

新建控制类ApiStuController.java,并添加映射路径

package dzxx.crud.controller;

import dzxx.crud.pojo.Stu;
import dzxx.crud.service.ApiStuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;


("/api")
public class ApiStuController {
    (required = false)
    private ApiStuService apiStuService;
    ("/getbyId")
    public Stu findById() {
        Stu stu = apiStuService.findById(2);
        return stu;
    }
    ("/updateStu")
    public Stu updateStu() {
        Stu stu=new Stu(2,"jack","i7654",77,null,null,1);
        apiStuService.updateStu(stu);
        return stu;
    }
    ("/getAll")
    public List<Stu> getAll(){
        return apiStuService.getAll();
    }
}

3. 运行效果如图所示;

在这里插入图片描述

4 自定义序列化

从上图同样可以看出,数据存储的格式是Hex,我们可以自定义Json格式的序列化机制进行数据缓存管理
在配置类RedisConfig.java中添加以下方法。

    //RedisTemplate 序列化方式,针对基于API的RedisTemplate进行自定义序列化机制改进
    @Bean
    public RedisTemplate<String ,Object> redisTemplate(){
        RedisTemplate<String,Object> redisTemplate=new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        //设置redistemplate模板Api的序列化方式为json
        redisTemplate.setDefaultSerializer(jsonSerializer());
        return redisTemplate;
    }

运行效果如图所示
在这里插入图片描述

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

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

相关文章

【每日一短语】对(某人)吹毛求疵

1、短语及释义 get all sensitive on sb. 释义&#xff1a; 对某人吹毛求疵。 sensitive: 敏感的&#xff0c;引申为“事多的”&#xff0c;“爱挑刺的”。 2、示例及出处 美剧&#xff1a;《摩登家庭》第4季第7集 Modern Family, Season 4 Episode 7 Jay Pritchett: Don’t g…

中医诊所一定要去尝试软文营销,效果简直不要太好

中医诊所是一种传统的医疗机构&#xff0c;随着互联网时代的发展&#xff0c;软文营销已经成为了中医诊所宣传推广的一种重要方式。通过撰写高质量的软文&#xff0c;中医诊所可以提升品牌知名度、增加患者数量、提高医疗服务质量等方面取得良好的效果。今天结合我10年营销经验…

INDEMIND双目惯性模组运行实时ORB-SLAM3教程

现在实验室视觉SLAM已经不够满足&#xff0c;所以需要多模态融合&#xff0c;正巧购入高翔博士推荐的INDEMIND双目惯性模组&#xff0c;根据官方例程在中使用ros接入ORB-SLAM3INDEMIND的双目鱼眼imu模组&#xff0c;这回有SDK及ORB-SLAM3安装过程中的各种常见性问题解决方法及安…

Boost的安装

过程 boost是一个非常重要的东西&#xff0c;是对C函数库的扩展&#xff0c;非常得不错&#xff0c;是第三方扩展&#xff0c;不过不是一般的第三方&#xff0c;是C标准委员会工作组成员发起的。 通过vs命令工具进入boost目录 执行bootstrap.bat命令 开始安装 b2.exe instal…

JavaScript经典教程(二)-- CSS基础部分

179&#xff1a;HTML基础部分&#xff08;元素分类、特性、特殊元素等&#xff09; — 补充 1、盒子模型 定义&#xff1a;一个元素在页面中所占的位置大小&#xff0c;叫盒子模型。 包含的样式&#xff1a;即影响元素大小的样式&#xff1a; width、height、margin、padding…

使用MyBatis实现关联查询

文章目录 一&#xff0c;查询需求&#xff08;一&#xff09;针对三张表关联查询&#xff08;二&#xff09;按班级编号查询班级信息&#xff08;三&#xff09;查询全部班级信息 二&#xff0c;创建数据库表&#xff08;一&#xff09;创建教师表&#xff08;二&#xff09;创…

云计算中的自动化运维技术及其实践

引言 随着云计算技术的快速发展&#xff0c;云计算成为了企业数据中心的新生态&#xff0c;提供了更加灵活、高效、安全的 IT 基础设施和应用服务&#xff0c;让企业能够更加专注于业务创新和变革。但是&#xff0c;云计算的快速发展也带来了新的安全挑战&#xff0c;尤其是在…

达摩院开源工业级说话人识别模型CAM++

近日&#xff0c;达摩院正式向公众开源工业级说话人识别通用模型CAM&#xff0c;兼顾准确率和计算效率&#xff0c;训练labels类别达20万&#xff0c;每类含20&#xff5e;200条梅尔频谱特征。当前该模型已上线Modelscope魔搭社区&#xff0c;后续将陆续开源针对各场景优化的工…

TCP协议三次握手过程分析

TCP(Transmission Control Protocol) 传输控制协议 TCP是主机对主机层的传输控制协议&#xff0c;提供可靠的连接服务&#xff0c;采用三次握手确认建立一个连接: 位码即tcp标志位,有6种标示:SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结…

Vue3技术4之watch监视属性、watch时value问题

Vue3技术4 watch监视属性watch监视ref定义的数据情况一&#xff1a;监视ref所定义的一个响应式数据App.vueDemo.vue 情况二&#xff1a;监视ref所定义的多个响应式数据App.vueDemo.vue 添加immediate属性Demo.vue watch监视reactive定义的数据情况一&#xff1a;监视reactive所…

直播带货冲击实体生意,杭州四季青打响禁止直播带货第一枪

最近&#xff0c;“杭州四季青部分市场禁止直播”的话题冲上热搜。 身处“直播电商之城”杭州的“中国服装行业第一街”杭州四季青的部分市场&#xff0c;打响了“驱逐直播第一枪”&#xff01; 杭州四季青部分市场内为什么要明令禁止直播&#xff0c;直播卖货对实体商户带来了…

华锐3d虚拟数字人提供哪些智能化服务?

虚拟数字人的诞生是互联网时代的产物&#xff0c;它的出现为数字化经济提供了全新解决方案。数字化技术和网络使人类得以进入以“智能机器数据算法”为主线的新生态之中。 广州华锐互动作为专业的AI虚拟数字人开发商&#xff0c;拥有成熟的技术团队和一流的解决方案&#xff0…

零售数据分析操作篇15:用总聚合做销售分析

上一讲讲了内存计算筛选&#xff0c;又可称之为自定义计算成员筛选&#xff0c;即当某列是通过自定义计算成员得到的时候&#xff0c;还要想利用其作为筛选条件&#xff0c;就需要用到自定义计算成员筛选功能。 上一讲还给大家出了道作业&#xff0c;就是&#xff1a;想知道哪…

RHCE-DNS服务器

主机名称解析服务器配置 要求&#xff1a; 1、建立DNS服务器&#xff0c;负责解析的域为openedu.com&#xff1b; 建立DNS首先需要在服务器端配置主配置文件&#xff1a; &#xff08;1&#xff09;临时关闭防火墙和selinux&#xff1a;systemctl stop firewalld&#xff1b;…

靶机精讲之HackademicRTB1

主机发现 nmap扫描 端口扫描 只有80端口开放 UDP扫描 web渗透 服务扫描 脚本扫描 DOS攻击漏洞 枚举漏洞 查看web端 进行目录爆破 点击 点击后发现地址结构像有目录爆破 接上面枚举漏洞 复制那枚举目录到web 接目录爆破 apeache服务器 查看内容管理系统是否是自建的 在库搜索…

【rustdesk】rust入门及 windows尝试编译

rustup 微软建议用vs code开发 下载了64位的版本: vs code 插件 rust-analyer 介绍Better TOML,用于更好的展示.toml文件Error Lens, 更好的获得错误展示 One Dark Pro, 非常好看的Vscode主题 CodeLLDB, debugger程序 安装

2023年工商管理在职研究生择校、择专业指南

工商管理在职研究生是许多管理岗位从业者提升职业素质、竞争力的重要途径。 工商管理在职研究生学习的内容更加专业、深入&#xff0c;涵盖的领域更加广泛&#xff0c;通过学习&#xff0c;可以提高专业素养&#xff0c;掌握更深入的理论和实务知识&#xff0c;拓宽人脉&#…

爆爆爆!!Deep Mind与Google Brain合并,成立 Google DeepMind 新部门

图&#xff5c;2010-2023&#xff0c;从 DeepMind 到 Google DeepMind&#xff0c;再到 DeepMind&#xff0c;再到 Google DeepMind 来源: 学术头条 微信号&#xff1a;SciTouTiao 或许是深深感受到了来自 OpenAI 与微软一起给到的巨大压力&#xff0c;以及加速实现通用人工智…

基于 VITA57.4 标准的 8 路 500MSPS/1GSPS/1.25GSPS 采样率 14 位 AD 采集 FMC 子卡模块

板卡概述 FMC148 是一款基于 VITA57.4 标准的 JESD204B 接口 FMC 子卡模块&#xff0c;该模块可以实现 8 路 14-bit、500MSPS/1GSPS/1.25GSPS ADC 采集功能。该板卡 ADC 器件采用 ADI 公司的 AD9680 芯片,全 功率-3dB 模拟输入带宽可达 2GHz。该 ADC 与 FPGA 的主机接口通 …

【PyQt】QGraphicsItem的setPos和transformation的平移并不等效

1. 结论 今天才知道&#xff0c;改变图元的位置的两个方法&#xff1a; setPos() 和 transform.translate() 的本质是不同的&#xff01; 2. 缘由 在调试代码时&#xff0c;获取某个位置不在原点的图元的坐标总是返回(0,0)&#xff0c;百思不得其解&#xff0c;后仔细研究发…