springboot3整合redis
来源于https://www.bilibili.com/video/BV1UC41187PR/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=865f32e12aef524afb83863069b036aa
一、整合redis
1.创建项目文件
2.添加依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.5</version></dependency><!-- mybatis-plus会自动调用mybatis,但mybatis-spring版本和springboot3+版本的spring会不匹配,所以要升版本--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>3.0.3</version></dependency></dependencies>
3.配置文件
后缀名改为yml
配置redis、mysql数据源、日志
server:port: 9999spring:data:redis:port: 6379host: localhostdatasource:username: rootpassword: *****url: jdbc:mysql:///testdblogging:level:com.qqcn: debug
4.创建redis配置类
@EnableCaching该注解为启动缓存管理
redisTemplate对象用来操作redis
redisCacheManager缓存管理器
其中setKey(Serializer)序列化 存到redis中的数据更加直观
package com.qqcn.config;import org.springframework.cache.annotation.EnableCaching;
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.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
@EnableCaching
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(factory);redisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));return redisTemplate;}@Beanpublic RedisCacheManager redisCacheManager(RedisTemplate<String, Object> redisTemplate) { // 明确指定参数化类型if (redisTemplate == null || redisTemplate.getConnectionFactory() == null) {// 处理错误情况,例如抛出异常或采取默认行为throw new RuntimeException("RedisTemplate or its connection factory is null");}RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);}
}
二、RedisTemplate操作-String
创建测试类演示
1.假如现在有一个登录的token想要存在redis里面
设置了有效期
package com.qqcn;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.UUID;
import java.util.concurrent.TimeUnit;@SpringBootTest
public class RedisTest {@Autowiredprivate RedisTemplate<String,Object> redisTemplate;@Testpublic void testString(){String key = "user:token:0001";
// 实际当中可以用jwtredisTemplate.opsForValue().set(key, UUID.randomUUID().toString(),30, TimeUnit.MINUTES);System.out.println(redisTemplate.opsForValue().get(key));}
}
启动redis
启动成功
token已存入
2.假如我们要对一篇文章进行访问数的统计
每查看一次都进行计数
@Testpublic void testString2(){String key = "article:A00001:viewsCount";redisTemplate.opsForValue().increment(key);System.out.println(redisTemplate.opsForValue().get(key));}
第一次执行是1,第二次就是2了
3.假如想要存储一个对象
如果一个对象无需修改而是仅查询作用,那么存String也是一个很好的选择
在配置类中做了一个json的序列化处理,所以存储对象进去最终会被转换成json字符串
@Testpublic void testString3(){Map<String,Object> user = new HashMap<>();user.put("id","0001");user.put("name","张三丰");user.put("age",28);String key = "user:0001";redisTemplate.opsForValue().set(key,user);System.out.println(redisTemplate.opsForValue().get(key));}
可以看到被存储为json格式
三、RedisTemplate操作-Hash
比如说在做一个电商类项目的时候,会有一个购物车对象
Hash是kv键值类型,值类型类似map结构,更适合用来保存对象
如果用opsForHash().put(Object key, Object hashkey, Object value)其中hashkey表示右边的k,value表示右边的v,如果一个一个存比较繁琐
所以我们这里用opsForHash().putAll(Object key,Map m)
测试取出购物车有哪些商品
@Testpublic void testHash(){String key = "user:0001:cart";Map<String, Object> shoppingCart = new HashMap<>();shoppingCart.put("cartId", "123456789");shoppingCart.put("userId", "987654321");List<Map<String, Object>> items = List.of(Map.of("itemId", "1", "itemName", "手机", "price", 999.99, "quantity", 1),Map.of("itemId", "2", "itemName", "笔记本电脑", "price", 1499.99, "quantity",2),Map.of("itemId", "3", "itemName", "耳机", "price", 49.99, "quantity", 3));shoppingCart.put("items", items);shoppingCart.put("totalAmount", 3149.92);shoppingCart.put("creationTime", "2046-03-07T10:00:00");shoppingCart.put("lastUpdateTime", "2046-03-07T12:30:00");shoppingCart.put("status", "未结账");redisTemplate.opsForHash().putAll(key, shoppingCart);System.out.println(redisTemplate.opsForHash().get(key, "items"));}
四、RedisTemplate操作-Set
是数据库中一种无序的、不重复的数据结构,用于存储一组唯一的元素
比如想去存储某个用户的粉丝有哪些人
redis中统计是非常的快的
添加了三个粉丝add进去
@Testpublic void testSet(){String key = "author:0001:fans";redisTemplate.opsForSet().add(key,"张三","李四","王五");System.out.println("粉丝量:" + redisTemplate.opsForSet().size(key));}
结果为粉丝量为3
五、RedisTemplate操作-ZSet
是一个有序且唯一的集合,每个元素都与一个浮点数分数相关联,使得集合中的元素可以根据分数进行排序,默认按照分数进行升序排序。
若要降序查询:
redisTemplate.opsForZSet().reverseRange(key,0,-1)
添加成员的时候有一个分数值,通过分数值进行排序处理
比如我们想存储某个用户的好友列表
除了添加用户的信息,还可以添加时间,可以根据时间获取好友的列表
@Testpublic void testZSet(){String key = "user:0001:friends";//取添加好友的时间的毫秒值redisTemplate.opsForZSet().add(key,"张三",System.currentTimeMillis());redisTemplate.opsForZSet().add(key,"李四",System.currentTimeMillis());redisTemplate.opsForZSet().add(key,"王五",System.currentTimeMillis());//倒序Set<Object> set = redisTemplate.opsForZSet().reverseRange(key, 0, -1);System.out.println(set);}
最后存入的在最前面(按时间的降序来处理)
六、RedisTemplate操作-List
一种简单的字符串列表,按照插入顺序排序
在redis中可以把List想象成通道,两边都是开放的,可以左进右出,也可以右进左出,或者左进左出也可以
可以用List实现队列的功能,比如现有一个订单的请求处理,在买商品的时候很可能因为并发的问题引发别的问题,可以利用队列让订单做一个排队
存入数据:
redisTemplate.opsForList().leftPush(key,order1);
获取并移除数据:
redisTemplate.opsForList().rightPop(key)
@Testpublic void testList(){String key = "order:queue";//订单1Map<String, Object> order1 = new HashMap<>();order1.put("orderId", "1001");order1.put("userId", "2001");order1.put("status", "已完成");order1.put("amount", 500.75);order1.put("creationTime", "2024-08-09T09:30:00");order1.put("lastUpdateTime", "2024-08-9T10:45:00");order1.put("paymentMethod", "在线支付");order1.put("shoppingMethod", "自提");order1.put("remarks", "尽快处理");//订单2Map<String, Object> order2 = new HashMap<>();order2.put("orderId", "1002");order2.put("userId", "2002");order2.put("status", "待处理");order2.put("amount", 280.99);order2.put("creationTime", "2024-08-09T11:00:00");order2.put("lastUpdateTime", "2024-08-09T11:00:00");order2.put("paymentMethod", "货到付款");order2.put("shoppingMethod", "快递配送");order2.put("remarks", "注意保鲜");// A程序接收订单请求并将其加入队列redisTemplate.opsForList().leftPush(key,order1);redisTemplate.opsForList().leftPush(key,order2);// B程序从订单队列中获取订单数据并处理System.out.println("处理订单:" + redisTemplate.opsForList().rightPop(key));}
从右边取出的数据:订单1
还剩订单2
七、@RedisHash注解
除了用RedisTemplate来操作hash数据,还提供了@RedisHash注解
用于将java对象直接映射到redis的hash数据当中
java对象的存储和检索变得更加简单
关键步骤:
1.@RedisHash注解标注在实体类上
2.创建接口并继承CrudRepository
1.创建一个实体类
@Id表示id为主键
package com.qqcn.entity;import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;@RedisHash
@Data
public class user {@Idprivate Integer id;private String name;private Integer age;private String phone;
}
2.创建一个接口
想要用此注解还需要创建一个接口
继承CrudRepository(增删改查)设定泛型第一个是操作的实体,第二个是主键的类型
定义完了接口之后就具备了对对象的基于redis的增删改查的能力
package com.qqcn.repository;import com.qqcn.entity.User;
import org.springframework.data.repository.CrudRepository;public interface UserRedisRepository extends CrudRepository<User,Integer> {
}
3.测试类进行测试
注入UserRedisRepository,进行测试类测试
@Autowiredprivate UserRedisRepository userRedisRepository;@Testpublic void testRedisHash(){User user = new User();user.setId(100);user.setName("张三丰");user.setAge(18);user.setPhone("18899998888");//保存到redis里面userRedisRepository.save(user);//读取Optional<User> redisUser = userRedisRepository.findById(100);System.out.println(redisUser);//更新user.setPhone("18899998866");//看数据是否存在,存在就修改,不存在就保存userRedisRepository.save(user);//再打印一次Optional<User> redisUser2 = userRedisRepository.findById(100);System.out.println(redisUser2);//删除//userRedisRepository.deleteById(100);//查看id是否存在boolean exists = userRedisRepository.existsById(100);System.out.println(exists);}
测试结果
因为没有指定key,key默认是 路径:id
八、缓存管理注解
redis最常见的用途就是用作缓存
而springboot的缓存管理功能旨在帮助开发人员轻松地在应用程序中使用缓存,以提高性能和响应速度,它提供了一套注解和配置,使得开发人员可以在方法级别上进行缓存控制,并且支持多种缓存存储提供程序
@Cacheable一般被用于查询方法,先在redis看看有无数据,如果有就直接在缓存里面拿,如果没有就查询数据库,并且会将查询到的数据放入缓存
@CachePut主要被用于更新缓存,一般可能用在新增和修改的方法上面
@CacheEvict主要用于清除缓存,一般会用在删除方法的上面
1.准备表
CREATE TABLE product (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255) NOT NULL,description TEXT,price DECIMAL(10, 2) NOT NULL,stock INT NOT NULL
);
INSERT INTO product (name, description, price, stock) VALUES
('iPhone 15', '最新的iPhone型号', 8999.99, 100),
('三星Galaxy S24', '旗舰安卓手机', 7899.99, 150),
('MacBook Pro', '专业人士的强大笔记本电脑', 15999.99, 50),
('iPad Air', '性能强劲的便携式平板电脑', 5599.99, 200),
('索尼PlayStation 6', '下一代游戏机', 4499.99, 75);
2.根据表创建实体类
package com.qqcn.entity;import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;@Data
@TableName
public class Product {@TableIdprivate Integer id;private String name;private String description;private Double price;private Integer stock;
}
3.创建一个mapper接口
到数据库当中查数据,必须要有数据库操作的存在
前面创建项目的时候是添加了mybatis-plus的依赖
所以创建一个mapper来简化数据库的操作
在mybatis-plus里面想要实现增删改查需要在接口上面继承BaseMapper,泛型里面指定实体是谁
package com.qqcn.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qqcn.entity.Product;public interface ProductMapper extends BaseMapper<Product> {
}
注意:要在启动类上加一个注解@MapperScan扫描一下
4.创建一个service
在此创建增删改查的几个方法
package com.qqcn.service;import com.qqcn.entity.Product;public interface ProductService {//查询public Product getProductById(Integer id);//新增 还是要写一个返回值//因为我们要用注解@CachePut缓存数据是只能缓存方法的返回值public Product addProduct(Product product);//修改public Product updateProduct(Product product);//删除public void deleteProductById(Integer id);
}
5.创建相应的实现类
package com.qqcn.service.impl;import com.qqcn.entity.Product;
import com.qqcn.mapper.ProductMapper;
import com.qqcn.service.ProductService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;@Service
public class ProductServiceImpl implements ProductService {@Resourceprivate ProductMapper productMapper;@Overridepublic Product getProductById(Integer id) {return productMapper.selectById(id);}@Overridepublic Product addProduct(Product product) {productMapper.insert(product);return product;}@Overridepublic Product updateProduct(Product product) {productMapper.updateById(product);return product;}@Overridepublic void deleteProductById(Integer id) {productMapper.deleteById(id);}
}
6.添加缓存存储的注解
我们希望看到的是
首先查找是先从redis里面找数据,如果有的话sql就不执行,如果sql执行了的话,日志里面会显示
value指定缓存的名称,key是保存在redis中的键(需要拼接id用单引号)
设置之后增删改查的同时会作缓存同步的处理,作高频访问的时候,可以提高效率,同时降低mysql压力
package com.qqcn.service.impl;import com.qqcn.entity.Product;
import com.qqcn.mapper.ProductMapper;
import com.qqcn.service.ProductService;
import jakarta.annotation.Resource;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;@Service
public class ProductServiceImpl implements ProductService {@Resourceprivate ProductMapper productMapper;@Cacheable(value = "product", key = "'product:' + #id")@Overridepublic Product getProductById(Integer id) {return productMapper.selectById(id);}@CachePut(value = "product", key = "'product:'+ #product.id")@Overridepublic Product addProduct(Product product) {productMapper.insert(product);return product;}@CachePut(value = "product", key = "'product:'+ #product.id")@Overridepublic Product updateProduct(Product product) {productMapper.updateById(product);return product;}@CacheEvict(value = "product", key = "'product:' + #id")@Overridepublic void deleteProductById(Integer id) {productMapper.deleteById(id);}
}
7.测试类进行测试
(1)测试查询
@Autowiredprivate ProductService productService;@Testpublic void testQuery(){Product product = productService.getProductById(1);System.out.println(product);}
这里在执行时发生了一个错误java.sql.SQLException: Access denied for user ‘root‘@‘localhost‘
出错在于mysql的密码是数字同时用的是.yml文件 所以我们需要把密码用双引号引起来
spring:data:redis:port: 6379host: localhostdatasource:username: rootpassword: "*****"url: jdbc:mysql://localhost:3306/testdb
更改之后测试成功,测试结果如下
redis中已缓存
重新测第二次
没有sql语句,因为我们可以在缓存中读取了
(2)测试更新(和新增同理,这里只演示更新)
@Testpublic void testUpdate(){//将刚刚查询到的名字修改一下Product product = productService.getProductById(1);product.setName("苹果15");//这里更新表一定会有sql日志,更新了缓存productService.updateProduct(product);//修改之后再一次查询,这里就没有sql日志了Product product2 = productService.getProductById(1);System.out.println(product2);}
测试结果,只有中间更新的时候有sql日志,查询走的都是缓存
redis已同步更改
(3)测试删除
删完的同时,缓存中的数据也会不存在
@Testpublic void testDelete(){productService.deleteProductById(1);}
测试结果,会打印一个删除的sql日志
mysql数据表中该数据被删除
redis中的缓存也没有了
相关文章:

springboot3整合redis
来源于https://www.bilibili.com/video/BV1UC41187PR/?spm_id_from333.1007.top_right_bar_window_history.content.click&vd_source865f32e12aef524afb83863069b036aa 一、整合redis 1.创建项目文件 2.添加依赖 <dependencies><dependency><groupId>…...

VUE基础快速入门
VUE 和 VUE-Cli VUE 是一种流行的渐进式JavaScript框架,用于构建Web用户界面它具有易学、轻量级、灵活性强、高效率等特点,并且可以与其他库和项目集成是目前最流行的前端框架之一VUE-Cli 称为“VUE脚手架”,它是由VUE官方提供的客户端,专门为…...
用Python实现特征工程之特征提取——数值特征提取、类别特征提取、文本特征提取、时间特征提取
特征提取是特征工程中的关键步骤,它从原始数据中提取有意义的特征,以便机器学习模型能够更好地理解和学习数据。根据数据类型,特征提取可以分为数值特征提取、类别特征提取、文本特征提取和时间特征提取。下面详细讲解每种特征提取方法&#…...

按图搜索新体验:阿里巴巴拍立淘API返回值详解
阿里巴巴拍立淘API是一项基于图片搜索的商品搜索服务,它允许用户通过上传商品图片,系统自动识别图片中的商品信息,并返回与之相关的搜索结果。以下是对阿里巴巴拍立淘API返回值的详细解析: 一、主要返回值内容 商品信息 商品列表…...
vue跨域问题
本地调试 可以通过在vue.config.js中配置devServer来实现跨域请求。 module.exports {publicPath: ./,productionSourceMap: false, // 生产环境是否生成 sourceMap 文件devServer: {proxy: {/bi: {target: http://1.11.113.20:1234/bi, // 后台接口域名ws: false, //…...

【NLP】文本处理的基本方法【jieba分词、命名实体、词性标注】
文章目录 1、本章目标2、什么是分词3、jieba的使用3.1、精确模式分词3.2、全模式分词3.3、搜索引擎模式分词3.4、中文繁体分词3.5、使用用户自定义词典 4、什么是命名实体识别5、什么是词性标注6、小结7、jieba词性对照表⭐ 🍃作者介绍:双非本科大三网络…...

unity 本地使用Json(全套)
提示:文章有错误的地方,还望诸位大神不吝指教! 文章目录 前言一、Json是什么?二、创建Json文件1.在线编辑并转实体类(C#)2.Json文件 三、解析Json并使用四、报错:JsonError:JsonExce…...

java消息队列ActiveMQ
安装 前置条件 activemq的运行依赖于jdk,需要提前安装jdk如果已经安装了jdk,需要根据jdk的版本来选择对应的版本进行安装activemq版本对应在官网上,使用java -version 看jdk的版本注意:jdk和mq的版本不一致会报错,电脑…...
Android SurfaceFlinger——信号同步原理(五十一)
经过前面系列文章的学习,我们的已经理解了 SurfaceFlinger 运行机制以及同步机制,但是SurfaceFlinger 又是以什么方法是把需要刷新的信号发送给 App 进程的。 一、VSync简介 垂直同步(Vertical Synchronization,简称 VSync)是一种用于同步视频信号和显示设备刷新率的技术…...

html+css网页制作 博云丝网5个页面 无js ui还原度100%
htmlcss网页制作 博云丝网5个页面 无js ui还原度100% 网页作品代码简单,可使用任意HTML编辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作)。 获取…...

Docker Hub 镜像代理加速
因为未知原因,docker hub 已经不能正常拉取镜像,可以使用以下代理服务来进行: "https://docker.m.daocloud.io", "https://noohub.ru", "https://huecker.io", "https://dockerhub.timeweb.cloud"…...
矩阵:消除冗余
矩阵 基本概念 矩阵(Matrix)是一个按照行和列排列的元素的二维数组。具体来说,一个 ( m \times n ) 的矩阵有 ( m ) 行和 ( n ) 列,表示为: A ( a 11 a 12 ⋯ a 1 n a 21 a 22 ⋯ a 2 n ⋮ ⋮ ⋱ ⋮ a m 1 a m 2 ⋯…...

【AWS账号解绑关联】Linker账号解绑重新关联注意事项
文章目录 一、来自客户疑问二、提交工单获取帮助三、最佳操作说明四、最佳操作步骤五、参考资料活动上新 一、来自客户疑问 将Linker账号,从一个组织中退出,重新关联到新的组织中,这解绑到重新完成新的关联绑定期间会在Linker账号中的账单中…...

入门学习使用overleaf和latex
文章目录 1.下载对应的latex论文模板2.overleaf平台的使用2.1overleaf平台的介绍2.2overleaf平台模板文件的上传2.3latex语法的学习2.3.2 分段(如下图显示)2.3.3 其他2.3.4简单latex实操2.3.5 换行符和换页符2.3.6左右居中对齐2.3.7 字体设置2.3.8插入固定位置图片2.3.9文字包围…...

后端调优——分布式锁选型——入门
文章目录 引言正文分布式锁的定义分布式锁的具体应用场景如何实现分布式锁主动轮询型分布式锁实现思路一、MySQL分布式锁二、Redis分布式锁 监听回调型分布式锁Etcd分布式锁Zookeeper分布式锁 锁的对比 总结 引言 最近面试,一直被问到分布式锁,然后仅仅…...

k8s集群管理 Pod管理命令
k8s集群管理命令 信息查询命令 子命令说明help用于查看命令及子命令的帮助信息cluster-info显示集群的相关配置信息api-resources查看当前服务器上所有的资源对象api-versions查看当前服务器上所有资源对象的版本config管理当前节点上的认证信息 资源对象概述 Pod概述 Pod 管…...

Java 并发(二)—— AQS原理
AQS,全名AbstractQueuedSynchronizer。 抽象队列同步器定义多线程访问共享资源的同步模板,解决了实现自定义同步器时涉及的大量细节问题,简化开发两种同步状态:独占、共享核心组件:State变量、CLH变体队列、获取 / 释…...

Maven插件:exec-maven-plugin-代码执行或者直接输出内置变量信息
文章目录 概述使用应用自行实现记录项目打包插件 概述 官网: https://www.mojohaus.org/exec-maven-plugin/usage.html 依赖: https://mvnrepository.com/artifact/org.codehaus.mojo/exec-maven-plugin 使用 <plugin><groupId>org.codeh…...

https://ffmpeg.org/
https://ffmpeg.org/ https://www.gyan.dev/ffmpeg/builds/ https://github.com/BtbN/FFmpeg-Builds/releases F:\Document_ffmpeg F:\Document_ffmpeg\ffmpeg-master-latest-win64-gpl-shared\bin...

linux 源码部署polardb-x 错误汇总
前言 在linux 源码部署polardb-x 遇到不少错误,特在此做个汇总。 问题列表 CN 启动报错 Failed to init new TCP 详细错误如下 Caused by: Failed to init new TCP. XClientPool to my_polarx#267b21d8127.0.0.1:33660 now 0 TCP(0 aging), 0 sessions(0 runni…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...

手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
多元隐函数 偏导公式
我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式,给定一个隐函数关系: F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 🧠 目标: 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z、 …...

门静脉高压——表现
一、门静脉高压表现 00:01 1. 门静脉构成 00:13 组成结构:由肠系膜上静脉和脾静脉汇合构成,是肝脏血液供应的主要来源。淤血后果:门静脉淤血会同时导致脾静脉和肠系膜上静脉淤血,引发后续系列症状。 2. 脾大和脾功能亢进 00:46 …...
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...