Einführung in Redis mit Spring Boot

Die Übersetzung des Artikels wurde speziell für Studenten des Kurses "Developer on the Spring Framework" erstellt.



In diesem Artikel werden die Grundlagen der Verwendung von Redis über Spring Boot mithilfe der Spring Data Redis-Bibliothek behandelt.



Wir werden eine Anwendung erstellen, die zeigt, wie CRUD-Operationen über eine Webschnittstelle ausgeführt werden. Der Quellcode für dieses Projekt ist auf GitHub verfügbar .

Was ist Redis?


Redis ist ein Open Source Data Warehouse für Schlüsselwertdatenstrukturen , die als Datenbank, Cache und Nachrichtenbroker verwendet werden können. In Bezug auf die Implementierung gehören Schlüsselwertspeicher zu den größten und ältesten Vertretern in der NoSQL-Welt. Redis unterstützt Datenstrukturen wie Zeichenfolgen, Hashes, Listen, Mengen und sortierte Mengen mit Bereichsabfragen.

Das Spring Data Redis- Framework erleichtert das Schreiben von Spring-Anwendungen, die Redis-Speicher verwenden, und bietet eine bequeme Abstraktion des Datenspeichers.

Redis Server Setup


Der Server steht hier kostenlos zur Verfügung.
Wenn Sie einen Mac verwenden, können Sie ihn mit homebrew installieren:

 brew install redis 

Starten Sie dann den Server:

 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 

Maven-Abhängigkeiten


pom.xml wir die erforderlichen Abhängigkeiten in pom.xml für die Anwendung, mit der wir arbeiten werden:

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

Redis Konfiguration


Wir müssen unsere Anwendung mit dem Redis-Server verbinden. Um eine Verbindung herzustellen, verwenden wir Jedis , eine Client-Implementierung von Redis.

Konfiguration


Beginnen wir mit der Definition von Konfigurations-Beans:

 @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 wird als Bean dargestellt, damit wir eine RedisTemplate erstellen RedisTemplate , um Daten anzufordern.

Post Publisher


Nach den Prinzipien von SOLID erstellen wir die MessagePublisher Schnittstelle:

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

Wir implementieren die MessagePublisher Schnittstelle mithilfe der übergeordneten RedisTemplate, um eine Nachricht zu veröffentlichen, da RedisTemplate mit RedisTemplate beliebige Objekte als Nachrichten senden können:

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

Wir definieren dies auch als Bean in RedisConfig :

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

Nachrichtenempfänger


Um Nachrichten zu abonnieren, müssen Sie die MessageListener Schnittstelle implementieren: Jedes Mal, wenn eine neue Nachricht eintrifft, wird der Benutzercode in der onMessage Methode onMessage . Diese Schnittstelle bietet Zugriff auf die Nachricht, den Kanal, über den sie empfangen wurde, und ermöglicht Ihnen die Verwendung einer beliebigen Vorlage, die zum Abonnieren des Kanals verwendet wird.

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

Außerdem muss diese Klasse in RedisConfig als Bean RedisConfig :

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

Redisrepository


Nachdem wir die Anwendung für die Interaktion mit dem Redis-Server eingerichtet haben, bereiten wir die Anwendung für den Empfang von Testdaten vor.

Modell


In diesem Beispiel definieren wir ein Movie mit zwei Feldern:

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

Repository-Schnittstelle


Im Gegensatz zu anderen Spring Data-Projekten bietet Spring Data Redis alles, was Sie für die Arbeit mit anderen Spring Data-Schnittstellen benötigen. Dies mag für Personen mit Erfahrung mit anderen Spring Data-Projekten seltsam aussehen.

Oft ist es nicht erforderlich, eine Implementierung der Repository-Schnittstelle für Spring Data-Projekte zu schreiben. Wir interagieren nur mit der Schnittstelle. Spring Data JPA bietet zahlreiche Repository-Schnittstellen, die erweitert werden können, um Funktionen wie CRUD-Operationen, abgeleitete Abfragen und Paginierung bereitzustellen.

Leider müssen wir unsere eigene Schnittstelle schreiben und dann die Methoden definieren :

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

Repository-Implementierung


Die Klasse verwendet redisTemplate das in der RedisConfig Konfigurationsklasse definiert ist.

Wir verwenden HashOperations , die Spring Data Redis anbietet:

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

Achten wir auf die Methode init() . In dieser Methode verwenden wir eine Funktion namens opsForHash() , die Operationen zurückgibt, die mit Hash-Werten ausgeführt werden, opsForHash() diesem Schlüssel zugeordnet sind. Dann verwenden wir für alle unsere CRUD-Operationen hashOps , das in init() definiert wurde.

Webschnittstelle


In diesem Abschnitt werden wir uns mit dem Hinzufügen von Redis CRUD-Funktionen zur Weboberfläche befassen.

Hinzufügen eines Films


Wir möchten einen Film über eine Webseite hinzufügen können. Der Schlüssel ist die Kennung des Films und der Wert ist das eigentliche Objekt. Wir werden jedoch später darauf zurückkommen, sodass nur der Name des Films als Wert angezeigt wird.

Fügen wir dem HTML-Dokument ein Formular hinzu und weisen Sie die entsprechenden Namen und Bezeichner zu:

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

Jetzt verwenden wir JavaScript, um Werte beim Senden des Formulars zu speichern:

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

Wir legen @RequestMapping Parameter für die POST-Anforderung fest, fordern den Schlüssel und den Wert an, erstellen ein Movie Objekt und speichern es im Repository:

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

Inhalt anzeigen


Sobald das Movie-Objekt hinzugefügt wurde, aktualisieren wir die Tabelle, um die neuen Werte anzuzeigen. Im Block des JavaScript-Codes haben wir die Funktion refreshTable() aufgerufen. Es führt eine GET-Anforderung aus, um die aktuellen Daten im Repository abzurufen:

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

Die GET-Anforderung wird von der findAll() -Methode verarbeitet, die alle im Speicher gespeicherten Movie-Objekte abruft und dann den Datentyp von Map <Object, Object> in Map <String, String> konvertiert:

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

Filmentfernung


Wir werden ein Skript schreiben, um eine POST-Anforderung entlang des /delete Pfads auszuführen, die Tabelle zu aktualisieren und den Tastaturfokus für eine bequeme Eingabe zu wechseln:

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

Wir fordern einen Schlüssel an und löschen das Objekt in redisRepository basierend auf diesem Schlüssel:

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

Demo


Hier haben wir zwei Filme hinzugefügt:



Und ein Film wurde gelöscht:



Fazit


In diesem Handbuch haben wir uns Spring Data Redis und eine Möglichkeit angesehen, es mit einer Webanwendung zu verbinden, um CRUD-Operationen auszuführen.

Der Quellcode für die Beispielanwendung befindet sich auf GitHub .

Das ist alles. Traditionell auf Ihre Kommentare warten.

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


All Articles