Introduction à Redis à l'aide de Spring Boot

La traduction de l'article a été préparée spécialement pour les étudiants du cours "Developer on the Spring Framework".



Dans cet article, nous couvrirons les bases de l'utilisation de Redis via Spring Boot à l'aide de la bibliothèque Spring Data Redis.



Nous allons créer une application qui montre comment effectuer des opérations CRUD via une interface Web. Le code source de ce projet est disponible sur GitHub .

Qu'est-ce que Redis?


Redis est un entrepôt de données open source pour les structures de données de valeurs-clés qui peuvent être utilisées comme base de données, cache et courtier de messages. En termes d'implémentation, les magasins de valeurs-clés sont parmi les plus grands et les plus anciens représentants du monde NoSQL. Redis prend en charge les structures de données telles que les chaînes, les hachages, les listes, les ensembles et les ensembles triés avec des requêtes de plage.

Le framework Spring Data Redis facilite l'écriture d'applications Spring qui utilisent le stockage Redis, fournissant une abstraction pratique du stockage de données.

Configuration du serveur Redis


Le serveur est disponible gratuitement ici .
Si vous utilisez un Mac, vous pouvez l'installer en utilisant homebrew :

 brew install redis 

Démarrez ensuite le serveur:

 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 

Dépendances Maven


pom.xml les dépendances nécessaires dans pom.xml pour l'application avec laquelle nous travaillerons:

 <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> 

Configuration de Redis


Nous devons connecter notre application au serveur Redis. Pour établir une connexion, nous utilisons Jedis , une implémentation client de Redis.

La configuration


Commençons par la définition des beans de configuration:

 @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 est présenté comme un bean, afin que nous puissions créer un RedisTemplate pour demander des données.

Publier l'éditeur


En suivant les principes de SOLID , nous créons l'interface MessagePublisher :

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

Nous implémentons l'interface MessagePublisher à l'aide du RedisTemplate de haut niveau pour publier un message, car RedisTemplate permet d'envoyer des objets arbitraires en tant que messages:

 @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); } } 

Nous définissons également cela comme un bean dans RedisConfig :

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

Destinataire du message


Pour vous abonner aux messages, vous devez implémenter l'interface MessageListener : chaque fois qu'un nouveau message arrive, le code utilisateur situé dans la méthode onMessage est onMessage . Cette interface permet d'accéder au message, au canal par lequel il a été reçu et vous permet d'utiliser n'importe quel modèle utilisé pour vous abonner au 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())); } } 

De plus, cette classe doit être enregistrée en tant que bean dans RedisConfig :

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

Redéposé


Maintenant que nous avons configuré l'application pour interagir avec le serveur Redis, nous allons préparer l'application pour recevoir les données de test.

Modèle


Pour cet exemple, nous définissons un modèle de Movie avec deux champs:

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

Interface de référentiel


Contrairement à d'autres projets Spring Data, Spring Data Redis fournit tout ce dont vous avez besoin pour travailler sur d'autres interfaces Spring Data. Cela peut sembler étrange pour les personnes ayant de l'expérience avec d'autres projets Spring Data.

Souvent, il n'est pas nécessaire d'écrire une implémentation d'interface de référentiel avec des projets Spring Data. Nous interagissons simplement avec l'interface. Spring Data JPA fournit de nombreuses interfaces de référentiel qui peuvent être étendues pour fournir des fonctionnalités telles que les opérations CRUD, les requêtes dérivées et la pagination.

Donc, malheureusement, nous devons écrire notre propre interface, puis définir les méthodes :

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

Implémentation du référentiel


La classe utilise redisTemplate défini dans la RedisConfig configuration RedisConfig .

Nous utilisons HashOperations , que Spring Data Redis propose:

 @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); } } 

Prenons attention à la méthode init() . Dans cette méthode, nous utilisons une fonction appelée opsForHash() , elle retourne les opérations effectuées avec des valeurs de hachage opsForHash() à cette clé. Ensuite, nous utilisons hashOps , qui a été défini dans init() , pour toutes nos opérations CRUD.

Interface Web


Dans cette section, nous examinerons l'ajout de capacités Redis CRUD à l'interface Web.

Ajout d'un film


Nous voulons pouvoir ajouter un film via une page Web. La clé est l'identifiant du film et la valeur est l'objet réel. Cependant, nous y reviendrons plus tard, donc seul le nom du film est affiché comme valeur.

Ajoutons un formulaire au document HTML et attribuons les noms et identifiants appropriés:

 <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> 

Maintenant, nous utilisons JavaScript pour enregistrer les valeurs lors de la soumission du formulaire:

 $(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(); }); 

Nous définissons les paramètres @RequestMapping pour la demande POST, demandons la clé et la valeur, créons un objet Movie et l'enregistrons dans le référentiel:

 @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); } 

Afficher le contenu


Une fois l'objet Movie ajouté, nous mettons à jour le tableau pour afficher les nouvelles valeurs. Dans le bloc de code JavaScript, nous avons appelé la fonction refreshTable() . Il exécute une demande GET pour récupérer les données actuelles dans le référentiel:

 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])); } } }); } 

La demande GET est traitée par la méthode findAll() , qui récupère tous les objets Movie stockés dans le magasin, puis convertit le type de données de Map <Object, Object> en 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; } 

Suppression de film


Nous allons écrire un script pour effectuer une requête POST le long du chemin /delete , mettre à jour le tableau et changer le focus du clavier pour une saisie pratique:

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

Nous demandons une clé et redisRepository l'objet dans redisRepository fonction de cette clé:

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

Démo


Ici, nous avons ajouté deux films:



Et un film a été supprimé:



Conclusion


Dans ce guide, nous avons examiné Spring Data Redis et une façon de le connecter à une application Web pour effectuer des opérations CRUD.

Le code source de l'exemple d'application se trouve sur GitHub .

C’est tout. Attend traditionnellement vos commentaires.

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


All Articles