springboot整合redis

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的自动配置

image.png

下面就是该配置类中的内容

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 redisTemplate(RedisConnectionFactory redisConnectionFactory)
          throws UnknownHostException {
      RedisTemplate template = new RedisTemplate<>();
              // 这里设置了连接工厂,通过定义不同的工厂可以用不同的组件连接redis
              // springboot默认配置了两种连接手段
              // 1. jedis(springboot 1.X)
              // 2. lettuce(springboot 2.X)
      template.setConnectionFactory(redisConnectionFactory);
      return template;
  }
      
      // 该类是单独为String设计的RedisTemplate
  @Bean
  @ConditionalOnMissingBean
  public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
          throws UnknownHostException {
      StringRedisTemplate template = new StringRedisTemplate();
      template.setConnectionFactory(redisConnectionFactory);
      return template;
  }

}

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();
}
image.png

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到底提供了几种序列化方式呢?

image.png

你可能感兴趣的:(springboot整合redis)