مقدمة
يلف Spring قالبًا قويًا نسبيًا لسهولة الاستخدام في استخدام redis ؛ لقد استخدمت redis في النظام البيئي الربيع من قبل ، ولكن استخدمت مباشرة Jedis للتفاعلات المقابلة. الآن دعونا نلقي نظرة على كيفية تنفيذ Redistemplate وما إذا كان أكثر ملاءمة للاستخدام.
لا تزال Jedis تستخدم لإدارة تجمعات الاتصال ، لذا بالإضافة إلى تقديم Dring-Data-Redis ، بالإضافة إلى تبعيات Jedis ، أضف ملف POM
<Rependency> <roupeD> org.springframework.data </rougiD> <artifactid> spring-data-redis </stifactid> <sophy> 1.8.4.Release </version> </reperency> <redency> <sropency> <sropencid> redis.clients </groupid>
إذا كنت بحاجة إلى تحديد المعلمات المتعلقة بالتسلسل ، فيمكنك أيضًا تقديم جاكسون. هذه المقالة بسيطة للمبتدئين ، لذلك لن تضيف هذا
قم بإعداد معلمات التكوين المتعلقة بـ Redis ، وتشمل المعلمات الشائعة المضيف ، والمنفذ ، وكلمة المرور ، والمهنية .... فيما يلي تكوين بسيط ويعطي المعاني المقابلة.
redis.hostname = 127.0.1.1redis.port = 6379redis.password = https: //blog.hhui.top# timeout timeout timeout. timeout = 10000#الحد الأقصى لعدد الخمول redis.maxidle = 300#تحكم في عدد حالات jedis يمكن جمعها للتجمع لاستبدالها أعلاه. إذا كان Jedis 2.4 ، فاستخدم هذه الخاصية لإعادة redis.maxtotal = 1000#الحد الأقصى لوقت الانتظار للاتصال. إذا تجاوز هذا الوقت هذه المرة ، فسيتم استلام استثناء. ضبط على -1 يعني لا يوجد حد. redis.maxwaitmillis = 1000#الحد الأدنى لوقت الاتصال هو الافتراضي 18000000 مللي ثانية (30 دقيقة) redis.minevictableDletimemillis = 300000#يتم إطلاق الحد الأقصى لعدد الاتصالات في كل مرة ، إذا كان هناك سلبي. الافتراضي -1redis.TimeBetweenevictionRunsMillis = 30000# ما إذا كنت ستحقق قبل إزالة الاتصال من التجمع ، إذا فشل التحقق ، قم بإزالة الاتصال من التجمع وحاول إزالة redis.testonborrow آخر = صحيح# التحقق من صحة عند الخمول.
يوضح
يرجى تذكر تعيين كلمة مرور redis ، خاصة عند السماح بالوصول عن بُعد. إذا لم يكن لديك كلمة مرور ، فسيتم مسح رقم المنفذ الافتراضي بسهولة وحقنه في البرنامج النصي ، ثم البدء في التعدين للأشخاص (تجربة شخصية ...)
وفقًا للفكرة العامة ، أولاً ، يجب عليك تحميل التكوين أعلاه ، وإنشاء تجمع اتصال Redis ، ثم إنشاء كائن Redistemplate ، وأخيراً عقد هذه القوة لبدء عمليات القراءة والكتابة المختلفة
استخدم javaconfig لتكوين ، وخاصة الفاصوليا ، وقراءة ملف التكوين لتعيين مختلف المعلمات ، و redistemplate المتوقعة
@configuration @propertySource ("classpath: redis.properties") تمتد الطبقة العامة redisconfig bean public redisconnectionfactory redisconnectionfactory () {jedisconnectionFactory fac = new JedisconnectionFactory () ؛ Fac.SethostName (evًري. getProperty ("redis.hostname")) ؛ fac.setport (integer.parseint (evesice.getProperty ("redis.port")))) ؛ FAC.SetPassword (Environment.getProperty ("redis.password")) ؛ fac.settimeout (integer.parseint (expleme.getProperty ("redis.timeout"))) ؛ fac.getPoolConfig (). fac.getPoolConfig (). fac.getPoolConfig (). fac.getPoolConfig (). fac.getpoolconfig (). .setnumtestsperutionrun (integer.parseint (البيئة. FAC.GETPOLCONFIG (). redistemplate (Redisconnectionfactory Redisconnectory) Runwith (springJunit4ClassRunner.Class) contextConfiguration (classes = {redisconfig.class}) الفئة العامة Redistest {autowired private redistemplate <string ، string> redistemplate ؛ Test public void testredisobj () {map <string ، Object> properties = new HashMap <> () ؛ Properties.put ("123" ، "Hello") ؛ Properties.put ("ABC" ، 456) ؛ redistemplate.opsforhash (). putAll ("التجزئة" ، الخصائص) ؛ خريطة <كائن ، كائن> ans = redistemplate.opsforhash (). إدخالات ("hash") ؛ System.out.println ("Ans:" + Ans) ؛ }}بعد التنفيذ ، يكون الإخراج كما يلي
الإجابة: {123 = مرحبًا ، ABC = 456}انطلاقًا من التكوين والتنفيذ أعلاه ، يكون الأمر بسيطًا للغاية. لا يوجد أي دائرة في الأساس ، ولكن عندما تقوم بتوصيله بـ Redis-Cli ، لا يمكنك الاستعلام عن محتوى مفتاح التجزئة
127.0.0.
لا توجد مشكلة في استخدام الرمز للتحقق من ذلك. لقد قمت بتوصيل وحدة التحكم مباشرة ووجدت أن هذا المفتاح يختلف عما توقعناه ، مع بعض البادئات ، لماذا؟
من أجل حل المشكلة أعلاه ، لا يمكنني تصحيحها إلا ومعرفة سببها.
موقع رمز المصدر المقابل:
// org.springframework.data.redis.core.abstractoperations#RawKeyByte [] RawKey (مفتاح الكائن) {assert.notnull (المفتاح ، "مفتاح غير فارغ مطلوب") ؛ إرجاع this.keyserializer () == null && مفتاح مثيل byte []؟ (byte []) ((byte []) مفتاح): this.keyserializer (). serialize (مفتاح) ؛}يمكنك أن ترى أن هذا المفتاح ليس المفتاح. getBytes () توقعنا ، ولكن هذا. نتيجة التصحيح هي أن المسلسل الافتراضي هو jdkserializationRedisserializer.
ثم اتبع القرائن وانتقل إلى أعمق خطوة بخطوة ، والرابط كما يلي
// org.springframework.core.serializer.serializingConverter#convert // org.springframework.core.serializer.defaultserializer#serializepublic class defaultserializer تنفذ Serializer <Object> {public defaultserializer () {if (! (Object extryof serializable)) {رمي new alficalArgumentException (this.getClass (). getSimplename () + "يتطلب حمولة قابلة للتسلسل ولكن تلقى كائن من النوع [" + object.getClass (). getName () + "]") ؛ } آخر {objectOutputStream ObjectOutputStream = new ObjectOutputStream (OutputStream) ؛ ObjectOutputStream.writeObject (كائن) ؛ ObjectOutputStream.flush () ؛ }}}وبالتالي فإن التنفيذ المحدد واضح للغاية ، وهو ObjectOutputStream. هذا الشيء هو أكثر أداة تدفق الفخذي التسلسلية بدائية في Java. سيحتوي على معلومات النوع ، لذلك سيتم تجهيزه بالبادئة.
لذلك لحل هذه المشكلة ، يكون ذلك أكثر وضوحًا. استبدل jdkserializationRializer الأصلي وقم بتغييره إلى سلسلة ، والذي يوفر فقط stringRedisserializer ، لذلك عند تكوين redistemplate ، قم بتعديله قليلاً
beanpublic redistemplate <string ، string> redistemplate (RedisConnectionFactory RedisconnectionFactory) {redistemplate <string ، string> redis = new redistemplate <> () ؛ redis.setConnectionFactory (redisconnectionFactory) ؛ // قم بتعيين طريقة التسلسل الافتراضية لـ Redis String/Value StringRedisSerializer StringRedisSerializer = new StringRedisserializer () ؛ redis.setKeySerializer (stringredisserializer) ؛ redis.setValueserializer (stringredisserializer) ؛ redis.SethashkeySerializer (stringredisserializer) ؛ redis.Sethashvalueserializer (stringredisserializer) ؛ redis.afterpropertiesset () ؛ إعادة redis ؛}تنفذ مرة أخرى ، وحدث الشيء المحرج ، وتم طرح الاستثناء ، وفشل تحويل النوع
java.lang.classcastexception: java.lang.integer لا يمكن إلقاؤها إلى java.lang.string في org.springframework.data.redis.serializer.stringredisserializer.serialize (stringredisserializer.java:33) في org.springframework.data.redis.core.abstractoperations.Rawhashvalue (AbstractOprations.Java:171) at org.springframework.data.redis.core.defaulthoashoperations.putall (prowthashAperations.java:129) ...
بالنظر إلى حالة الاختبار السابقة ، فإن القيمة الموجودة في الخريطة تحتوي على عدد صحيح ، ويجب أن تكون المعلمة التي تلقاها stringredisserializer سلسلة ، لذلك لا تستخدم هذا ، وستظل تكتب معاملة متوافقة.
الطبقة العامة DefaultStrSerializer تنفذ Redisserializer <Object> {Private Final Charset Charset ؛ Public DefaultStRserializer () {this (charset.forname ("utf8")) ؛ } Public DefaultStrSerializer (charset charset) {assert.notnull (charset ، "يجب ألا يكون charset فارغًا!") ؛ this.charset = charset ؛ } Override Public Byte [] Serialize (Object O) يلقي SerializationException {return o == null؟ null: string.valueof (o) .getBytes (charset) ؛ } Override الكائن العام Deserialize (byte [] bytes) يلقي serializationException {return bytes == null؟ NULL: سلسلة جديدة (بايت ، charset) ؛ }}ثم يمكنك البدء في الاستمتاع والاختبار بعد التنفيذ
Keys *1) "/XAC/XED/X00/X05T/X00/X04HASH" 2) "Hash" 127.0.0.1:6379> Hgetall Hash1) "123" 2) "Hello" 3) "ABC" 4) "456"
دعونا نرى باختصار وضع الاستخدام لـ Redistemplate ، وقراءة وتغليف طريقة الاتصال التي تستخدمها OPSForXXX لهياكل بيانات مختلفة (السلسلة ، القائمة ، ZSET ، التجزئة).
. setorg.springframework.data.redis.core.redistemplate#opsforzset
بالإضافة إلى طريقة الاستخدام المذكورة أعلاه ، فإن طريقة شائعة أخرى هي استخدام التنفيذ مباشرة. حالة بسيطة هي كما يلي
testpublic void testredis () {string key = "hello" ؛ قيمة السلسلة = "العالم" ؛ redistemplate.execute ((rediscallback <Void>) con -> {con.set (key.getBytes () ، value.getBytes ()) ؛ return null ؛}) ؛ string asn = redistemplate.execute ((rediscallback <string>) con -> سلسلة جديدة (con.get (key.getBytes ()))) ؛ System.out.println (ASN) ؛ String Hkey = "hkey" ؛ redistemplate.execute ((rediscallback <Void>) con -> {con.hset (hkey.getbytes () ، "23" .getBytes () ، "what" .getBytes ()) ؛ return null ؛}) ؛ خريطة <byte [] ، byte []> map = redistemplate.execute ((rediscallback <map <byte [] ، byte []>) con -> con.hgetall (hkey.getbytes ())) ؛ لـ (map.entry <byte [] ، byte [] >> الإدخال: map.entryset ()) {system.out.println ("key:" + new string (intpl.getkey ()) + "| value: }}نتيجة الإخراج على النحو التالي
عالم
المفتاح: 23 | القيمة: ماذا
السؤال الذي يمكن التفكير فيه بشكل طبيعي هو ما هو الفرق بين الطريقتين أعلاه؟
تتم الطبقة الأساسية لـ OPSForXXX عن طريق الاتصال على التنفيذ. إنه يلف بشكل أساسي بعض مواقف الاستخدام ويحدد التسلسل ، مما يجعله أسهل وأكثر ملاءمة للاستخدام. وبهذه الطريقة ، فإن البوق الصغير هو أنه يحتاج إلى إنشاء كائن جديد DefaultXXXOPERATIONS في كل مرة ، ويستغرق خطوة أخرى. بناءً على هذا ، هل سيحقق أداءً إضافيًا وذاكرة تكاليف؟ لم أختبرها ، لكنني شخصياً أشعر أن المبلغ صغير ، يجب ألا يكون هناك أي تأثير واضح ؛ وعندما تكون QPs عالية جدًا ، فإن المساعدة التي يمكن أن يجلبها هذا التحسين المريح ربما لا تكون كثيرًا.
دراسة-ديمو/ربيع-REDIS
ما سبق هو المحتوى الكامل لهذه المقالة. آمل أن يكون لمحتوى هذه المقالة قيمة مرجعية معينة لدراسة أو عمل الجميع. إذا كان لديك أي أسئلة ، فيمكنك ترك رسالة للتواصل. شكرا لك على دعمك إلى wulin.com.