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

【征服redis3】一文征服redis的jedis客户端

使用数据库的时候,我们可以用JDBC来实现mysql数据库与java程序之间的通信,为了提高通信效率,我们有了数据库连接池比如druid等等。而我们想通过Java程序控制redis,同样可以借助一些工具来实现,这就是redis客户端,常见的有Jedis、lettuce、redisson等等,这几个工具各有优缺点,而且应用都比较多,所以我们分三篇逐步来看。

Jedis 是一个功能强大、易用性高的 Redis 客户端库,适用于 Java 开发人员在项目中连接和操作 Redis 服务器。接下来,将介绍 Jedis 的使用方法和示例。

目录

1. Jedis介绍与安装测试

2.Jedis的基本操作体验

1.设置和获取字符串类型的键值对

2.判断键是否存在

3.删除键

4.设置键的过期时间

3.Jedis的数据类型操作

1.字符串类型

2.列表类型

3.集合类型

4.哈希类型

5.有序集合类型

4. Jedis 的事务操作

1.开启和提交事务

2.回滚事务

3.监视键

5. Jedis 的发布订阅操作

1.发布消息

2.订阅消息

6. Jedis 的管道操作

7. Jedis 的连接池配置和使用

8. Jedis 的异常处理

1. 处理连接异常

2. 处理命令执行异常:

9.Jedis 的性能优化


1. Jedis介绍与安装测试


Jedis 是一个流行的 Java 编写的 Redis 客户端库,它提供了连接和操作 Redis 服务器的功能。Jedis具有以下特点:

  1. 简单易用:Jedis 提供了简洁的 API,方便开发人员使用,减少了连接和操作 Redis 的复杂性。不过呢,简单也意味一些高级不能不支持的,这个与后面的客户端对比就知道了
  2. 高性能:Jedis 是通过直接与 Redis 服务器进行通信来实现操作的,因此具有较高的性能。
  3. 支持多种数据类型:Jedis 支持操作 Redis 的各种数据类型,包括字符串、哈希、列表、集合、有序集合等。
  4. 支持事务和管道:Jedis 提供了事务和管道的支持,可以将多个操作打包成一个原子操作,提高了操作的效率。
  5. 支持连接池:Jedis 支持连接池,可以复用连接,避免频繁建立和关闭连接的开销,提高了性能。

如果我们想在通过java 来管理redis,可以按照下面的方式进行:

首先,下载 Jedis

Jedis 的源代码托管在 Github 上,如果想看源码,可以直接从这里下载。如果要直接使用,可以通过 Maven 或 Gradle 添加 Jedis 的依赖即可。

在 pom.xml 文件中添加以下内容:

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.10.0</version>
</dependency>

版本一直在更新,Jedis是Java语言的Redis客户端库,它的版本号可以通过查看Jedis的Maven依赖或者JAR包的版本信息来获取。以下是一些常见的Jedis版本号范例:

  • Jedis 2.x版本:例如2.10.0、2.9.0等。
  • Jedis 3.x版本:例如3.6.0、3.5.2等。

这里我们使用应用比较多的2.10.0版本。

然后,我们可以在代码里配置Redis服务器的地址和端口

在 Java 程序中,需要提供 Redis 服务器的地址和端口,以便 Jedis 能够连接到 Redis。以下是一段示例代码:

  public static void main(String[] args) {Jedis jedis = new Jedis("localhost", 6379);// 测试连接System.out.println("Connection Successful");System.out.println("Server is running: " + jedis.ping());}

然后执行,可以看到如下信息,就说明已经安装成功了:

Connection Successful
Server is running: PONG

在这里,我们创建了一个新的 Jedis 对象,然后提供了 Redis 服务器的地址(“localhost”)和默认端口(6379)。然后,调用 jedis.ping() 来测试与 Redis 服务器的连接。
如果 Redis 服务器需要密码验证,可以在连接时添加密码参数: 

Jedis jedis = new Jedis("localhost", 6379);
jedis.auth("password");

使用的时候,将上面的“password” 换成你的 Redis 服务器的密码即可。

配置完成后,就可以通过 Jedis 连接和操作 Redis 服务器了。在实际工程中,我们会将连接信息写在配置文件里来集中管理,这里为了简单 ,我们直接用程序写死了。

接下来,将介绍 Jedis 的常用操作方法和示例。

2.Jedis的基本操作体验

1.设置和获取字符串类型的键值对

以下是如何使用 Jedis 的 set 和 get 方法来设置和获取字符串类型的键值对的例子:

        jedis.set("mykey", "海涛");String value = jedis.get("mykey");System.out.println("Stored string in redis:: " + value);

输出结果为:

Stored string in redis:: 海涛

2.判断键是否存在

可以使用 exists 方法来检查一个键是否存在。以下是一个例子:

//        判断是否存在boolean keyExists = jedis.exists("mykey");System.out.println("Does key 'mykey' exists? " + keyExists);

3.删除键

可以使用 del 方法来删除一个键。以下是一个例子:

jedis.del("mykey");

此时如果我们再使用上面的代码判断key是否存在就会发现此时返回的是 false。

4.设置键的过期时间

可以使用 expire 方法来为一个键设置过期时间(以秒为单位)。以下是一个例子:

        jedis.set("mykey", "海涛");jedis.expire("mykey", 60);  // 这个键将在60秒后过期

3.Jedis的数据类型操作

我们在前面通过redis-cli客户端来操作redis的几种类型,接下来,我们就看一下如何通过jedis来操作这些类型。

1.字符串类型

字符串类型是最简单也是最重要的的方式,我们可以直接使用set来设置一个,也可以使用mset来设置多个,例如:

jedis.set("key", "海涛"); // 设置字符串类型的键值对
String value = jedis.get("key"); // 获取字符串类型的键对应的值// 批量设置字符串类型的键值对
jedis.mset("key1", "海涛", "key2", "江涛");// 批量获取字符串类型的键对应的值
List<String> values = jedis.mget("key1", "key2");

输出结果:

value:海涛
values=[海涛, 江涛]

  • 2.设置和获取字符串类型的键值对:
jedis.set("mykey", "myvalue");
String value = jedis.get("mykey");
System.out.println("Stored string in redis:: " + value);
  • 3.批量设置和获取键值对:
jedis.mset("key1", "海涛", "key2", "江涛");
List<String> values = jedis.mget("key1", "key2");

2.列表类型

我们可以通过jedis的api接口来调用,名称与命令非常类似:

    public  static void  testList( Jedis jedis){// 添加元素到列表头部和尾部jedis.lpush("list", "element1", "element2"); // 头部添加jedis.rpush("list", "element3", "element4"); // 尾部添加// 获取列表的长度Long length = jedis.llen("list");System.out.println(length);// 获取指定范围内的元素List<String> elements = jedis.lrange("list", 0, -1); // 获取所有元素System.out.println(elements);}
  • 添加元素到列表头部和尾部:
jedis.lpush("mylist", "element1", "element2");
jedis.rpush("mylist", "element3");
  • 获取列表的长度:
Long length = jedis.llen("mylist");
  • 获取指定范围内的元素:
List<String> elements = jedis.lrange("mylist", 0, -1);

3.集合类型

集合类型是一种非常常见的类型,基本使用方式如下:

    public static void testSet(Jedis jedis) {// 添加元素到集合jedis.sadd("set", "element1", "element2");// 获取集合的大小Long size = jedis.scard("set");System.out.println("size=" + size);// 判断元素是否存在于集合中boolean exists = jedis.sismember("set", "element1");System.out.println(exists);}
  • 添加元素到集合:
jedis.sadd("myset", "element1", "element2");
  • 获取集合的大小:
Long size = jedis.scard("myset");
  • 判断元素是否存在于集合中:
boolean exists = jedis.sismember("myset", "element1");

4.哈希类型

hash是实现缓存的重要类型,使用jedis操作哈希的代码如下:

// 设置和获取哈希字段的值
jedis.hset("hash", "field1", "value1");
String value = jedis.hget("hash", "field1");// 获取哈希中所有字段和值
Map<String, String> hash = jedis.hgetAll("hash");
  • 设置和获取哈希字段的值:
jedis.hset("myhash", "field1", "value1");
String value = jedis.hget("myhash", "field1");
  • 获取哈希中所有字段和值:
Map<String, String> allFieldsAndValues = jedis.hgetAll("myhash");

5.有序集合类型

使用jedis进行有序集合的操作如下:

// 添加元素到有序集合
jedis.zadd("zset", 1, "member1");
jedis.zadd("zset", 2, "member2");// 获取有序集合的成员和分数
Set<Tuple> membersWithScores = jedis.zrangeWithScores("zset", 0, -1);// 根据分数范围获取有序集合的成员
Set<String> membersInRange = jedis.zrangeByScore("zset", 1, 2);
  • 添加元素到有序集合:
jedis.zadd("myzset", 1, "element1");
jedis.zadd("myzset", 2, "element2");
  • 获取有序集合的成员和分数:
Set<String> elements = jedis.zrange("myzset", 0, -1);
  • 根据分数范围获取有序集合的成员:
Set<String> elements = jedis.zrangeByScore("myzset", 1, 2);

4. Jedis 的事务操作

Jedis是Redis的Java客户端库,它提供了丰富的API来操作Redis数据库。在Jedis中,可以使用事务操作来执行一系列的Redis命令,并保证这些命令的原子性。

1.开启和提交事务

在 Jedis 中,可以使用 multi() 方法来开启一个事务,然后使用 exec() 方法来提交事务。在这两个方法之间的所有命令都会被放入事务队列中,等待 exec() 方法的调用。

Transaction t = jedis.multi();
t.set("foo", "bar");
t.exec();

2.回滚事务

Jedis 提供了 discard() 方法来回滚事务。注意,只有当在调用 multi() 方法之后,还没有调用 exec() 方法之前,才可以调用 discard() 方法。

Transaction t = jedis.multi();
t.set("foo", "bar");
t.discard();

3.监视键

watch() 方法可以用来监视一个或多个键,如果在事务执行之前这些键被其他命令所改变,那么事务将被打断。

jedis.watch("foo");
Transaction t = jedis.multi();
t.set("foo", "bar");
t.exec();

5. Jedis 的发布订阅操作

Jedis是 提供了丰富的功能来与Redis进行交互。其中,发布订阅是Jedis库的一项重要功能,允许客户端在订阅频道时接收发布到频道的消息。

1.发布消息

在 Jedis 中,可以使用 publish() 方法来发布消息。第一个参数是频道的名称,第二个参数是消息的内容。

Jedis jedis = new Jedis("localhost", 6379);
String channel = "myChannel";
String message = "Hello subscribers!";
jedis.publish(channel, message);
jedis.close();

2.订阅消息

订阅消息需要创建一个 JedisPubSub 对象,并重写它的 onMessage() 方法。然后使用 subscribe() 方法来订阅一个或多个频道。

Jedis jedis = new Jedis("localhost", 6379);
JedisPubSub jedisPubSub = new JedisPubSub() {@Overridepublic void onMessage(String channel, String message) {System.out.println("Received message: " + message + " from channel: " + channel);}
};
String channel = "myChannel";
jedis.subscribe(jedisPubSub, channel);
jedis.close();

定义了一个JedisPubSub对象,该对象覆盖了onMessage方法,用于处理接收到的消息。然后,指定要订阅的频道名称,并使用subscribe方法进行订阅。

需要注意的是,subscribe方法是阻塞的,它会一直等待直到接收到消息。因此,在实际应用中,通常会将订阅操作放在单独的线程中进行,以避免阻塞主线程。

在订阅消息后,如果需要取消订阅,可以使用unsubscribe方法。

jedis.unsubscribe(jedisPubSub, channel);

6. Jedis 的管道操作

Jedis提供了管道(pipeline)操作来批量执行多个命令,以减少网络延迟和提高性能。管道操作允许在客户端一次性发送多个命令到Redis服务器,并在服务器端依次执行这些命令,最后将结果一次性返回给客户端。

使用Jedis进行管道操作的步骤如下:

  1. 创建Jedis对象:首先,创建一个Jedis对象来与Redis服务器进行通信。
  2. 开启管道:通过调用Jedis对象的pipelined()方法来开启管道。
  3. 执行命令:使用Jedis对象执行需要批量执行的命令。可以使用Jedis对象的各种命令方法,如set()、get()等。
  4. 提交管道:通过调用Jedis对象的sync()方法来提交管道操作。这将一次性将所有命令发送到Redis服务器执行,并返回所有命令的结果。
  5. 关闭Jedis对象:最后,记得关闭Jedis对象以释放资源。在Jedis中,可以使用管道(Pipeline)来批量执行多个命令,以提高命令执行的效率。管道通过将多个命令打包在一起发送到Redis服务器,从而减少了网络I/O的开销。

使用Jedis管道的简单示例:

Pipeline pipeline = jedis.pipelined();for (int i = 0; i < 100; i++) {pipeline.set("key" + i, "value" + i);
}pipeline.sync();

创建了一个Pipeline对象,然后连续调用了100次set()方法。调用sync()方法会将之前调用的所有命令一次性发送到Redis服务器。

管道中的命令不保证原子性,也就是说,如果管道中的某个命令执行失败,不会影响到其他命令的执行。如果需要保证一组命令的原子性,应该使用Redis的事务功能。

此外,管道中的命令默认是不会立即返回结果的,如果需要获取命令的返回结果,可以使用syncAndReturnAll()方法来替代sync()方法。这将返回一个List,其中包含了管道中每个命令的返回结果。
使用Jedis进行管道操作的示例代码

Jedis jedis = new Jedis("localhost", 6379);
Pipeline pipeline = jedis.pipelined();// 执行多个命令
pipeline.set("key1", "value1");
pipeline.get("key1");
pipeline.hset("hashKey", "field1", "value2");// 提交管道
List<Object> results = pipeline.syncAndReturnAll();// 处理结果
for (Object result : results) {System.out.println(result);
}// 关闭Jedis对象
jedis.close();

创建了一个Jedis对象,并通过调用pipelined()方法开启了管道。执行三个命令:设置一个字符串类型的键值对、获取该键的值,以及设置一个哈希类型的字段值对。最后,通过调用syncAndReturnAll()方法提交管道操作,并返回了所有命令的结果。
可以通过遍历结果列表来处理每个命令的返回值。最后,记得关闭Jedis对象以释放资源。

使用管道操作可以显著提高性能,特别是在需要批量执行多个命令时。然而,需要注意的是,管道操作是无法使用事务的。如果需要支持事务操作,可以考虑使用Redis的事务功能。

7. Jedis 的连接池配置和使用

在实际使用中,通常会使用连接池来管理Jedis连接。Jedis的连接池使用Apache Commons Pool2实现。

基本过程是:

创建了一个JedisPoolConfig对象,并设置了各种连接池参数。然后使用这个配置对象,以及Redis服务器的地址和端口,创建了一个JedisPool对象。

在需要使用Jedis连接的地方,使用getResource()方法从连接池中获取一个Jedis连接。这个连接使用完毕后,Jedis会自动将其归还到连接池中。

注意,在获取Jedis连接时,使用了Java的try-with-resources语句,这样可以确保无论是否发生异常,Jedis连接都会被正确关闭。

配置和使用Jedis连接池的示例:

1.配置连接池参数:

JedisPoolConfig poolConfig = new JedisPoolConfig();
// 最大连接数
poolConfig.setMaxTotal(128);
// 最大空闲连接数
poolConfig.setMaxIdle(64);
// 最小空闲连接数
poolConfig.setMinIdle(10);
// 获取连接时的最大等待毫秒数
poolConfig.setMaxWaitMillis(2000);
// 在获取连接的时候检查有效性
poolConfig.setTestOnBorrow(true);

2.创建Jedis连接池:

JedisPool jedisPool = new JedisPool(poolConfig, "localhost", 6379);

从连接池中获取Jedis连接的代码如下:

try (Jedis jedis = jedisPool.getResource()) {// 使用Jedis连接执行命令jedis.set("key", "value");System.out.println(jedis.get("key"));
} catch (Exception e) {// 异常处理
}

8. Jedis 的异常处理

处理Jedis连接或命令执行异常的一般方法是使用try/catch块来捕获并处理这些异常。
在使用Jedis时,我们需要对连接异常和命令执行异常进行适当的处理。

1. 处理连接异常

在创建连接池对象时,可以设置连接超时时间和读写超时时间,以及设置连接失败重试次数。
在获取Jedis连接对象时,可以捕获JedisConnectionException异常来处理连接异常,例如重新获取连接或进行其他操作。
在使用Jedis连接对象进行Redis操作时,如果发生连接异常,可以捕获JedisConnectionException异常,并根据具体情况进行处理,例如重新获取连接或进行其他操作。
示例代码如下:

JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(100);
config.setMaxIdle(50);
config.setMinIdle(10);
config.setTestOnBorrow(true);
config.setTestOnReturn(true);JedisPool jedisPool = new JedisPool(config, "localhost", 6379, 5000, "password");Jedis jedis = null;
try {jedis = jedisPool.getResource();// 进行Redis操作
} catch (JedisConnectionException e) {// 处理连接异常,例如重新获取连接或进行其他操作
} finally {if (jedis != null) {jedis.close();}
}

Jedis连接异常通常是由于网络问题或者Redis服务器问题引起的。当尝试获取一个Jedis连接,或者使用一个已经获取的连接进行操作时,都可能触发这种异常。

2. 处理命令执行异常:

当尝试执行一个无效的Redis命令,或者传递给命令的参数不正确时,Jedis会抛出一个JedisDataException。

Jedis jedis = new Jedis("localhost", 6379);
try {jedis.hset("key", "field", "value");
} catch (JedisDataException e) {// 命令执行异常处理
} finally {jedis.close();
}

如果hset命令的参数不正确,例如key不存在,或者field已经存在,那么会抛出一个JedisDataException。需要捕获并处理这个异常。

  1. 在使用Jedis连接对象执行Redis命令时,可能会发生JedisDataException异常,例如命令格式不正确或参数类型不匹配等。
  2. 在使用Jedis连接对象执行Redis命令时,也可能会发生JedisException异常,例如Redis服务器出现问题或连接被关闭等。
  3. 在捕获这些异常时,可以根据具体情况进行处理,例如打印错误信息、回滚事务或进行其他操作。

示例代码如下:

try {jedis.set("key", "value");
} catch (JedisDataException e) {// 处理命令执行异常,例如命令格式不正确或参数类型不匹配等
} catch (JedisException e) {// 处理命令执行异常,例如Redis服务器出现问题或连接被关闭等
}

9.Jedis 的性能优化

使用连接池:在并发环境下,频繁地建立和释放连接会消耗大量的系统资源,影响应用性能。Jedis提供了连接池功能,可以复用已经建立的连接,减少连接的开销。

JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");
Jedis jedis = null;
try {jedis = pool.getResource();// 使用jedis进行Redis操作
} finally {if (jedis != null) {jedis.close(); // 实际上是将连接返还给连接池,而不是关闭连接}
}

批量执行命令:如果需要执行多个Redis命令,那么可以使用Jedis的管道(Pipeline)功能,一次性发送所有命令,然后一次性接收所有结果。这样可以避免每次命令执行都需要进行一次网络通信。

Jedis jedis = new Jedis("localhost");
Pipeline pipeline = jedis.pipelined();
pipeline.set("key1", "value1");
pipeline.set("key2", "value2");
pipeline.sync();

在上述代码中,两个set命令会一次性发送到Redis服务器,然后sync方法会一次性接收两个命令的结果。这样可以避免每次命令执行都需要进行一次网络通信,减少了网络开销。

  1. 使用正确的数据结构和命令:Redis提供了多种数据结构和命令,根据具体的业务需求,选择最合适的数据结构和命令,可以大大提高性能。
  2. 避免长时间操作:对于耗时较长的操作,尽量避免在主线程中执行,可以考虑使用异步处理或者使用多线程处理。
  3. 适当使用持久化:根据业务需求,可以选择适当的持久化策略,例如RDB或者AOF。RDB性能较高,但是可能会丢失最近一段时间的数据;AOF性能较低,但是数据更安全。
  4. 尽量避免使用Keys命令:Keys命令会遍历整个数据库,对性能影响较大。尽量使用Scan命令代替。
     

示例:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Pipeline;public class JedisExample {public static void main(String[] args) {// 创建Jedis实例,连接本地RedisJedis jedis = new Jedis("localhost");// 设置键值jedis.set("key", "value");// 获取键值System.out.println(jedis.get("key"));// 使用连接池JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");Jedis jedisFromPool = null;try {jedisFromPool = pool.getResource();// 使用jedisFromPool进行Redis操作jedisFromPool.set("key1", "value1");System.out.println(jedisFromPool.get("key1"));} finally {if (jedisFromPool != null) {jedisFromPool.close();  // 实际上是将连接返还给连接池,而不是关闭连接}}// 使用PipelinePipeline pipeline = jedis.pipelined();pipeline.set("key2", "value2");pipeline.set("key3", "value3");pipeline.sync(); // 一次性发送所有命令// 关闭Jedisjedis.close();}
}

相关文章:

【征服redis3】一文征服redis的jedis客户端

使用数据库的时候&#xff0c;我们可以用JDBC来实现mysql数据库与java程序之间的通信&#xff0c;为了提高通信效率&#xff0c;我们有了数据库连接池比如druid等等。而我们想通过Java程序控制redis&#xff0c;同样可以借助一些工具来实现&#xff0c;这就是redis客户端&#…...

Python如何操作RabbitMQ实现direct关键字发布订阅模式?有录播直播私教课视频教程

direct关键字发布订阅模式 基本用法 发布者 import json from rabbitmq import pika import rabbitmq# 建立连接 credentials rabbitmq.PlainCredentials(zhangdapeng,zhangdapeng520, ) # mq用户名和密码 connection_target rabbitmq.ConnectionParameters(host127.0.0.…...

如何应用数据图表了解家里的 Unifi 网络状况?

1. 前言 自从之前写了《【让 IT 更简单】使用 Ubiquiti 全家桶对朋友家进行网络改造》 《【Rethinking IT】如何结合 Unifi 和 MikroTik 设备打造家庭网络》两篇文章后&#xff0c;相信给各位正在用 Unifi 或者打算使用 Unifi 的朋友应该有所帮助。 那么&#xff0c;今天我就…...

新版K8s:v1.28拉取Harbor仓库镜像以及本地镜像(docker弃用改用containerd,纯纯踩坑)

目录 一、项目概述二、环境三、项目样式Harborkuboard运行样式 四、核心点Harbor安装config.toml文件修改(containerd)ctr、nerdctl相关命令kuboard工作负载 五、总结 一、项目概述 使用Kuboard作为k8s集群的管理平台&#xff0c;Harbor作为镜像仓库&#xff0c;拉取Harbor镜像…...

Unity URP切换品质和Feature开关的性能问题

现在对我的项目进行安卓端发布&#xff0c;需要切换品质和一些Feature开关。 我是这样做的。 划分品质 首先Renerer分为2个Android和PC&#xff0c;图中其他不用参考。 每个副本的URP Asset分为pc和android&#xff0c;例如图中的 hall和hall_android。 我们可以看到hall用的…...

jmeter解决返回unicode编辑

一般乱码有两种方法来解决&#xff1a; 1、修改配置文件jmeter.properties中默认编码格式ISO-8859-1&#xff08;不支持中文),修改为utf-8 sampleresult.default.encoding utf-82、添加BeanShell PostProcessor加入 prev.setDataEncoding("utf-8")3、还有一种返回…...

C# 基础入门

第二章 C# 语法基础 2-1 C# 中的关键字 关键字&#xff0c;是一些被C#规定了用途的重要单词。 在Visual Studio的开发环境中&#xff0c;关键字被标识为蓝色&#xff0c;下图代码中&#xff0c;用红方框圈出的单词就是关键字。 关键字 class &#xff0c;这个关键字的用途是…...

PHP 支付宝(单笔转账到银行账户接口)

alipay.fund.trans.tobank.transfer(单笔转账到银行账户接口) 小程序文档 - 支付宝文档中心 一、下载支付宝SDK&#xff0c;现有版本v1、v2、v3 https://github.com/alipay/alipay-sdk-php-all github 慢的话&#xff0c;DNS 直达即可 140.82.112.3 github.com 【host文…...

【Java万花筒】Java安全卫士:从密码学到Web应用攻击

Java安全锦囊&#xff1a;从Web应用攻击到加密算法&#xff0c;助你建立强固的开发堡垒 前言 在当今数字化时代&#xff0c;安全性至关重要&#xff0c;特别是对于Java开发者而言。本文将深入探讨Java安全与加密领域的关键库和技术&#xff0c;包括Bouncy Castle、Jasypt、Ke…...

redis安装-Linux为例

可以下载一个Shell或者MobaXterm工具&#xff0c;便于操作 在redis官网下载压缩包 开始安装 安装依赖 yum install -y gcc tcl切换目录 切换目录后直接把redis安装包拖到/user/local/src/下 cd /user/local/src/解压然后安装 #解压 tar -zxvf redis-7.2.4.tar.gz #安装 …...

iOS长按时无法保存图片问题解决方案

在使用iOS设备的用户中&#xff0c;相信很多人都有过在浏览网页时遇到长按时无法保存图片的困扰。这主要是因为网页开发者为了保护版权或隐私&#xff0c;默认屏蔽掉了图片长按时保存的功能。 具体来说&#xff0c;问题出在-webkit-touch-callout这个CSS属性上。这个属性用于定…...

Datawhale 强化学习笔记(一)

参考 在线阅读文档 github 教程 开源框架 JoyRL datawhalechina/joyrl: An easier PyTorch deep reinforcement learning library. (github.com) 策略梯度算法的两种不同的推导版本。 强化学习中的一些核心问题&#xff0c;比如优化值的估计、解决探索与利用等问题。 从传统强…...

首届PolarDB开发者大会在京举办,阿里云李飞飞:云数据库加速迈向智能化

1月17日&#xff0c;阿里云PolarDB开发者大会在京举办&#xff0c;中国首款自研云原生数据库PolarDB发布“三层分离”新版本&#xff0c;基于智能决策实现查询性能10倍提升、节省50%成本。此外&#xff0c;阿里云全新推出数据库场景体验馆、训练营等系列新举措&#xff0c;广大…...

003-90-15【SparkSQLDFDS】慈航寺庙山脚下八卦田旁油菜花海深处人家王大爷家女儿用GPT学习DataSet的基本操作

003-90-14【SparkSQL&DF&DS】慈航寺庙山脚下八卦田旁油菜花海深处人家王大爷家女儿用GPT学习DataSet的基本操作 【SparkSQL&DF&DS】Dataset 的创建和使用 【SparkSQL&DF&DS】2,Dataset 的创建和使用1&#xff0c; 创建2, show3, map4, as5, select6 f…...

代码随想录-刷题第五十七天

42. 接雨水 题目链接&#xff1a;42. 接雨水 思路&#xff1a;本题十分经典&#xff0c;使用单调栈需要理解的几个问题&#xff1a; 首先单调栈是按照行方向来计算雨水&#xff0c;如图&#xff1a; 使用单调栈内元素的顺序 从大到小还是从小到大呢&#xff1f; 从栈头&…...

flutter 播放SVGA动图

SVGAPlayer-Flutter&#xff1a;这是一个轻量级的动画渲染库&#xff0c;可以通过Flutter CustomPainter原生渲染动画&#xff0c;为您带来高性能&#xff0c;低成本的动画体验123。 您可以按照以下步骤使用 SVGAPlayer-Flutter 插件&#xff1a; 1.在 pubspec.yaml 文件中添…...

鸿蒙开发软件汉化

一、打开设置 File>Settings>Plugins>Marketplace&#xff0c;输入Chinese搜索插件&#xff08;有的人是搜不到的&#xff09;&#xff0c;但别慌&#xff0c;选择Marketplace傍边的 Installed 按钮&#xff0c;里面就有Chinese插件(如果搜索出来的东西比较多往下就可…...

Three.js Tri-panner (三面贴图) 材质 两种实现方式

文章目录 介绍自定义shaderNodeMaterial骨骼材质特殊处理 介绍 Tri-panner 在babylonjs中有支持 但是three.js目前的基础材质并不支持 需要自己定义shader 或者使用目前还没有什么完善的文档的 NodeMaterial 下面展示两种实现方式 自定义shader /*** description: 替换三角面…...

Docker部署Flask项目

Docker部署Flask项目 一、准备项目代码二、编写Dockerfile三、服务器部署 一、准备项目代码 这里写了一个简单的Flask的demo&#xff0c;源代码如下&#xff1a; from flask import Flaskapp Flask(__name__)app.route("/") def index():return "<h1 styl…...

Git将某个文件合并到指定分支

企业开发中&#xff0c;经常会单独拉分支去做自己的需求开发&#xff0c;但是某些时候一些公共的配置我们需要从主线pull&#xff0c;这时候整个分支merge显然不合适 1.切换至待合并文件的分支 git checkout <branch>2.将目标分支的单个文件合并到当前分支 git checkou…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...