Предисловие
Пружина инкапсулирует относительно мощный шаблон для удобного использования при использовании Redis; Я использовал Redis в экосистеме Spring раньше, но непосредственно использовал Jedis для соответствующих взаимодействий. Теперь давайте посмотрим на то, как реализован Redistemplate и является ли он удобнее использовать.
Jedis по-прежнему используется для управления пулом соединений, поэтому в дополнение к введению Spring-Data-REDIS, а также зависимости jedis, добавьте файл POM
<depervice> <groupid> org.springframework.data </groupid> <artifactid> spring-data-redis </artifactid> <sersive> 1.8.4.release </version> </redise> <dependence> <groupid>.
Если вам нужно указать параметры, связанные с сериализацией, вы также можете представить Джексона. Эта статья простой начальный уровень, поэтому вы не добавите этого
Подготовьте параметры конфигурации, связанные с REDIS, общие включают хост, порт, пароль, тайм-аут .... Ниже приведена простая конфигурация и дает соответствующие значения.
redis.hostname = 127.0.0.1redis.port = 6379redis.password = https: //blog.hhui.top# timeout timeout redis.timeout = 10000#Максимальный номер холостого хода redis.maxidle = 300#контролирует, сколько случаев Jedis может быть выделено для пула, чтобы заменить выше Redis. Если это Jedis 2.4, используйте это свойство для Redis.maxtotal = 1000#Максимальное время ожидания подключения. Если на этот раз превысит на этот раз, будет получено исключение. Установка в -1 означает отсутствие предела. redis.maxwaitmillis = 1000#Минимальное время простоя подключения - по умолчанию 18000000 мс (30 минут) redis.minevictableidletimelis = 300000#Максимальное количество соединений высвобождается каждый раз, default 3redis.numtestsperevictionrun = 1024#Время времени для экикции SCAN (MS), если это негативно. По умолчанию -1Redis.timeWeeWeeVictionRunSmillis = 30000#, чтобы проверить, перед снятием соединения из пула, если проверка сбой, удалите соединение из пула и попытаться удалить еще один Redis.TestonBorrow = true# Проверьте достоверность, когда на холостом ходу, defaultis.testwhileidle = true.
иллюстрировать
Пожалуйста, не забудьте установить пароль Redis, особенно при разрешении удаленного доступа. Если у вас нет пароля, номер порта по умолчанию будет легко отсканирован и введен в сценарий, а затем начните добывать для людей (личный опыт ...)
Согласно общей идее, сначала вы должны загрузить вышеуказанную конфигурацию, создать пул подключений Redis, а затем создать создание объекта Redistemplate и, наконец, удерживать эту силу, чтобы начать различные операции чтения и записи
Используйте javaconfig для настройки, в основном двух бобов, прочтите файл конфигурации, чтобы установить различные параметры и ожидаемый Redistemplate
@Configuration @propertysource ("classpath: redis.properties") открытый класс Redisconfig Extends jcacheconfigurersupport {@autowired частная среда; @Bean public redisconnectionFactory RedisconnectionFactory () {jedisconnectionFactory fac = new jedisconnectionFactory (); fac.sethostname (Environment.getProperty ("redis.hostname")); fac.setport (integer.parseint (Environment.getProperty ("redis.port"))); fac.setpassword (Environment.getProperty ("Redis.Password")); fac.settimeout (integer.parseint (Environment.getProperty ("Redis.TimeOut"))); fac.getpoolconfig (). setmaxidle (integer.parseint (Environment.getProperty ("redis.maxidle"))); fac.getpoolconfig (). setmaxtotal (integer.parseint (Environment.getProperty ("redis.maxtotal"))); fac.getpoolconfig (). setmaxwaitmillis (integer.parseint (Environment.getProperty ("redis.maxwaitmillis"))); fac.getPoolConfig (). SetMineVictableIdletImeMillis (integer.parseint (Environment.getProperty ("Redis.MinevictableIdletImeMillis"))); fac.getPoolConfig (). SetMineVictableIdletImeMillis "))); fac.getPoolConfig (). SetMineVictableIdletimelis (integer.parseint (Environment.getProperty (" redis.minevictableidletimemillis ")); fac.getpoolconfig () .setnumTestSperevictionRun (integer.parseint (Environment.getProperty ("Redis.numtestSperevictionRun")); fac.getPoolConfig (). SetteStonBorw (Boolean.parseboolean (Environment.getproperty ("Redis.testonbork")); Redistemplate (RedisconnectionFactory RedisconnectionFactory) {Redistemplate <String, String> Redis = new Redistemplate <> (); @Runwith (springjunit4classrunner.class) @contextconfiguration (classes = {redisconfig.class}) public 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 ("hash", свойства); Map <объект, объект> ans = redistemplate.opsforhash (). Negries ("hash"); System.out.println ("ans:" + ans); }}После выполнения вывод выглядит следующим образом
Ответ: {123 = Привет, ABC = 456}Судя по вышеуказанной конфигурации и реализации, это очень просто. В основном нет круга, но когда вы подключаете его с Redis-Cli, вы не можете запросить содержание хэш-ключа
127.0.0.1:6379> GET HASH (NIL) 127.0.0.1:6379> Клавиши *1) "/xac/xed/x00/x05t/x00/x04hash"
Нет проблем с использованием кода, чтобы проверить его. Я напрямую соединил консоль и обнаружил, что этот ключ отличается от того, что мы ожидали, с некоторыми префиксами, почему?
Чтобы решить вышеуказанную проблему, я могу только отладить ее и посмотреть, что вызвало ее.
Соответствующее местоположение исходного кода:
// org.springframework.data.redis.core.abstractoperations#rawkeybyte [] rawkey (object key) {assert.notnull (ключ, «не требуется не нулевой ключ»); вернуть это.keyserializer () == null && key ancementof byte []? (byte []) ((byte []) key): this.keyserializer (). serialize (key);}Вы можете видеть, что этот ключ не является Key.getBytes (), который мы ожидали, но это. Результатом отладки является то, что сериализатором по умолчанию является jdkserializationredisserializer.
Затем перейдите по подсказкам и сделайте шаг за шагом глубже, ссылка следующая
// org.springframework.core.serializer.serializeConverter#преобразование // org.springframework.core.serializer.defaultserializer#serializepublic class defaulteeriz {if (! (Extance ObjectOf serializable)) {Throw new allodalargumentException (this.getClass (). getSiMplename () + "требует сериализуемой полезной нагрузки, но получил объект типа [" + object.getClass (). getName () + "]"); } else {objectOutputStream objectOutputStream = new objectOutputStream (outputStream); objectOutputStream.WriteObject (Object); objectOutputStream.flush (); }}}Таким образом, конкретная реализация очень ясна, что является объектно -аудиторией. Эта вещь - самый примитивный сериализованный инструмент потоковой передачи пустыней в Java. Он будет содержать информацию типа, поэтому он будет оснащен префиксом.
Итак, чтобы решить эту проблему, это яснее. Замените нативный jdkserializationredisserializer и измените его на строку, которая просто обеспечивает StringRedisserializer, поэтому при конфигурации Redistemplate слегка измените его
@Beanpublic redistemplate <string, string> redistemplate (redisconnectionfactory redisconnectionFactory) {redistemplate <string, string> redis = new Redistemplate <> (); Redis.setConnectionFactory (RedisconnectionFactory); // Установить метод сериализации по умолчанию Redis String/значение 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 at org.springframework.data.redis.serializer.stringredisserializ org.springframework.data.redis.core.abstractoperations.rawhashvalue (Abstractoportions.java:171) на org.springframework.data.redis.core.defaulthashoperations.putall (defaulthashoperations.java:129) ...
Глядя на предыдущий тестовый пример, значение на карте имеет целое число, а параметр, полученный StringRedisserializer, должен быть строкой, поэтому не используйте это, и вы все равно будете писать совместимый.
Общедоступный класс Defaltrserializer реализует 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) Throws SerializationException {return o == null? null: string.valueof (o) .getbytes (charset); } @Override public Object deserialize (byte [] bytes) бросает serializationexception {return bytes == null? null: новая строка (байты, charset); }}Затем вы можете начать веселиться и проверять после исполнения
Клавиши *1) "/xac/xed/x00/x05t/x00/x04hash" 2) "hash" 127.0.0.1:1:6379> hgetall hash1) "123" 2) "Привет" 3) "ABC" 4) "456"
Давайте кратко увидим позу использования Redistemplate, и прочитаем и инкапсулируем призывник, используемый OPSForxxx для различных структур данных (строка, список, ZSET, хэш).
// Хэш -структура данных Org.springframework.data.redis.core.redistemplate#opsforhash // distorg.springframework.data.redis.core.redistemplate#opsforlist // sthringorg.springframework.data.redis.core.redisteplate#opsforg.springframework.data.redis.core.redisteplate#opsforg.springframe.data.redis.core.redistepl setorg.springframework.data.redis.core.redistemplate#opsforzset
В дополнение к вышеуказанному методу использования, еще один распространенный - напрямую использовать выполнение. Простой случай заключается в следующем
@Testpublic void testredis () {string key = "hello"; String value = "world"; redistemplate.execute ((rediscallback <void>) con -> {con.set (key.getbytes (), value.getbytes ()); return null;}); String asn = redistemplate.execute ((rediscallback <string>) con -> new String (con.get (key.getbytes ()))); System.out.println (ASN); String hkey = "hkey"; redistemplate.execute ((rediscallback <void>) con -> {con.hset (hkey.getbytes (), "23" .getbytes (), "что" .getbytes ()); return null;}); Map <byte [], byte []> map = redistemplate.execute ((rediscallback <map <byte [], byte []>) con -> con.hgetall (hkey.getbytes ())); for (map.Entry <byte [], byte [] >> intpirt: map.entryset ()) {system.out.println ("key:" + new String (intry.getKey ()) + "| value:" + new String (interval.getValue ())); }}Результат вывода выглядит следующим образом
мир
Ключ: 23 | Значение: что
Вопрос, о котором можно подумать о естественном смысле, заключается в том, в чем разница между двумя вышеупомянутыми методами?
Базовый уровень OPSFORXXX выполняется с помощью вызова выполнения. В основном он инкапсулирует некоторые позы использования и определяет сериализацию, что делает ее проще и удобнее использования. Таким образом, небольшая труба заключается в том, что ей нужно каждый раз создавать новый объект DefaultXXXOperations, и это занимает еще один шаг. Основываясь на этом, принесет ли это дополнительную производительность и накладные расходы на память? Я не проверял это, но лично я чувствую, что количество мало, не должно быть очевидного влияния; И когда QP очень высок, помощь, которую может принести удобная оптимизация, вероятно, не так уж много.
Исследование-демо/пружина
Вышеуказанное - все содержание этой статьи. Я надеюсь, что содержание этой статьи имеет определенную справочную ценность для каждого обучения или работы. Если у вас есть какие -либо вопросы, вы можете оставить сообщение для общения. Спасибо за поддержку Wulin.com.