مقدمة إلى Redis باستخدام Spring التمهيد

تم إعداد ترجمة المقال خصيصًا لطلاب الدورة التدريبية "Developer on the Spring Framework".



في هذه المقالة ، سنغطي أساسيات استخدام Redis خلال Spring Boot باستخدام مكتبة Spring Data Redis.



سننشئ تطبيقًا يوضح كيفية إجراء عمليات CRUD من خلال واجهة ويب. الكود المصدري لهذا المشروع متاح على جيثب .

ما هو رديس؟


Redis هو مستودع بيانات مفتوح المصدر لهياكل البيانات ذات القيمة الأساسية التي يمكن استخدامها كقاعدة بيانات وذاكرة تخزين مؤقت ووسيط للرسائل. من حيث التنفيذ ، تعد المتاجر ذات القيمة الرئيسية من بين أكبر وأقدم الممثلين في عالم NoSQL. يدعم Redis هياكل البيانات مثل السلاسل والتجزئة والقوائم والمجموعات والمجموعات المصنفة مع استعلامات النطاق.

يجعل إطار Spring Data Redis من السهل كتابة تطبيقات Spring التي تستخدم تخزين Redis ، مما يوفر مجموعة مناسبة من تخزين البيانات.

إعداد خادم Redis


الخادم متاح مجانا هنا .
إذا كنت تستخدم جهاز Mac ، فيمكنك تثبيته باستخدام homebrew :

 brew install redis 

ثم ابدأ الخادم:

 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 

تبعيات مخضرم


دعنا نعلن التبعيات اللازمة في pom.xml للتطبيق الذي سنعمل مع:

 <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


نحتاج إلى توصيل تطبيقنا بخادم Redis. لتأسيس اتصال ، نستخدم Jedis ، تطبيق عميل لـ Redis .

ترتيب


لنبدأ بتعريف حبوب التكوين:

 @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 ، حتى نتمكن من إنشاء RedisTemplate لطلب البيانات.

نشر الناشر


باتباع مبادئ SOLID ، نقوم بإنشاء واجهة MessagePublisher :

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

ننفذ واجهة MessagePublisher باستخدام RedisTemplate عالي المستوى لنشر رسالة ، لأن RedisTemplate يسمح RedisTemplate بإرسال كائنات عشوائية كرسائل:

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

نحن أيضًا نعرّف ذلك على أنه حبة في RedisConfig :

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

مستلم الرسالة


للاشتراك في الرسائل ، تحتاج إلى تطبيق واجهة MessageListener : في كل مرة تصل رسالة جديدة ، يتم onMessage رمز المستخدم الموجود في طريقة onMessage . تتيح هذه الواجهة الوصول إلى الرسالة ، القناة التي تم استلامها من خلالها ، وتتيح لك استخدام أي قالب مستخدم للاشتراك في القناة.

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

أيضًا ، يجب تسجيل هذه الفئة RedisConfig في RedisConfig :

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

RedisRepository


الآن وقد قمنا بإعداد التطبيق للتفاعل مع خادم Redis ، سنقوم بإعداد التطبيق لتلقي بيانات الاختبار.

نموذج


في هذا المثال ، نعرّف نموذج Movie به حقلان:

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

مستودع مستودع


بخلاف مشاريع Spring Data الأخرى ، يوفر Spring Data Redis كل ما تحتاجه للعمل على واجهات Spring Data الأخرى. قد يبدو هذا غريبًا بالنسبة للأشخاص ذوي الخبرة في مشاريع Spring Data الأخرى.

غالبًا لا توجد حاجة لكتابة تطبيق واجهة مستودع مع مشاريع Spring Data. نتفاعل فقط مع الواجهة. يوفر Spring Data JPA العديد من واجهات مستودع التخزين التي يمكن تمديدها لتوفير ميزات مثل عمليات CRUD ، والاستعلامات المشتقة ، والصفحات.

لذلك ، للأسف ، نحتاج إلى كتابة الواجهة الخاصة بنا ، ثم تحديد الأساليب :

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

مستودع التنفيذ


يستخدم الفصل redisTemplate المعرفة في RedisConfig تكوين RedisConfig .

نستخدم HashOperations ، التي HashOperations Spring Data HashOperations :

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

دعنا ننتبه إلى طريقة init() . في هذه الطريقة ، نستخدم دالة تسمى opsForHash() ، حيث تقوم بإرجاع العمليات التي يتم تنفيذها باستخدام قيم التجزئة opsForHash() بهذا المفتاح. ثم نستخدم hashOps ، والذي تم تعريفه في init() ، لجميع عملياتنا CRUD.

واجهة الويب


في هذا القسم ، سننظر في إضافة قدرات Redis CRUD إلى واجهة الويب.

إضافة فيلم


نريد أن نكون قادرين على إضافة فيلم من خلال صفحة ويب. المفتاح هو معرف الفيلم ، والقيمة هي الكائن الفعلي. ومع ذلك ، سنعود إلى هذا لاحقًا ، لذلك يتم عرض اسم الفيلم فقط كقيمة.

لنقم بإضافة نموذج إلى مستند HTML وتعيين الأسماء والمعرفات المناسبة:

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

نستخدم الآن JavaScript لحفظ القيم عند إرسال النموذج:

 $(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 لطلب POST ، وطلب المفتاح والقيمة ، وإنشاء كائن Movie وحفظه في المستودع:

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

عرض المحتوى


بمجرد إضافة كائن الفيلم ، نقوم بتحديث الجدول لعرض القيم الجديدة. في كتلة شفرة JavaScript ، أطلقنا على refreshTable() . ينفذ طلب GET لاسترداد البيانات الحالية في المستودع:

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

تتم معالجة طلب GET بواسطة أسلوب findAll() ، الذي يسترجع جميع كائنات الفيلم المخزنة في المتجر ثم يحول نوع البيانات من Map <Object, Object> إلى 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; } 

إزالة الفيلم


سنكتب برنامج نصي لتنفيذ طلب POST على طول مسار /delete ، قم بتحديث الجدول وتبديل تركيز لوحة المفاتيح لإدخال مناسب:

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

نطلب مفتاحًا ونحذف الكائن في redisRepository استنادًا إلى هذا المفتاح:

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

عرض


أضفنا هنا فيلمين:



وتم حذف فيلم واحد:



استنتاج


في هذا الدليل ، نظرنا إلى Spring Data Redis وطريقة واحدة لتوصيله بتطبيق ويب لأداء عمليات CRUD.

الكود المصدري للتطبيق النموذجي موجود على جيثب .

هذا كل شيء. في انتظار تقليديا لتعليقاتكم.

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


All Articles