Статьи

Интегрируйте Redis в свой проект Spring

В этой статье показано, как интегрировать кэш Redis в ваш весенний проект с помощью конфигурации аннотаций.

Мы начнем с нашей конфигурации Gradle. Мы будем использовать драйвер джедаев.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
group 'com.gkatzioura.spring'
version '1.0-SNAPSHOT'
 
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
 
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE")
    }
}
 
jar {
    baseName = 'gs-serving-web-content'
    version =  '0.1.0'
}
 
sourceCompatibility = 1.8
 
repositories {
    mavenCentral()
}
 
dependencies {
    compile "org.springframework.boot:spring-boot-starter-thymeleaf"
    compile 'org.slf4j:slf4j-api:1.6.6'
    compile 'ch.qos.logback:logback-classic:1.0.13'
    compile 'redis.clients:jedis:2.7.0'
    compile 'org.springframework.data:spring-data-redis:1.5.0.RELEASE'
    testCompile group: 'junit', name: 'junit', version: '4.11'
}
 
task wrapper(type: Wrapper) {
    gradleVersion = '2.3'
}

Приступим к настройке Redis, используя весенние аннотации.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.gkatzioura.spring.config;
 
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
 
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
 
    @Bean
    public JedisConnectionFactory redisConnectionFactory() {
 
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
        jedisConnectionFactory.setUsePool(true);
        return jedisConnectionFactory;
    }
 
    @Bean
    public RedisSerializer redisStringSerializer() {
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        return stringRedisSerializer;
    }
 
    @Bean(name="redisTemplate")
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf,RedisSerializer redisSerializer) {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
        redisTemplate.setConnectionFactory(cf);
        redisTemplate.setDefaultSerializer(redisSerializer);
        return redisTemplate;
    }
 
    @Bean
    public CacheManager cacheManager() {
        return new RedisCacheManager(redisTemplate(redisConnectionFactory(),redisStringSerializer()));
    }
 
}

Следующим шагом является создание нашего интерфейса кеширования

01
02
03
04
05
06
07
08
09
10
11
12
package com.gkatzioura.spring.cache;
 
import java.util.Date;
import java.util.List;
 
public interface CacheService {
 
    public void addMessage(String user,String message);
 
    public List<String> listMessages(String user);
 
}

Пользователь будет добавлять сообщения, и он сможет получить их. Однако в нашей реализации сообщения, относящиеся к пользователям, будут жить в течение одной минуты.

Наша реализация CacheService с использованием Redis выглядит следующим образом.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.gkatzioura.spring.cache.impl;
 
import com.gkatzioura.spring.cache.CacheService;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Service;
 
import javax.annotation.Resource;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
 
@Service("cacheService")
public class RedisService implements CacheService {
 
    @Resource(name = "redisTemplate")
    private ListOperations<String, String> messageList;
 
    @Resource(name = "redisTemplate")
    private RedisOperations<String,String> latestMessageExpiration;
 
    @Override
    public void addMessage(String user,String message) {
 
        messageList.leftPush(user,message);
 
        ZonedDateTime zonedDateTime = ZonedDateTime.now();
        Date date = Date.from(zonedDateTime.plus(1, ChronoUnit.MINUTES).toInstant());
        latestMessageExpiration.expireAt(user,date);
    }
 
    @Override
    public List<String> listMessages(String user) {
        return messageList.range(user,0,-1);
    }
 
}

Наш механизм кэширования сохранит список сообщений, отправленных каждым пользователем. Для достижения этого мы будем использовать интерфейс ListOperations, используя пользователя в качестве ключа. Интерфейс RedisOperations дает нам возможность указать время жизни для ключа. В нашем случае он используется для пользовательского ключа.

Далее мы создаем контроллер с внедренным сервисом кэширования.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.gkatzioura.spring.controller;
 
import com.gkatzioura.spring.cache.CacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
 
import java.util.List;
 
@RestController
public class MessageController {
 
 
    @Autowired
    private CacheService cacheService;
 
    @RequestMapping(value = "/message",method = RequestMethod.GET)
    @ResponseBody
    public List<String> greeting(String user) {
 
        List<String> messages = cacheService.listMessages(user);
 
        return messages;
    }
 
    @RequestMapping(value = "/message",method = RequestMethod.POST)
    @ResponseBody
    public String saveGreeting(String user,String message) {
 
        cacheService.addMessage(user,message);
 
        return "OK";
 
    }
 
}

Последний, но не менее важный наш класс Application

01
02
03
04
05
06
07
08
09
10
11
12
13
package com.gkatzioura.spring;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class Application {
 
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
 
}

Для запуска просто выдайте

1
gradle bootRun