SpringData Redis etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
SpringData Redis etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

9 Ağustos 2023 Çarşamba

SpringData Redis LettuceClientConfiguration Sınıfı

Giriş
Şu satırı dahil ederiz
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
readFrom metodu
Açıklaması şöyle. Okuma işleminin nerede yapılacağını belirtir.
All ReadFrom settings except MASTER may return stale data because replicas replication is asynchronous and requires some delay. You need to ensure that your application can tolerate stale data.

Setting                 Description 
MASTER                 Default mode. Read from the current master node.

MASTER_PREFERRED         Read from the master, but if it is unavailable, read from replica nodes.

REPLICA         Read from replica nodes.

REPLICA_PREFERRED        Read from the replica nodes, but if none is unavailable, read from the master.

LOWEST_LATENCY Read from any node of the cluster with the lowest latency.

ANY                         Read from any node of the cluster.

ANY_REPLICA         Read from any replica of the cluster.
Örnek
Şöyle yaparız
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
    .commandTimeout(redisCommandTimeout)
    .readFrom(ReadFrom.REPLICA_PREFERRED)
    .build();

27 Mart 2023 Pazartesi

SpringData Redis ZSetOperations Sınıfı

removeRangeByScore metodu
Örnek
Şöyle yaparız
public Set<String> rateLimiter(String id) {
  String key = "rate-" + id;
  long currentTime = System.currentTimeMillis();
  long slidingWindowTime = 60_000L; //1 min, This is basically the rate limit time.

  List<Object> valOuter =  redisTemplate.execute(new SessionCallback<List<Object>>() {
    @Override
    public List<Object> execute(@NotNull RedisOperations operations) throws DataAccessException {
      operations.multi();
      operations.opsForZSet().removeRangeByScore(key, 0, currentTime - slidingWindowTime);
      operations.opsForZSet().add(key, Long.toString(currentTime), currentTime);
      operations.expire(key, currentTime + slidingWindowTime, TimeUnit.MILLISECONDS);
      redisTemplate.opsForZSet().range(key, 0, -1);
      return operations.exec();
    }
  });
  log.info("EmployeeDao: rateLimiter: {}", valOuter);

  return valOuter != null ? (Set<String>) valOuter.get(valOuter.size()-1) : Collections.emptySet() ;
}


24 Şubat 2023 Cuma

SpringData Redis Redission Sınıfı

Giriş
Redisson için açıklama şöyle
Redisson adopts the nety framework based on NIO, which can not only be used as the underlying driver client of Redis, but also can send redis commands in synchronous, asynchronous, asynchronous stream or pipeline forms, execute and process Lua scripts, and process the returned results.
Maven
Şu satırı dahil ederiz
<dependency>
   <groupId>org.redisson</groupId>
   <artifactId>redisson</artifactId>
   <version>3.17.6</version>
</dependency>
Örnek
Şöyle yaparız
@RequiredArgsConstructor
@Configuration
public class RedissonConfig {

  @Bean
  public RedissonClient redissionClient() {
    Config config = new Config();
    config.useSingleServer().setAddress("redis://127.0.0.1:6379");
    return Redisson.create(config);
 }

@Bean
public RedisTemplate<String, Object> redisTemplate( RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new JdkSerializationRedisSerializer());
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
redisTemplate.setEnableTransactionSupport(true);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}

SpringData Redis RedisStandaloneConfiguration Sınıfı

Giriş
Şu satırı dahil ederiz
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
Eğer ayarları application.properties ile yapmak istemiyorsak bu sınıfı yaratmak gerekir. 
Hem LettuceConnectionFactory  hem de JedisConnectionFactory için bu sınıf gerekir

JedisConnectionFactory
Örnek
Şöyle yaparız. Bu kod ile artık RedisTemplate kullanabiliriz.
@Configuration
@EnableRedisRepositories
public class RedisConfig {

  @Bean
  public JedisConnectionFactory connectionFactory(){
    RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
    configuration.setHostName("localhost");
    configuration.setPort(6379);
    return new JedisConnectionFactory(configuration);
  }

  @Bean
  @Primary
  public RedisTemplate<String, Object> redisTemplate(){
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory());
    template.setKeySerializer(new StringRedisSerializer());
    template.setHashKeySerializer(new StringRedisSerializer());
    template.setHashKeySerializer(new JdkSerializationRedisSerializer());
    template.setHashValueSerializer(new JdkSerializationRedisSerializer());
    template.setEnableTransactionSupport(true);
    template.afterPropertiesSet();

    return template;
  }
}


4 Ocak 2023 Çarşamba

SpringData Redis Stream - Persistent Pub/Sub

Giriş
ReactiveRedisTemplate.opsForStream() ile gerçekleşiyor

Pending mesajları almak için şöyle yaparız
PendingMessages pendingMessages = redisTemplate
  .opsForStream()
  .pending("purchase-events", "purchase-events", Range.unbounded(), 100L);
Örnek
Elimizde şöyle bir kod olsun
@Configuration
public class RedisStreamConfiguration {
  @Value("${redis.node.ip}")
  private String ip;alo
  @Value("${redis.node.port}")
  private int pageManagerValues;alo
  @Value("${redis.node.password}")
  private String password;

  private RedisClusterConfiguration redisClusterConfiguration() {
    RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
    redisClusterConfiguration.addClusterNode(new RedisNode(ip, port));
    redisClusterConfiguration.setPassword(password);
    return redisClusterConfiguration;
  }
 
  @Bean
  public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
    return new LettuceConnectionFactory(redisClusterConfiguration());
  }
}
Config'in devamı şöyle olsun
@Configuration
public class RedisStreamConfiguration {
 
  @Bean
  public ReactiveRedisTemplate<String, String> reactiveRedisTemplate(
    @Qualifier("reactiveRedisConnectionFactory")ReactiveRedisConnectionFactory factory) {
    
    StringRedisSerializer keySerializer = new StringRedisSerializer();
    Jackson2JsonRedisSerializer<String> valueSerializer = new Jackson2JsonRedisSerializer<>(String.class);

    RedisSerializationContext.RedisSerializationContextBuilder<String, String> builder =
      RedisSerializationContext.newSerializationContext(keySerializer);

    RedisSerializationContext<String, String> context = builder .value(valueSerializer).build();
    return new ReactiveRedisTemplate<>(factory, context);
  }
  @Bean
  public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
    return new LettuceConnectionFactory(redisClusterConfiguration());
  }
}
Publisher şöyle
@RequiredArgsConstructor
@Service
public class BasketStreamService {

  @Value("${stream.key}")
  private String streamKey;
  private final ReactiveRedisTemplate<String, String> reactiveRedisTemplate;
  private Gson gson;

  @PostConstruct
  public void init(){
    gson = new Gson();
  }

  public void publishEvent(Basket basket){

    ObjectRecord<String, String> objectRecord = StreamRecords.newRecord()
      .ofObject(gson.toJson(basket))
      .withStreamKey(streamKey);
    this.reactiveRedisTemplate
      .opsForStream()
      .add(objectRecord)
      .block(); // or subscribe
    }
}
Consumer şöyle
@Component
@RequiredArgsConstructor
public class RedisConsumeService {

  @Value("${stream.key}")
  private String streamKey;

  private final StreamListener<String, ObjectRecord<String, String>> streamListener;

  @Bean
  public Subscription subscription(RedisConnectionFactory redisConnectionFactory) 
  throws UnknownHostException {
  
    StreamMessageListenerContainer
      .StreamMessageListenerContainerOptions<String, ObjectRecord<String, String>>
      options = 
        StreamMessageListenerContainer
        .StreamMessageListenerContainerOptions
        .builder()
        .pollTimeout(Duration.ofSeconds(1))
        .targetType(String.class)
        .build();

    StreamMessageListenerContainer<String, ObjectRecord<String, String>>  
    listenerContainer = 
      StreamMessageListenerContainer
        .create(redisConnectionFactory, options);

    Subscription subscription = listenerContainer.receive(
    Consumer
      .from(streamKey, InetAddress.getLocalHost()
      .getHostName()),
    StreamOffset.create(streamKey, ReadOffset.lastConsumed()),
    streamListener);

    listenerContainer.start();
    return subscription;
  }
}
Listener şöyle
@Service
@RequiredArgsConstructor
@Slf4j
public class BasketProductConsumer implements 
  StreamListener<String, ObjectRecord<String, String>> {

  private final RedisTemplate<String, String> shRedisTemplate;
  private final SuggestionService suggestionService;
  private Gson gson;
  @PostConstruct
  public void init(){
    gson = new Gson();
  }

  @SneakyThrows
  @Override
  public void onMessage(ObjectRecord<String, String> record) {
       
    Basket basket = gson.fromJson(record.getValue(), Basket.class);
    List<Product> suggested = suggestionService.getSuggestion(basket);

    basket.setSuggestionProduct(suggested);

    shRedisTemplate.opsForHash()
      .put(basket.getSessionId(), "basket", gson.toJson(basket));
    Long ack = shRedisTemplate.opsForStream()
      .acknowledge("purchase-events", record);
  }
}




SpringData Redis Pub/Sub - Persistent Değildir Consumer Çalışmıyorsa Mesajı Alamaz

Örnek
Elimizde şöyle bir topic olsun
@Bean
public ChannelTopic channelTopic(){
  return new ChannelTopic("pubsub:pageupdate");
}
Publisher için şöyle yaparız
// Publisher
@Service
@RequiredArgsConstructor
public class RedisPublishService {
  
private final ReactiveRedisTemplate reactiveRedisTemplate;
  private final ChannelTopic channelTopic;

    
  public void publish(List<String> updatedPageList){
    reactiveRedisTemplate.convertAndSend(channelTopic.getTopic(), updatedPageList).block();
  }
}
Consumer için şöyle yaparız
// Consumer
@Slf4j
public class RedisListenerService implements MessageListener {
  @Override
  public void onMessage(Message message, byte[] pattern) {
    log.info("Consumed on pub sub {}", message);
    TODO: implement your logic
  }
}

@Bean
public MessageListener messageListener(){
  return new MessageListenerAdapter(new RedisListenerService());
}

@Bean
public RedisMessageListenerContainer redisMessageListenerContainer(){
  RedisMessageListenerContainer container = new RedisMessageListenerContainer();
  container.setConnectionFactory(redisConnectionFactory());
  container.addMessageListener(messageListener(), channelTopic());
  return container;
}

29 Aralık 2022 Perşembe

SpringCache Redis RedisCacheManager Sınıfı

Giriş
Şu satırı dahil ederiz.
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
Çoğunlukla bu sınıfı yaratmak için RedisCacheManager.builder() çağrısı ile RedisCacheManagerBuilder kullanılıyor

constructor - RedisCacheWriter + RedisCacheConfiguration

Örnek
Şöyle yaparız
@Bean("cache-manager") public RedisCacheManager redisCacheManager(RedisTemplate<String, Object> redisTemplate) { var redisCacheWriter = RedisCacheWriter .nonLockingRedisCacheWriter(Objects.requireNonNull( redisTemplate.getConnectionFactory())); var redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer( redisTemplate.getValueSerializer())); return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration); }

20 Ağustos 2021 Cuma

SpringCache Redis RedisCacheConfiguration Sınıfı

Giriş
Şu satırı dahil ederiz
import org.springframework.data.redis.cache.RedisCacheConfiguration;
disableCachingNullValues metodu
Örnek
Şöyle yaparız
@Bean
public RedisCacheConfiguration cacheConfiguration() {
  return RedisCacheConfiguration.defaultCacheConfig()
    .entryTtl(Duration.ofMinutes(60))
    .disableCachingNullValues()
    .serializeValuesWith(RedisSerializationContext.SerializationPair
      .fromSerializer(new GenericJackson2JsonRedisSerializer()));
    }
}
entryTtl metodu
Örnek
Açıklaması şöyle
By setting the expiration time of different keys in the configuration file, the effect of customizing the key expiration time can be achieved.
Şöyle yaparız
@Autowired
private MyProperties properties;
 
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
  RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration
    .defaultCacheConfig()
    .entryTtl(Duration.ofMinutes(10)).disableCachingNullValues();
 
  RedisCacheWriter redisCacheWriter = RedisCacheWriter
    .nonLockingRedisCacheWriter(connectionFactory);
 
  ImmutableSet.Builder<String> cacheNames = ImmutableSet.builder();
  ImmutableMap.Builder<String, RedisCacheConfiguration> cacheConfig = 
    ImmutableMap.builder();
  for (Map.Entry<String, Duration> entry : properties.getInitCaches().entrySet()) {
    cacheNames.add(entry.getKey());
    cacheConfig.put(entry.getKey(), defaultCacheConfig.entryTtl(entry.getValue()));
  }
 
  return RedisCacheManager.builder(redisCacheWriter)
    .cacheDefaults(defaultCacheConfig)
    .initialCacheNames(cacheNames.build())
    .withInitialCacheConfigurations(cacheConfig.build())
    .build();
}
Properties dosyası şöyledir
initCaches:
  fooboo: 10m
  fooboo1: 1h
Properties sınıfı şöyledir
@ConfigurationProperties
public class MyProperties {
 
   private final Map<String, Duration> initCaches = Maps.newHashMap();
 
   public Map<String, Duration> getInitCaches() {
     return initCaches;
   }
}
serializeKeysWith ve serializeValuesWith metodları
Örnek - JSON
Şöyle yaparız. Burada ObjetMapper parametresi ile Spring'e ait olan bean kullanılıyor. Yeni bir tane yaratmaya gerek yok
@Configuration
@EnableCaching
class CachingConfig{

  @Bean
  fun cacheConfiguration(mapper: ObjectMapper): RedisCacheConfiguration {
    return RedisCacheConfiguration.defaultCacheConfig()
      .entryTtl(Duration.ofMinutes(5))
      .disableCachingNullValues()
      .serializeValuesWith(
        SerializationPair.fromSerializer(GenericJackson2JsonRedisSerializer(mapper))
      )
  }
}
Eğer Spring'e ait olan bean'ini kopyasın alıp yeni module takmak istersek şöyle yaparız
@Bean
fun cacheConfiguration(mapper: ObjectMapper): RedisCacheConfiguration {
  val myMapper = mapper.copy()
    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
    .registerModule(
      Hibernate6Module()
        .enable(Hibernate6Module.Feature.FORCE_LAZY_LOADING)
        .enable(Hibernate6Module.Feature.REPLACE_PERSISTENT_COLLECTIONS)
      )
      .activateDefaultTyping(
        jacksonObjectMapper().polymorphicTypeValidator,
        ObjectMapper.DefaultTyping.EVERYTHING,
        JsonTypeInfo.As.PROPERTY
      )
  return RedisCacheConfiguration.defaultCacheConfig()
    .entryTtl(Duration.ofMinutes(5))
    .disableCachingNullValues()
    .serializeValuesWith(
      SerializationPair.fromSerializer(GenericJackson2JsonRedisSerializer(myMapper))
    )
}
Örnek - RedisSerialization
Şöyle yaparız
@EnableCaching
@Configuration
public class RedisConfig {

  private final RedisSerializer<String> stringSerializer = RedisSerializer.string();
  private final RedisSerializer<Object> objectRedisSerializer = RedisSerializer.json();

  private final Duration ttl = Duration.ofHours(6);

  @Bean
  public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory
redisConnectionFactory) {
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(redisConnectionFactory);
    return redisTemplate;
  }

  @Bean
  public RedisCacheConfiguration redisCacheConfiguration() {
    return RedisCacheConfiguration
      .defaultCacheConfig()
      .serializeKeysWith(RedisSerializationContext.SerializationPair
.fromSerializer(stringSerializer))
      .serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(objectRedisSerializer))
      .entryTtl(ttl);
  }
}

1 Ağustos 2021 Pazar

SpringData Redis SetOperations Sınıfı

Örnek
Şöyle yaparız
@Component
public class RedisUtil<T> {
    private RedisTemplate<String, T> redisTemplate;
    private ValueOperations<String, T> valueOperations;
    private ListOperations<String, T> listOperations;
    private SetOperations<String, T> setOperations;
    private HashOperations<String, Integer, T> hashOperations;

  @Autowired
  public RedisUtil(RedisTemplate<String, T> redisTemplate) {
    this.redisTemplate = redisTemplate;
    this.valueOperations = redisTemplate.opsForValue();
    this.listOperations = redisTemplate.opsForList();
    this.setOperations = redisTemplate.opsForSet();
    this.hashOperations = redisTemplate.opsForHash();
  }


  //region Set
  public void addToSet(String key, T... values) {
    setOperations.add(key, values);
  }

  public Set<T> getSetMembers(String key) {
    return setOperations.members(key);
  }
  //endregion

}

SpringData Redis ListOperations Sınıfı

Örnek
Şöyle yaparız
@Component
public class RedisUtil<T> {
    private RedisTemplate<String, T> redisTemplate;
    private ValueOperations<String, T> valueOperations;
    private ListOperations<String, T> listOperations;
    private SetOperations<String, T> setOperations;
    private HashOperations<String, Integer, T> hashOperations;

  @Autowired
  public RedisUtil(RedisTemplate<String, T> redisTemplate) {
    this.redisTemplate = redisTemplate;
    this.valueOperations = redisTemplate.opsForValue();
    this.listOperations = redisTemplate.opsForList();
    this.setOperations = redisTemplate.opsForSet();
    this.hashOperations = redisTemplate.opsForHash();
  }

 
  //region List
  public void addList(String key, T value) {
    listOperations.leftPush(key, value);
  }

  public List<T> getListMembers(String key) {
    return listOperations.range(key, 0, -1);
  }

  public Long getListSize(String key) {
    return listOperations.size(key);
  }
  //endregion
}

SpringData Redis ValueOperations Sınıfı - Key/Value İşlemler İçindir

Giriş
Şu satırı dahil ederiz
import org.springframework.data.redis.core.ValueOperations;
get metodu
Örnek
Elimizde şöyle bir kod olsun.
private RedisTemplate<String, Object> redisTemplate = ...;
Şöyle yaparız.
ValueOperations<String, String> valueOperations  = redisTemplate.opsForValue();

String key = ...;

String value = valueOperations.get(key);
Örnek
Şöyle yaparız
RedisTemplate<String, Object> redisTemplate = ...;

private Optional<KeyValuePair> checkInCache(String key) {

  try {
    Object entryInCache = redisTemplate.opsForValue().get(key);
    return Optional.of(objectMapper.readValue(entryInCache.toString(),KeyValuePair.class));

  } catch (Exception e) {
    ...
  }
  return Optional.empty();

}

@Override
public KeyValuePair findByKey(String key) {
  return checkInCache(key).orElseGet(()->this.getFromDb(key));
}
increment metodu
Örnek
Şöyle yaparız
String name = ...
long count = redisTemplate.opsForValue().increment(name, 1);
set metodu
Örnek
Şöyle yaparız
@Component
public class RedisUtil<T> {
  private RedisTemplate<String, T> redisTemplate;
  private ValueOperations<String, T> valueOperations;
 

  @Autowired
  public RedisUtil(RedisTemplate<String, T> redisTemplate) {
    this.redisTemplate = redisTemplate;
    this.valueOperations = redisTemplate.opsForValue();
  }

  //region String
  public void putValue(String key, T value) {
    valueOperations.set(key, value);
  }

  public T getValue(String key) {
    return valueOperations.get(key);
  }
...
}

25 Ocak 2021 Pazartesi

SpringData Redis ReactiveRedisTemplate Sınıfı

Giriş
Şu satırı dahil ederiz
import org.springframework.data.redis.connection.stream.ObjectRecord;
import org.springframework.data.redis.connection.stream.StreamRecords;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
Bu sınıf ReactiveRedisOperations'tan kalıtır
constructor
Şöyle yaparız
@Configuration
public class ReactiveRedisConfiguration {

  private final Environment env;

  public ReactiveRedisConfiguration(Environment env) {
    this.env = env;
  }

  @Bean
  public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
    return new LettuceConnectionFactory(
      Objects.requireNonNull(env.getProperty("spring.redis.host")),
      Integer.parseInt(Objects.requireNonNull(env.getProperty("spring.redis.port"))));
  }


  @Bean
  public ReactiveRedisOperations<String, Object> redisOperations(
    ReactiveRedisConnectionFactory reactiveRedisConnectionFactory) {
    Jackson2JsonRedisSerializer<Object> serializer = 
      new Jackson2JsonRedisSerializer<>(Object.class);

    RedisSerializationContext.RedisSerializationContextBuilder<String, Object> builder =
      RedisSerializationContext.newSerializationContext(new StringRedisSerializer());

    RedisSerializationContext<String, Object> context = builder.value(serializer)
      .hashValue(serializer)
      .hashKey(serializer).build();

    return new ReactiveRedisTemplate<>(reactiveRedisConnectionFactory, context);
  }
}
opsForHash metodu
Örnek
Şöyle yaparız
public Mono<Object> set(String key, String hashKey, Object val) {
  return redisOperations.opsForHash().put(key, hashKey, val).map(b -> val);
}

public Flux<Object> get(@NotNull String key){
  return redisOperations.opsForHash().values(key);
}

public Mono<Object> get(String key, Object hashKey) {
  return redisOperations.opsForHash().get(key, hashKey);
}

public Mono<Long> remove(String key, Object hashKey) {
  return redisOperations.opsForHash().remove(key, hashKey);
}

opsForStream metodu
Redis Streams kullanabilmeyi sağlar

Örnek
Mesaj publish etmek için şöyle yaparız
String streamKey = "movie-events"
MovieDetails movieDetails = ...
ObjectRecord<String, MovieDetails> record = StreamRecords.newRecord()
  .ofObject(movieDetails)
  .withStreamKey(streamKey);

redisTemplate
  .opsForStream()
  .add(record)
  .subscribe(System.out::println);
Mesajı almak için şöyle yaparız
import org.springframework.data.redis.connection.stream.ObjectRecord;
import org.springframework.data.redis.stream.StreamListener;

public class MovieEventConsumer implements
StreamListener<String, ObjectRecord<String, MovieDetails>> {
  @Override
  public void onMessage(ObjectRecord<String, MovieDetails> record) {
    ...
  }
}
opsForZSet metodu
Şöyle yaparız
this.redisTemplate
  .opsForZSet()
  .incrementScore("MyMovie", "Likes", 1)
  .subscribe();

SpringData Redis Kullanımı

Giriş
Redis iki farklı amaç için kullanılabilir.
1. SpringCache'in için önbellek olarak. Bu kullanımda Redis ile direkt bir kodlamamız olmuyor.
2. Spring'in sağladığı sınıfları kullanarak Redis'i direkt kullanma. 

Bağlantı için Jedis veya Lettuce kullanılabilir. 

Örnek - Jedis - Spring Tarafından Varsayılan Kütüphane
Şöyle yaparız
dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>3.3.0</version>
</dependency>
Örnek - Lettuce
Şöyle yaparız
dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
<dependency>
  <groupId>io.lettuce</groupId>
  <artifactId>letus-core</artifactId>
  <version>...</version>
</dependency>
1. SpringData Redis application.properties Ayarları ile bağlantı ayarları belirtilir.
2. İsteniyorsa RedisConnection ve RedisConnectionFactory arayüzlerini gerçekleştiren nesneler yaratılır. Bu arayüzler org.springframework.data.redis.connection paketinde. Açıklaması şöyle
RedisConnection, which manages communication with the Redis back end, offers the fundamental building block for Redis communication, and automatically converts the underlying connecting library exceptions to Spring’s reliable DAO exception hierarchy.

In order to create RedisConnection you can use the RedisConnectionFactory. The RedisConnectionFactory can be used most simply by configuring the proper connection through the IoC container and injecting it into the target class.
JedisConnectionFactory yazısına bakabilirsiniz

3. RedisTemplate veya ReactiveRedisTemplate sınıfları kullanılarak opsForX() metodu çağrılır. Döndürülen nesne ile direkt Redis işlemleri yapılabilir.

4. Veya direkt RedisTemplate nesnesini kullanmak yerine Repository yöntemi kullanılır. 
Örnek
Şöyle yaparız
@RedisHash("Student")
public class Student implements Serializable {
  private String id;
  private String name;
  private Integer age;
}

public interface StudentRepository extends CrudRepository<Student, String> {
}

@Service
public class StudentService {

  @Autowired
  StudentRepository studentRepository;

  public Student addStudent(Student student){
    return studentRepository.save(student);
  }

  public List<Student> getStudents(){
    List<Student> list = new ArrayList<Student>();
    studentRepository.findAll().forEach( i -> {
      list.add(i);
    });
    return list;
  }
}
Örnek
Kullanılacak Redis repository nesnelerini belirtmek için şöyle yaparız
@SpringBootApplication
@EnableJpaRepositories(basePackages = "org.medium.jpa")
@EnableRedisRepositories(basePackages = "org.medium.redis", 
  enableKeyspaceEvents = RedisKeyValueAdapter.EnableKeyspaceEvents.ON_STARTUP)
public class MediumApplication {
  public static void main(String[] args) {
    SpringApplication application = new SpringApplication(MediumApplication.class);
    application.run(args);
  }
}
Redis nesnesi şöyledir
package org.medium.redis;

import java.io.Serializable;

import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;

@RedisHash(value = "mediumuser")
@Getter
@Setter
@ToString
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class MediumRedisUser implements Serializable {
    @Id
    Long id;
    String name;
}

17 Ekim 2019 Perşembe

SpringData Redis StringRedisTemplate Sınıfı

opsForValue metodu
Şöyle yaparız
StringRedisTemplate stringRedisTemplate ...;
String KEY = "...";
String val = "...";
Boolean firstSet = stringRedisTemplate.opsForValue().setIfAbsent(KEY, val);//