Jedis介绍
首先,我们知道redis其实是一个数据库,其并不能被java代码所控制。那么,为了能在java代码中操作redis数据库,那就必须要有一个连接层来控制redis。
如何使用jedis
jedis中的方法设计与原生redis命令几乎是一样的,因此,查询redis的命令手册就能够知道jedis中方法如何书写,那我们先看看一些基础命令。
// 通过jedis实例获取连接并操作redis
public class JedisExample {
@Test
public void testFirstExample() {
// 连接redis
Jedis jedis = new Jedis("localhost", 6379);
// Jedis jedis = new Jedis("localhost"); // 默认6379端口
// string类型
jedis.set("name", "demo");
String name = jedis.get("name");
// list类型
jedis.lpush("myList", "hello");
jedis.rpush("myList", "world");
String lpopVal = jedis.lpop("myList");
String rpopVal = jedis.rpop("myList");
// set类型
jedis.sadd("mySet", "123");
jedis.sadd("mySet", "456");
jedis.sadd("mySet", "789");
jedis.srem("mySet", "789");
jedis.scard("mySet");
// zset类型
jedis.zadd("myZset", 99, "X");
jedis.zadd("myZset", 90, "Y");
jedis.zadd("myZset", 97, "Z");
Double zscore = jedis.zscore("myZset", "Z");
// 其他
jedis.incr("intKey");
jedis.incrBy("intKey", 5);
jedis.del("intKey");
// 触发持久化
// jedis.save();
// jedis.bgsave()
// 关闭连接
jedis.close();
}
}
// 使用jedis数据库连接池技术,并获取jedis实例
public class JedisPoolExample {
@Test
public void testUsePool() {
// 配置连接池
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(20);
config.setMaxIdle(10);
config.setMinIdle(5);
// 创建连接池
JedisPool jedisPool = new JedisPool(config, "localhost", 6379);
Jedis jedis = jedisPool.getResource();
// 使用jedis进行操作
jedis.set("name", "otherNameVal");
// 用完之后,一定要手动关闭连接(归还给连接池)
jedis.close();
}
}
jedis注意事项
jedis并不是一个线程安全的类,故不应该在多线程环境中共用一个Jedis实例。但是,也应该避免直接创建多个Jedis实例,因为这种做法会导致创建过多的socket连接(一个jedis就对应了一个连接),性能不高。 要保证线程安全且获得较好的性能,可以使用JedisPool。 JedisPool是一个连接池,既可以保证线程安全,又可以保证了较高的效率。
springboot如何整合redis
我们要学习springboot如何整合的,那就必须要先去spring的官网上查看相关说明,redis作为一种持久化技术,我们很容易的可以想到spring data整合,那么参考spring data就可以看到相应的说明。
这里使用Maven倒入springboot-redis的包,这里可以去仓库查询合适的版本号,我这里以springboot 2.1.9.RELEASE作为例子的版本
org.springframework.boot
spring-boot-starter-data-redis
2.1.9.RELEASE
查看springboot中redis的自动配置
下面就是该配置类中的内容
RedisAutoConfiguration.class
@Configuration
@ConditionalOnClass(RedisOperations.class)
// 这里通过读取RedisProperties类获取配置信息
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
// 这个注解就是说在没有找打其他名为redisTemplate的类就使用该默认配置
// 这里返回一个redisTemplate,通过该redisTemplate就可以操作redis
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate
RedisConnectionFactory
是一个接口,其中提供了两个实现
public interface RedisConnectionFactory extends PersistenceExceptionTranslator {
/**
* Provides a suitable connection for interacting with Redis.
*
* @return connection for interacting with Redis.
*/
RedisConnection getConnection();
/**
* Provides a suitable connection for interacting with Redis Cluster.
*
* @return
* @since 1.7
*/
RedisClusterConnection getClusterConnection();
/**
* Specifies if pipelined results should be converted to the expected data type. If false, results of
* {@link RedisConnection#closePipeline()} and {RedisConnection#exec()} will be of the type returned by the underlying
* driver This method is mostly for backwards compatibility with 1.0. It is generally always a good idea to allow
* results to be converted and deserialized. In fact, this is now the default behavior.
*
* @return Whether or not to convert pipeline and tx results
*/
boolean getConvertPipelineAndTxResults();
/**
* Provides a suitable connection for interacting with Redis Sentinel.
*
* @return connection for interacting with Redis Sentinel.
* @since 1.4
*/
RedisSentinelConnection getSentinelConnection();
}
RedisProperites.class
提供了配置的相关信息
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
/**
* Database index used by the connection factory.
*/
private int database = 0;
/**
* Connection URL. Overrides host, port, and password. User is ignored. Example:
* redis://user:[email protected]:6379
*/
private String url;
/**
* Redis server host.
*/
private String host = "localhost";
/**
* Login password of the redis server.
*/
private String password;
/**
* Redis server port.
*/
private int port = 6379;
/**
* Whether to enable SSL support.
*/
private boolean ssl;
/**
* Connection timeout.
*/
private Duration timeout;
private Sentinel sentinel;
private Cluster cluster;
private final Jedis jedis = new Jedis();
private final Lettuce lettuce = new Lettuce();
// 省略了get & set方法
}
RedisTemplate有何用
好了,我们知道我们配置的最终目的都是在生成这个RedisTemplate,那么这个东西到底有什么用呢?
其实,这个东西就是spring给我们提供的一种封装。我们应该还学过一种类似的——JDBCTemplate,使用该类来操作数据库。那么同样,spring也提供了redisTemplate用于在springboot中操作redis。进而避免直接使用jedis或者lettuce,通过再加一层的方式屏蔽组件的差异。
如何自定义自己的RedisTemplate
好了,既然知道redisTemplate是什么,我们就要学会如何定制他,以让他满足我们的使用。
首先,看看这个东西里面到底是什么?
public class RedisTemplate extends RedisAccessor implements RedisOperations, BeanClassLoaderAware {
private boolean enableTransactionSupport = false;
private boolean exposeConnection = false;
private boolean initialized = false;
private boolean enableDefaultSerializer = true;
private @Nullable RedisSerializer> defaultSerializer;
private @Nullable ClassLoader classLoader;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer keySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer valueSerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashKeySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashValueSerializer = null;
private RedisSerializer stringSerializer = RedisSerializer.string();
private @Nullable ScriptExecutor scriptExecutor;
private final ValueOperations valueOps = new DefaultValueOperations<>(this);
private final ListOperations listOps = new DefaultListOperations<>(this);
private final SetOperations setOps = new DefaultSetOperations<>(this);
private final ZSetOperations zSetOps = new DefaultZSetOperations<>(this);
private final GeoOperations geoOps = new DefaultGeoOperations<>(this);
private final HyperLogLogOperations hllOps = new DefaultHyperLogLogOperations<>(this);
private final ClusterOperations clusterOps = new DefaultClusterOperations<>(this);
}
因为实在太长了,这里就没有列出方法,而是列出了其中的一些属性。我们知道方法大多数都是用于操作redis的,而真正重要的应该是其中的属性
我们可以看到,这个类中大多数都在描述一个东西——Serializer,即序列化。 为什么要讨论这个东西?
redis并不是java,并不能存储对象这种东西,因此,最后底层一个java对象要被保存就必须通过序列化的技术。
那么springboot到底提供了几种序列化方式呢?