Introdução ao Redis usando o Spring Boot

A tradução do artigo foi preparada especificamente para os alunos do curso "Developer on the Spring Framework".



Neste artigo, abordaremos o básico do uso do Redis através do Spring Boot usando a biblioteca Spring Data Redis.



Criaremos um aplicativo que demonstre como executar operações CRUD por meio de uma interface da web. O código fonte deste projeto está disponível no GitHub .

O que é Redis?


O Redis é um data warehouse de código aberto para estruturas de dados de valor-chave que podem ser usados ​​como banco de dados, cache e intermediário de mensagens. Em termos de implementação, os armazenamentos de valores-chave estão entre os maiores e mais antigos representantes do mundo NoSQL. O Redis suporta estruturas de dados como strings, hashes, listas, conjuntos e conjuntos classificados com consultas de intervalo.

A estrutura Spring Data Redis facilita a gravação de aplicativos Spring que usam armazenamento Redis, fornecendo uma abstração conveniente do armazenamento de dados.

Configuração do servidor Redis


O servidor está disponível gratuitamente aqui .
Se você estiver usando um Mac, poderá instalá-lo usando o homebrew :

 brew install redis 

Em seguida, inicie o servidor:

 mikes-MacBook-Air:~ mike$ redis-server 10699:C 23 Nov 08:35:58.306 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 10699:C 23 Nov 08:35:58.307 # Redis version=4.0.2, bits=64, commit=00000000, modified=0, pid=10699, just started 10699:C 23 Nov 08:35:58.307 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf 10699:M 23 Nov 08:35:58.309 * Increased maximum number of open files to 10032 (it was originally set to 256). _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 4.0.2 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 10699 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 10699:M 23 Nov 08:35:58.312 # Server initialized 10699:M 23 Nov 08:35:58.312 * Ready to accept connections 

Dependências do Maven


Vamos declarar as dependências necessárias no pom.xml para o aplicativo com o qual trabalharemos:

 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 

Configuração Redis


Precisamos conectar nosso aplicativo ao servidor Redis. Para estabelecer uma conexão, usamos o Jedis , uma implementação cliente do Redis.

Configuração


Vamos começar com a definição de beans de configuração:

 @Bean JedisConnectionFactory jedisConnectionFactory() { return new JedisConnectionFactory(); } @Bean public RedisTemplate<String, Object> redisTemplate() { final RedisTemplate<String, Object> template = new RedisTemplate<String, Object>(); template.setConnectionFactory(jedisConnectionFactory()); template.setValueSerializer(new GenericToStringSerializer<Object>(Object.class)); return template; } 

JedisConnectionFactory é apresentado como um bean, para que possamos criar um RedisTemplate para solicitar dados.

Publicar editor


Seguindo os princípios do SOLID , criamos a interface MessagePublisher :

 public interface MessagePublisher { void publish(final String message); } 

Implementamos a interface MessagePublisher usando o RedisTemplate de alto nível para publicar uma mensagem, pois o RedisTemplate permite enviar objetos arbitrários como mensagens:

 @Service public class MessagePublisherImpl implements MessagePublisher { @Autowired private RedisTemplate<String, Object> redisTemplate; @Autowired private ChannelTopic topic; public MessagePublisherImpl() { } public MessagePublisherImpl(final RedisTemplate<String, Object> redisTemplate, final ChannelTopic topic) { this.redisTemplate = redisTemplate; this.topic = topic; } public void publish(final String message) { redisTemplate.convertAndSend(topic.getTopic(), message); } } 

Também definimos isso como um bean no RedisConfig :

 @Bean MessagePublisher redisPublisher() { return new MessagePublisherImpl(redisTemplate(), topic()); } 

Destinatário da mensagem


Para assinar mensagens, é necessário implementar a interface MessageListener : sempre que uma nova mensagem chega, o código do usuário localizado no método onMessage é onMessage . Essa interface fornece acesso à mensagem, ao canal pelo qual foi recebida, e permite que você use qualquer modelo usado para se inscrever no canal.

 @Service public class MessageSubscriber implements MessageListener { public static List<String> messageList = new ArrayList<String>(); public void onMessage(final Message message, final byte[] pattern) { messageList.add(message.toString()); System.out.println("Message received: " + new String(message.getBody())); } } 

Além disso, essa classe deve ser registrada como um bean no RedisConfig :

 @Bean MessageListenerAdapter messageListener() { return new MessageListenerAdapter(new MessageSubscriber()); } 

Redisrepositório


Agora que configuramos o aplicativo para interagir com o servidor Redis, prepararemos o aplicativo para receber dados de teste.

Modelo


Neste exemplo, definimos um modelo de Movie com dois campos:

 private String id; private String name; //standard getters and setters 

Interface do Repositório


Ao contrário de outros projetos do Spring Data, o Spring Data Redis fornece tudo o que você precisa para trabalhar em cima de outras interfaces do Spring Data. Isso pode parecer estranho para pessoas com experiência em outros projetos do Spring Data.

Geralmente, não há necessidade de escrever uma implementação de interface de repositório com projetos do Spring Data. Nós apenas interagimos com a interface. O Spring Data JPA fornece inúmeras interfaces de repositório que podem ser estendidas para fornecer recursos como operações CRUD, consultas derivadas e paginação.

Infelizmente, precisamos escrever nossa própria interface e depois definir os métodos :

 public interface RedisRepository { Map<Object, Object> findAllMovies(); void add(Movie movie); void delete(String id); Movie findMovie(String id); } 

Implementação de Repositório


A classe usa redisTemplate definido na RedisConfig configuração RedisConfig .

Usamos o HashOperations , que o Spring Data Redis oferece:

 @Repository public class RedisRepositoryImpl implements RedisRepository { private static final String KEY = "Movie"; private RedisTemplate<String, Object> redisTemplate; private HashOperations hashOperations; @Autowired public RedisRepositoryImpl(RedisTemplate<String, Object> redisTemplate){ this.redisTemplate = redisTemplate; } @PostConstruct private void init(){ hashOperations = redisTemplate.opsForHash(); } public void add(final Movie movie) { hashOperations.put(KEY, movie.getId(), movie.getName()); } public void delete(final String id) { hashOperations.delete(KEY, id); } public Movie findMovie(final String id){ return (Movie) hashOperations.get(KEY, id); } public Map<Object, Object> findAllMovies(){ return hashOperations.entries(KEY); } } 

Vamos prestar atenção ao método init() . Neste método, usamos uma função chamada opsForHash() , que retorna operações executadas com valores de hash opsForHash() a essa chave. Em seguida, usamos o hashOps , definido em init() , para todas as nossas operações CRUD.

Interface da web


Nesta seção, veremos como adicionar recursos Redis CRUD à interface da web.

Adicionando um filme


Queremos poder adicionar um filme através de uma página da web. A chave é o identificador do filme e o valor é o objeto real. No entanto, retornaremos a isso mais tarde, portanto, apenas o nome do filme será exibido como o valor.

Vamos adicionar um formulário ao documento HTML e atribuir os nomes e identificadores apropriados:

 <form id="addForm"> <div class="form-group"> <label for="keyInput">Movie ID (key)</label> <input name="keyInput" id="keyInput" class="form-control"/> </div> <div class="form-group"> <label for="valueInput">Movie Name (field of Movie object value)</label> <input name="valueInput" id="valueInput" class="form-control"/> </div> <button class="btn btn-default" id="addButton">Add</button> </form> 

Agora usamos JavaScript para salvar valores ao enviar o formulário:

 $(document).ready(function() { var keyInput = $('#keyInput'), valueInput = $('#valueInput'); refreshTable(); $('#addForm').on('submit', function(event) { var data = { key: keyInput.val(), value: valueInput.val() }; $.post('/add', data, function() { refreshTable(); keyInput.val(''); valueInput.val(''); keyInput.focus(); }); event.preventDefault(); }); keyInput.focus(); }); 

@RequestMapping parâmetros @RequestMapping para a solicitação POST, solicitamos a chave e o valor, criamos um objeto Movie e salvamos no repositório:

 @RequestMapping(value = "/add", method = RequestMethod.POST) public ResponseEntity<String> add( @RequestParam String key, @RequestParam String value) { Movie movie = new Movie(key, value); redisRepository.add(movie); return new ResponseEntity<>(HttpStatus.OK); } 

Exibir conteúdo


Depois que o objeto Movie é adicionado, atualizamos a tabela para exibir os novos valores. No bloco de código JavaScript, chamamos a função refreshTable() . Ele executa uma solicitação GET para obter os dados atuais no repositório:

 function refreshTable() { $.get('/values', function(data) { var attr, mainTable = $('#mainTable tbody'); mainTable.empty(); for (attr in data) { if (data.hasOwnProperty(attr)) { mainTable.append(row(attr, data[attr])); } } }); } 

A solicitação GET é processada pelo método findAll() , que recupera todos os objetos Movie armazenados na loja e converte o tipo de dados de Map <Object, Object> para Map <String, String> :

 @RequestMapping("/values") public @ResponseBody Map<String, String> findAll() { Map<Object, Object> aa = redisRepository.findAllMovies(); Map<String, String> map = new HashMap<String, String>(); for(Map.Entry<Object, Object> entry : aa.entrySet()){ String key = (String) entry.getKey(); map.put(key, aa.get(key).toString()); } return map; } 

Remoção de filme


Escreveremos um script para executar uma solicitação POST no caminho /delete , atualizar a tabela e alternar o foco do teclado para uma entrada conveniente:

 function deleteKey(key) { $.post('/delete', {key: key}, function() { refreshTable(); $('#keyInput').focus(); }); } 

Solicitamos uma chave e redisRepository o objeto em redisRepository base nesta chave:

 @RequestMapping(value = "/delete", method = RequestMethod.POST) public ResponseEntity<String> delete(@RequestParam String key) { redisRepository.delete(key); return new ResponseEntity<>(HttpStatus.OK); } 

Demo


Aqui nós adicionamos dois filmes:



E um filme foi excluído:



Conclusão


Neste guia, analisamos o Spring Data Redis e uma maneira de conectá-lo a um aplicativo Web para executar operações CRUD.

O código fonte do aplicativo de amostra está no GitHub .

Só isso. Tradicionalmente, aguardando seus comentários.

Source: https://habr.com/ru/post/pt463365/


All Articles