SpringBoot 3.2.0 结合Redisson接入Redis

依赖版本

  • JDK 17
  • Spring Boot 3.2.0
  • Redisson 3.25.0

工程源码:Gitee

集成Redis步骤

导入依赖

<properties>
    <redisson.version>3.25.0</redisson.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson-spring-boot-starter</artifactId>
        <version>${redisson.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

编写配置文件

# application.yml
spring:
  # ======== Redis配置 ========
  redis:
    redisson:
      file: classpath:redisson.yaml
# redisson.yaml# 编码。默认值: org.redisson.codec.JsonJacksonCodec
codec: !<org.redisson.codec.Kryo5Codec> {}
# 线程池数量。默认值: 当前处理核数量 * 2
threads: 16
# Netty线程池数量。默认值: 当前处理核数量 * 2
nettyThreads: 32
# 传输模式。默认值: NIO
transportMode: "NIO"
# 监控锁的看门狗超时,单位:毫秒。默认值: 30000
lockWatchdogTimeout: 30000
# 是否保持订阅发布顺序。默认值: true
keepPubSubOrder: true# Redisson 单实例配置
singleServerConfig:
  # 节点地址。格式:redis://host:port
  address: "redis://127.0.0.1:6379"
  # 密码。默认值: null
  password: null
  # 数据库编号。默认值: 0
  database: 0
  # 客户端名称(在Redis节点里显示的客户端名称)。默认值: null
  clientName: null
  # 连接超时,单位:毫秒。默认值: 10000
  connectTimeout: 10000
  # 命令等待超时,单位:毫秒。默认值: 3000
  timeout: 3000
  # 命令失败重试次数。默认值: 3
  retryAttempts: 3
  # 命令重试发送时间间隔,单位:毫秒。默认值: 1500
  retryInterval: 1500
  # 最小空闲连接数。默认值: 32
  connectionMinimumIdleSize: 24
  # 连接池大小。默认值: 64
  connectionPoolSize: 64
  # 单个连接最大订阅数量。默认值: 5
  subscriptionsPerConnection: 5
  # 发布和订阅连接的最小空闲连接数。默认值: 1
  subscriptionConnectionMinimumIdleSize: 1
  # 发布和订阅连接池大小。默认值: 50
  subscriptionConnectionPoolSize: 50
  # DNS监测时间间隔,单位:毫秒。默认值: 5000
  dnsMonitoringInterval: 5000
  # 连接空闲超时,单位:毫秒。默认值: 10000
  idleConnectionTimeout: 10000

编写Redis操作工具

import lombok.RequiredArgsConstructor;
import org.redisson.api.RAtomicDouble;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RBucket;
import org.redisson.api.RList;
import org.redisson.api.RMap;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RSet;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;/**
 * Redis工具类
 */
@Component
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class RedisService {private final RedissonClient redissonClient;// ============================= String类型操作 ============================/**
     * 将值存储到Redis中
     *
     * @param key   键
     * @param value 值
     */
    public <T> void setString(String key, T value) {
        RBucket<T> bucket = redissonClient.getBucket(key);
        bucket.set(value);
    }/**
     * 将值存储到Redis中
     *
     * @param key      键
     * @param value    值
     * @param timeout  过期时间
     * @param timeUnit 时间单位
     */
    public <T> void setString(String key, T value, long timeout, TimeUnit timeUnit) {
        RBucket<T> bucket = redissonClient.getBucket(key);
        bucket.set(value, timeout, timeUnit);
    }/**
     * 根据键获取Redis中的值
     *
     * @param key 键
     * @return 值
     */
    public <T> T getString(String key) {
        RBucket<T> bucket = redissonClient.getBucket(key);
        return bucket.get();
    }// ============================= Hash类型操作 ============================/**
     * 将值存储到Redis中
     *
     * @param key   键
     * @param field hash键
     * @param value 值
     */
    public <T> boolean addToHash(String key, Object field, T value) {
        RMap<Object, T> hash = redissonClient.getMap(key);
        return hash.fastPut(field, value);
    }/**
     * 将值存储到Redis中
     *
     * @param key      键
     * @param field    hash键
     * @param value    值
     * @param timeout  过期时间
     * @param timeUnit 时间单位
     */
    public <T> boolean addToHash(String key, Object field, T value, long timeout, ChronoUnit timeUnit) {
        RMap<Object, T> hash = redissonClient.getMap(key);
        boolean fastPut = hash.fastPut(field, value);
        boolean expire = hash.expire(Instant.now().plus(timeout, timeUnit));
        return fastPut && expire;
    }/**
     * 根据键和Hash键获取Redis中的值
     *
     * @param key   键
     * @param field hash键
     * @return 值
     */
    public <T> T getFromHash(String key, Object field) {
        RMap<Object, T> hash = redissonClient.getMap(key);
        return hash.get(field);
    }/**
     * 根据键获取Redis中的值
     *
     * @param key 键
     * @return 值
     */
    public <T> Map<Object, T> getFromHash(String key) {
        RMap<Object, T> hash = redissonClient.getMap(key);
        return hash.readAllMap();
    }/**
     * 根据键和Hash键更新Redis中的值
     *
     * @param key   键
     * @param field hash键
     * @param value 值
     * @return 更新成功返回true,否则返回false
     */
    public <T> boolean updateToHash(String key, Object field, T value) {
        RMap<Object, T> hash = redissonClient.getMap(key);
        return hash.fastReplace(field, value);
    }/**
     * 根据Key,删除Hash类型的数据
     *
     * @param key      键
     * @param hashKeys hash键
     * @return 删除成功的数量
     */
    public <T> long removeFromHash(String key, T... hashKeys) {
        RMap<Object, T> hash = redissonClient.getMap(key);
        return hash.fastRemove(hashKeys);
    }// ============================= List类型操作 ============================/**
     * 向List数据类型中添加值
     *
     * @param key   键
     * @param value 值
     */
    public <T> boolean addToList(String key, T value) {
        RList<T> list = redissonClient.getList(key);
        return list.add(value);
    }/**
     * 向List数据类型中添加值
     *
     * @param key   键
     * @param value 值
     */
    public <T> boolean addToList(String key, List<T> value) {
        RList<T> list = redissonClient.getList(key);
        return list.addAll(value);
    }/**
     * 向List数据类型中添加值
     *
     * @param key      键
     * @param value    值
     * @param timeout  过期时间
     * @param timeUnit 时间单位
     */
    public <T> boolean addToList(String key, T value, long timeout, ChronoUnit timeUnit) {
        RList<T> list = redissonClient.getList(key);
        list.add(value);
        return list.expire(Instant.now().plus(timeout, timeUnit));
    }/**
     * 从List数据类型中获取值
     *
     * @param key   键
     * @param start 起始位置
     * @param end   结束位置
     * @return 值
     */
    public <T> List<T> getFromList(String key, int start, int end) {
        RList<T> list = redissonClient.getList(key);
        return list.range(start, end);
    }/**
     * 获取List数据类型中的所有值
     *
     * @param key 键
     * @return 值
     */
    public <T> List<T> getFromList(String key) {
        RList<T> list = redissonClient.getList(key);
        return list.readAll();
    }
​
​
    /**
     * 移除集合左侧第一个元素
     *
     * @param key 键
     */
    public void removeListLeft(String key) {
        RList<Object> list = redissonClient.getList(key);
        list.fastRemove(0);
    }/**
     * 移除集合右侧第一个元素
     *
     * @param key 键
     */
    public void removeListRight(String key) {
        RList<Object> list = redissonClient.getList(key);
        list.fastRemove(list.size() - 1);
    }/**
     * 移除集合指定位置元素
     *
     * @param key   键
     * @param index 索引
     */
    public void removeFromList(String key, int index) {
        RList<Object> list = redissonClient.getList(key);
        list.fastRemove(index);
    }/**
     * 移除集合指定元素
     *
     * @param key   键
     * @param value 值
     */
    public <T> boolean removeFromList(String key, T value) {
        RList<T> list = redissonClient.getList(key);
        return list.removeIf(o -> o.equals(value));
    }// ============================= Set类型操作 ============================/**
     * 添加值到Set数据类型中
     *
     * @param key   键
     * @param value 值
     */
    public <T> boolean addToSet(String key, T value) {
        RSet<T> set = redissonClient.getSet(key);
        return set.add(value);
    }/**
     * 添加值到Set数据类型中
     *
     * @param key      键
     * @param value    值
     * @param timeout  过期时间
     * @param timeUnit 时间单位
     * @return 是否成功
     */
    public <T> boolean addToSet(String key, T value, long timeout, ChronoUnit timeUnit) {
        RSet<T> set = redissonClient.getSet(key);
        boolean add = set.add(value);
        boolean expire = set.expire(Instant.now().plus(timeout, timeUnit));
        return add && expire;
    }/**
     * 添加值到Set数据类型中
     *
     * @param key    键
     * @param values 值
     * @return 是否成功
     */
    public <T> boolean addToSet(String key, List<T> values) {
        RSet<T> set = redissonClient.getSet(key);
        return set.addAll(values);
    }/**
     * 添加值到Set数据类型中
     *
     * @param key      键
     * @param values   值
     * @param timeout  过期时间
     * @param timeUnit 时间单位
     * @return 是否成功
     */
    public <T> boolean addToSet(String key, List<T> values, long timeout, ChronoUnit timeUnit) {
        RSet<T> set = redissonClient.getSet(key);
        set.addAllCounted(values);
        return set.expire(Instant.now().plus(timeout, timeUnit));
    }
​
​
    /**
     * 获取Set的所有元素。
     *
     * @param key 键
     * @return 所有值
     */
    public <T> Set<T> getFromSet(String key) {
        RSet<T> set = redissonClient.getSet(key);
        return set.readAll();
    }/**
     * 从Set数据类型中删除值
     *
     * @param key    键
     * @param values 值
     */
    public <T> void removeFromSet(String key, List<T> values) {
        RSet<T> set = redissonClient.getSet(key);
        values.forEach(set::remove);
    }/**
     * 从Set数据类型中删除值
     *
     * @param key   键
     * @param value 值
     */
    public <T> boolean removeFromSet(String key, T value) {
        RSet<T> set = redissonClient.getSet(key);
        return set.remove(value);
    }// ============================= ZSet类型操作 ============================/**
     * 添加值到ZSet数据类型中
     *
     * @param key   键
     * @param value 值
     * @param score 分值
     */
    public <T> void addToZSet(String key, T value, double score) {
        RScoredSortedSet<T> sortedSet = redissonClient.getScoredSortedSet(key);
        sortedSet.add(score, value);
    }/**
     * 在ZSet数据类型中添加值
     *
     * @param key      键
     * @param value    值
     * @param score    分值
     * @param timeout  过期时间
     * @param timeUnit 时间单位
     */
    public <T> void addToZSet(String key, T value, double score, long timeout, ChronoUnit timeUnit) {
        RScoredSortedSet<T> sortedSet = redissonClient.getScoredSortedSet(key);
        sortedSet.add(score, value);
        sortedSet.expire(Instant.now().plus(timeout, timeUnit));
    }/**
     * 获取ZSet的范围元素。
     *
     * @param key   键
     * @param start 起始位置
     * @param end   结束位置
     * @return Set类型的值
     */
    public <T> Set<Object> getFromZSet(String key, int start, int end) {
        RScoredSortedSet<T> sortedSet = redissonClient.getScoredSortedSet(key);
        return new HashSet<>(sortedSet.valueRange(start, end));
    }/**
     * 删除ZSet数据类型中的值
     *
     * @param key    键
     * @param values 值
     */
    public <T> void removeFromZSet(String key, List<T> values) {
        RScoredSortedSet<T> sortedSet = redissonClient.getScoredSortedSet(key);
        sortedSet.removeAll(values);
    }/**
     * 删除ZSet数据类型中的值
     *
     * @param key   键
     * @param value 值
     */
    public <T> void removeFromZSet(String key, T value) {
        RScoredSortedSet<T> sortedSet = redissonClient.getScoredSortedSet(key);
        sortedSet.remove(value);
    }// ============================= Common ============================/**
     * 判断Key是否存在
     *
     * @param key 键
     * @return 存在返回true,否则返回false
     */
    public boolean exists(String key) {
        return redissonClient.getBucket(key).isExists();
    }/**
     * 删除Key
     *
     * @param key 键
     */
    public boolean remove(String key) {
        long delete = redissonClient.getKeys().delete(key);
        return delete > 0;
    }/**
     * 设置Key的过期时间
     *
     * @param key      键
     * @param timeout  过期时间
     * @param timeUnit 时间单位
     * @return 设置成功返回true,否则返回false
     */
    public boolean expire(String key, long timeout, ChronoUnit timeUnit) {
        return redissonClient.getBucket(key).expire(Instant.now().plus(timeout, timeUnit));
    }/**
     * 获取Key的过期时间
     *
     * @param key 键
     * @return 过期时间
     */
    public Long getExpire(String key) {
        return redissonClient.getBucket(key).getExpireTime();
    }/**
     * 递增操作
     *
     * @param key   键
     * @param delta 增加的值
     * @return 递增后的值,如果键不存在,则返回-1
     */
    public long increment(String key, long delta) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        return atomicLong.addAndGet(delta);
    }/**
     * 递减操作
     *
     * @param key   键
     * @param delta 减少的值
     * @return 递减后的值,如果键不存在,则返回-1
     */
    public long decrement(String key, long delta) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        return atomicLong.decrementAndGet();
    }/**
     * 递增操作
     *
     * @param key   键
     * @param delta 增加的值
     * @return 递增后的值,如果键不存在,则返回-1
     */
    public double increment(String key, double delta) {
        RAtomicDouble atomicDouble = redissonClient.getAtomicDouble(key);
        return atomicDouble.addAndGet(delta);
    }/**
     * 递减操作
     *
     * @param key   键
     * @param delta 减少的值
     * @return 递减后的值,如果键不存在,则返回-1
     */
    public double decrement(String key, double delta) {
        RAtomicDouble atomicDouble = redissonClient.getAtomicDouble(key);
        return atomicDouble.decrementAndGet();
    }
}

编写测试用例

import jakarta.annotation.Resource;
import jodd.util.ThreadUtil;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import java.time.LocalDateTime;
import java.util.List;@Slf4j
@SpringBootTest
@DisplayName("Redis 集成测试类")
public class RedisApplicationTest {@Resource
    private RedisService redisService;private static final String STRING_KEY = "redis:string";
    private static final String LIST_KEY = "redis:list";
    private static final String SET_KEY = "redis:set";
    private static final String HASH_KEY = "redis:hash";@Test
    @DisplayName("Redis String 数据类型测试")
    public void redisStringTest() {
        log.info("Redis String 数据类型测试");
        redisService.setString(STRING_KEY, LocalDateTime.now().toString());
        String redisGetStringData = redisService.getString(STRING_KEY);
        log.info("Redis String Get:{}", redisGetStringData);
        boolean remove = redisService.remove(STRING_KEY);
        log.info("Redis String Remove:{}", remove);
        redisGetStringData = redisService.getString(STRING_KEY);
        log.info("Redis String Get After Delete:{}", redisGetStringData);
    }@Test
    @DisplayName("Redis List 数据类型测试")
    public void redisListTest() {
        log.info("Redis List 数据类型测试");
        // 填充数据
        List<Integer> list = Lists.newArrayList();
        for (int i = 0; i < 5; i++) {
            list.add(LocalDateTime.now().getNano());
            ThreadUtil.sleep(5);
        }boolean addItemResult = redisService.addToList(LIST_KEY, LocalDateTime.now().getNano());
        log.info("Redis List Add item:{}", addItemResult);
        redisService.getFromList(LIST_KEY)
                .forEach(s -> log.info("Redis List Get After Add Item:{}", s));boolean addListDataResult = redisService.addToList(LIST_KEY, list);
        log.info("Redis List Add List:{}", addListDataResult);
        redisService.getFromList(LIST_KEY)
                .forEach(s -> log.info("Redis List Get After Add List:{}", s));
​
        redisService.getFromList(LIST_KEY, 0, 2)
                .forEach(s -> log.info("Redis List Get By Index:{}", s));
​
        log.info("Redis List Size Before Delete:{}", redisService.getFromList(LIST_KEY).size());
        redisService.removeFromList(LIST_KEY, 0);
        log.info("Redis List Size After Delete:{}", redisService.getFromList(LIST_KEY).size());boolean remove = redisService.remove(LIST_KEY);
        log.info("Redis List Remove:{}", remove);
    }@Test
    @DisplayName("Redis Set 数据类型测试")
    public void redisSetTest() {
        log.info("Redis Set 数据类型测试");
        // 填充数据
        List<Integer> list = Lists.newArrayList();
        for (int i = 0; i < 5; i++) {
            list.add(LocalDateTime.now().getNano());
            ThreadUtil.sleep(5);
        }boolean addItemResult = redisService.addToSet(SET_KEY, LocalDateTime.now().getNano());
        log.info("Redis Set Add item:{}", addItemResult);
        redisService.getFromSet(SET_KEY)
                .forEach(s -> log.info("Redis Set Get After Add Item:{}", s));boolean addListDataResult = redisService.addToSet(SET_KEY, list);
        log.info("Redis Set Add List:{}", addListDataResult);
        redisService.getFromSet(SET_KEY)
                .forEach(s -> log.info("Redis Set Get After Add List:{}", s));
​
        log.info("Redis Set Size Before Delete:{}", redisService.getFromSet(SET_KEY).size());
        redisService.removeFromSet(SET_KEY, LocalDateTime.now().getNano());
        log.info("Redis Set Size After Delete:{}", redisService.getFromSet(SET_KEY).size());boolean remove = redisService.remove(SET_KEY);
        log.info("Redis Set Remove:{}", remove);
    }@Test
    @DisplayName("Redis Hash 数据类型测试")
    public void redisHashTest() {
        log.info("Redis Hash 数据类型测试");
        Integer key = LocalDateTime.now().getNano();boolean addItemResult = redisService
                .addToHash(HASH_KEY, key, LocalDateTime.now().toString());
        log.info("Redis Hash Add item:{}", addItemResult);
        redisService.getFromHash(HASH_KEY)
                .forEach((k, v) -> log.info("Redis Hash Get After Add Item:{} - {}", k, v.toString()));
​
        log.info("Redis Hash Get By Key:{}", redisService.getFromHash(HASH_KEY, key).toString());
​
        log.info("Redis Hash Size Before Delete:{}", redisService.getFromHash(HASH_KEY).size());
        redisService.removeFromHash(HASH_KEY, key);
        log.info("Redis Hash Size After Delete:{}", redisService.getFromHash(HASH_KEY).size());boolean remove = redisService.remove(HASH_KEY);
        log.info("Redis Hash Remove:{}", remove);
    }
}

运行测试用例

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue3-30-路由-嵌套路由的基本使用

什么是嵌套路由 嵌套路由 &#xff1a;就是一个组件内部还希望展示其他的组件&#xff0c;使用嵌套的方式实现页面组件的渲染。 就像 根组件 通过路由渲染 普通组件一样&#xff0c;嵌套路由也是一样的道理。 嵌套路由的相关关键配置 1、<router-view> 标签 声明 被嵌套组…

Echarts中饼图-实现放大显示数据

示例 代码演示 option {tooltip: {trigger: item},legend: {top: 5%,left: center},series: [{name: Access From,type: pie,radius: [40%, 70%],avoidLabelOverlap: false,label: {show: false,position: center},emphasis: {scale: true,//是否开启高亮后扇区的放大效果。s…

python查找mongo中符合条件的json记录

一、需求&#xff1a; 之前有次需要临时查找mongo中存储的json串&#xff0c;符合特定条件的记录&#xff1b; 举个例子&#xff0c;mongo中记录如下图&#xff1a; 其中每条存储的数据大概为&#xff1a; [{"createUser": "Zxtech","paramName&qu…

LVM逻辑卷与扩容

目录 一.LVM&#xff1a; 1.什么是LVM&#xff1a; 2.LVM的基本核心组件&#xff1a; 3.LVM的基本命令&#xff1a; 二.逻辑卷的创建&#xff1a; 第一步&#xff0c;我们先要为虚拟机添加硬盘 然后我们要添加依赖包 然后我们要进行磁盘分区 再添加好分区后&#xff0…

回顾2023,展望2024

时光飞逝&#xff0c;光阴似箭&#xff0c;转眼间又到了一年的年末&#xff0c;现在是2023年12月29日&#xff0c;再过两天就要元旦了&#xff0c;我们也要跨入2024年了。 记录自己的总结&#xff0c;一直想写&#xff0c;不知从何写起&#xff0c;在这一年中&#xff0c;有深夜…

程序员实现财富自由的十种方法!

程序员肯定都有过一夜暴富的梦想&#xff0c;也许是兼职接单&#xff0c;也许是成为炙手可热的大网红&#xff0c;也许只是平凡的中张百万大奖彩票…… 除去运气超好实力拔群以外&#xff0c;大多数程序员是很难在短时间内实现财富自由的。虽是如此&#xff0c;但搞钱对于程序…

Unity Shader-真实下雨路面

Unity Shader-真实下雨路面 简介素材1.准备插件Amplify Shader Editor&#xff08;这里我使用的是1.6.4最新版&#xff09;2.贴纸和切图d 一、创建一个Shader Surface&#xff0c;实现气泡播放效果二、叠加一次气泡播放效果&#xff0c;使其看起来更多&#xff0c;更无序三、小…

Matplotlib_plt.subplots 遇见中文乱码解决方案

文章目录 一、现象&#xff1a;二、解决方案1.将 **SimHei.ttf** &#xff0c;下载到当前运行目录中2.绘图中涉及标题、横纵坐标等&#xff0c;加上 **FontProperties font** 即可 环境说明&#xff1a;macOS系统 一、现象&#xff1a; 原先代码是这样的 import numpy as n…

BUUCTF Reverse/[2019红帽杯]Snake

BUUCTF Reverse/[2019红帽杯]Snake 下载解压缩后得到可执行文件&#xff0c;而且有一个unity的应用程序&#xff0c;应该是用unity编写的游戏 打开是一个贪吃蛇游戏 用.NET Reflector打开Assembly-CSharp.dll。&#xff08;unity在打包后&#xff0c;会将所有的代码打进一个Ass…

二、类与对象(三)

17 初始化列表 17.1 初始化列表的引入 之前我们给成员进行初始化时&#xff0c;采用的是下面的这种方式&#xff1a; class Date { public:Date(int year, int month, int day)//构造函数{_year year;_month month;_day day;} private:int _year;int _month;int _day; };…

社招面试题:说一说SPI是什么,有哪些使用场景?

大家好&#xff0c;我是小米&#xff01;今天在这里和大家分享一个在技术面试中常被问到的话题——SPI&#xff08;Service Provider Interface&#xff09;&#xff0c;这是一个令人着迷的技术领域&#xff0c;也是很多Java开发者必须要熟悉的概念。不废话&#xff0c;让我们一…

TikTok短视频互动:设计引人入胜的玩法体验

在数字社交的浪潮中&#xff0c;TikTok以其独特的短视频形式和丰富多彩的互动玩法&#xff0c;成为了全球年轻一代热衷的社交平台。本文将深入剖析TikTok短视频互动的精髓&#xff0c;探讨其设计背后的原理&#xff0c;以及为何这种互动体验如此吸引人。 创意挑战的魅力 TikTok…

机器视觉在智能交通与无人驾驶领域的应用及前景

​引言 机器视觉算法对于智能交通系统和无人驾驶技术是十分重要的。机器视觉技术是无人驾驶汽车感知环境、做出决策的关键&#xff0c;它使得车辆能够理解周围的世界并安全地导航。在智能交通系统中&#xff0c;机器视觉也发挥着至关重要的作用&#xff0c;从提高交通效率到增…

Unity Shader 实现X光效果

Unity Shader 实现X光效果 Unity Shader 实现实物遮挡外轮廓发光效果第五人格黎明杀机火炬之光 实现方案操作实现立体感优化总结源码 Unity Shader 实现实物遮挡外轮廓发光效果 之前看过《火炬之光》、《黎明杀机》、《第五人格》等不少的游戏里面人物被建筑物遮挡呈现出不同的…

【Java干货教程】JSON,JSONObject,JSONArray类详解

一、定义 JSON&#xff1a;就是一种轻量级的数据交换格式&#xff0c;被广泛应用于WEB应用程序开发。JSON的简洁和清晰的层次结构&#xff0c;易于阅读和编写&#xff1b;同时也易于机器解析和生成&#xff0c;有效的提升网络传输效率&#xff1b;支持多种语言&#xff0c;很多…

「年终总结」生成人工智能的奇妙年份

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…

MySQL之复合查询

单表查询回顾 在讲解多表查询前&#xff0c;我们先回顾一下单表查询&#xff0c;这是因为多表查询本质上依然是单表查询&#xff08;其原因在下文中讲解多表查询时再说明&#xff09;&#xff0c;只要掌握了单表查询&#xff0c;那么想掌握多表查询是非常简单的。 在<<…

【Electron】富文本编辑器之文本粘贴

由于这个问题导致&#xff0c;从其他地方复制来的内容 粘贴发送之后都会多一个 换行 在发送的时候如果直接&#xff0c;发送innerHTML 就 可以解决 Electron h5 Andriod 都没问题&#xff0c;但是 公司的 IOS 端 不支持&#xff0c;且不提供支持&#xff08;做不了。&#xff…

2023年华为OD机试(python)B卷-符合要求的结对方式

一、题目 题目描述&#xff1a; 用一个数组A代表程序员的工作能力&#xff0c;公司想通过结对编程的方式提高员工的能力&#xff0c;假设结对后的能力为两个员工的能力之和&#xff0c;求一共有多少种结对方式使结对后能力为N。 二、输入输出 输入描述: 5 1 2 2 2 3 4 第一行为…

个人用户免费,亚马逊正式推出 AI 编程服务 CodeWhisperer

亚马逊于 2022 年 6 月以预览版的形式&#xff0c;推出了 AI 辅助编程服务 CodeWhisperer。2023年4月18日&#xff0c;亚马逊云科技宣布&#xff0c;实时 AI 编程助手 Amazon CodeWhisperer 正式可用&#xff0c;同时推出的还有供所有开发人员免费使用的个人版&#xff08;Code…