Integrated SprngBoot

steps

  1. Create a New SpringBoot project
  2. Redis integration with SpringBoot requires an importspring-boot-starter-data-redisRely on
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Copy the code

In this case, we can click on the spring-boot-starter-data-redis source code to see that it is still connected to the hyac-core

<dependency>
      <groupId>io.lettuce</groupId>
      <artifactId>lettuce-core</artifactId>
      <version>. 6.0.4 RELEASE</version>
      <scope>compile</scope>
</dependency>
Copy the code
  • Prior to SpringBoot2.x, Jedis: direct connection was used, which is not safe if multiple threads operate, and Jedis Pool connection pool -BIO mode was used
  • After spring Boot2.x, adopt netty, instances can be shared in multiple threads, even safe in multi-threading -NIO mode
  1. Configure redis
# configuration redis
spring.redis.host=192.168.150.131
spring.redis.port=6379
Copy the code

Configuration analysis

RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration

/* * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */

package org.springframework.boot.autoconfigure.data.redis;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

/ * * * {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Redis support.
 *
 * @author Dave Syer
 * @author Andy Wilkinson
 * @author Christian Dupuis
 * @author Christoph Strobl
 * @author Phillip Webb
 * @author Eddú Meléndez
 * @author Stephane Nicoll
 * @author Marco Aust
 * @author Mark Paluch
 * @since1.0.0 * /
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class) 
@EnableConfigurationProperties(RedisProperties.class) // The RedisProperties configuration class exists in Spring
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) // Provide both lettuce and Jedis
public class RedisAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean(name = "redisTemplate")// This redis template is used by default if we do not customize it
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class) 
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) { // Create a separate one for the String
		StringRedisTemplate template = new StringRedisTemplate();
		template.setConnectionFactory(redisConnectionFactory);
		returntemplate; }}Copy the code

If we click on redisProperties.class, we’ll see it

We come back, click LettuceConnectionConfiguration respectively. The class and JedisConnectionConfiguration class, look at the difference between them

LettuceConnectionConfiguration.class

JedisConnectionConfiguration.class

We can see that many Jedis classes do not exist and do not have implementations, and all of them exist, perfectly, so we use Lettuce.

  1. Write simple test class tests
	@Autowired
	private RedisTemplate redisTemplate;

	@Test
	void contextLoads(a) {
		// opsForValue The value is a String of the same type as String
		// Go on and there are other analogies
		redisTemplate.opsForValue().set("k1"."hello");
		System.out.println(redisTemplate.opsForValue().get("k1"));

	}
Copy the code
  1. Console result

  1. Client result (garbled)

Problem found: Client data is garbled

RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration = RedisAutoConfigyration

The solution

In real development, we usually customize the RedisTemplate template, and one is provided here for reference only

package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        
      ,object>
        RedisTemplate<String, Object> template = new RedisTemplate<>();

        // Connect factory
        template.setConnectionFactory(redisConnectionFactory);

        /* * serialization Settings */
        // The key and hash key are serialized by String
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // Value, hash value uses Jackson serialization
        template.setValueSerializer(RedisSerializer.json());
        template.setHashValueSerializer(RedisSerializer.json());
        template.afterPropertiesSet();

        returntemplate; }}Copy the code

After that, use your own custom templates to test in the test class

@Autowired
@Qualifier("redisTemplate")// Be sure to jump to our custom template
private RedisTemplate redisTemplate;
Copy the code

Found normal display, no garbled code!

Then, we find that the method provided by the native Tenplate template is too tedious to write, so how to reduce the stress?

The answer is simple: write utility classes

Here is a tool class written by others for your reference

package com.example.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public final class RedisUtils {

    @Autowired
    private RedisTemplate<String, Object> MyRedisTemplate;  // Inject your own custom template here

    // =============================common============================
    /** * specifies the cache expiration time *@paramThe key key *@paramTime Time (seconds) *@return* /
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                MyRedisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * Get expiration time by key *@paramThe key key cannot be NULL *@returnTime (s) returns 0 for permanently valid */
    public long getExpire(String key) {
        return MyRedisTemplate.getExpire(key, TimeUnit.SECONDS);
    }


    /** * Check whether the key exists *@paramThe key key *@returnTrue Exists false Does not exist */
    public boolean hasKey(String key) {
        try {
            return MyRedisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * delete cache *@paramKey can pass one value or more */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if(key ! =null && key.length > 0) {
            if (key.length == 1) {
                MyRedisTemplate.delete(key[0]);
            } else{ MyRedisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key)); }}}// ============================String=============================
    /** * Common cache fetch *@paramThe key key *@returnValue * /
    public Object get(String key) {
        return key == null ? null : MyRedisTemplate.opsForValue().get(key);
    }

    /** * Normal cache into *@paramThe key key *@paramThe value value *@returnTrue Successful false failed */

    public boolean set(String key, Object value) {
        try {
            MyRedisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * Normal cache is placed and set time *@paramThe key key *@paramThe value value *@paramTime Time (s) Time must be greater than 0. If time is less than or equal to 0, the value is set indefinitely *@returnTrue Successful false failed */
    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                MyRedisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * increment **@paramThe key key *@paramDelta is incremented by a number (greater than 0) *@return* /
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("The increasing factor must be greater than zero.");
        }
        return MyRedisTemplate.opsForValue().increment(key, delta);
    }

    /** * decrements **@paramThe key key *@paramDelta is reduced by a number (less than 0) *@return* /
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("The decrement factor must be greater than zero.");
        }
        return MyRedisTemplate.opsForValue().increment(key, -delta);
    }

    // ================================Map=================================
    /**
     * HashGet
     *
     * @paramThe key key cannot be NULL *@paramItem items cannot be null *@returnValue * /
    public Object hget(String key, String item) {
        return MyRedisTemplate.opsForHash().get(key, item);
    }

    /** * get all keys ** corresponding to the hashKey@paramThe key key *@returnCorresponding multiple key values */
    public Map<Object, Object> hmget(String key) {
        return MyRedisTemplate.opsForHash().entries(key);
    }


    /**
     * HashSet
     *
     * @paramThe key key *@paramMap corresponds to multiple key values *@returnTrue Successful false failed */
    public boolean hmset(String key, Map<String, Object> map) {
        try {
            MyRedisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * HashSet and set the time **@paramThe key key *@paramMap corresponds to multiple key values *@paramTime Time (seconds) *@returnTrue Successful false failed */
    public boolean hmset(String key, Map<String, Object> map, long time) {
        try {
            MyRedisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * puts data into a hash table, or creates ** if none exists@paramThe key key *@paramItem item *@paramThe value value *@returnTrue Successful false failed */
    public boolean hset(String key, String item, Object value) {
        try {
            MyRedisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * puts data into a hash table, or creates * 0 ** if none exists@paramKey key * 1 *@paramItem item *@paramThe value value *@paramTime Time (s) Note: If the existing hash table has time, the original time * will be replaced@returnTrue Successful false failed */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            MyRedisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * 0 * Deletes the value * 1 ** from the hash table@paramThe key key cannot be NULL *@paramItem items can be more than null */
    public void hdel(String key, Object... item) {
        MyRedisTemplate.opsForHash().delete(key, item);
    }


    /** * determines whether the value of the item * 0 ** exists in the hash table@paramThe key key cannot be NULL * 1 *@paramItem items cannot be null *@returnTrue Exists false Does not exist */
    public boolean hHasKey(String key, String item) {
        return MyRedisTemplate.opsForHash().hasKey(key, item);
    }


    /** * hash increments that do not exist create one and return the new value * 0 **@paramKey key * 1 *@paramItem item *@paramBy is going to be increased by how much (greater than 0) star@return* /
    public double hincr(String key, String item, double by) {
        return MyRedisTemplate.opsForHash().increment(key, item, by);
    }


    /** * hash decrement **@paramThe key key *@paramItem item *@paramI'm going to subtract by (less than 0) star@return* /
    public double hdecr(String key, String item, double by) {
        return MyRedisTemplate.opsForHash().increment(key, item, -by);
    }


    // ============================set=============================
    /** * Get all values in Set based on key **@paramThe key key *@return* /
    public Set<Object> sGet(String key) {
        try {
            return MyRedisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null; }}/** * select * from a set based on value@paramThe key key *@paramThe value value *@returnTrue Exists false Does not exist */
    public boolean sHasKey(String key, Object value) {
        try {
            return MyRedisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * Put the data into the set cache **@paramThe key key *@paramValues can be multiple *@returnNumber of successes */
    public long sSet(String key, Object... values) {
        try {
            return MyRedisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0; }}/** * Put set data into cache **@paramThe key key *@paramTime Time (seconds) *@paramValues can be multiple *@returnNumber of successes */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = MyRedisTemplate.opsForSet().add(key, values);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0; }}/** * Get the length of the set cache **@paramThe key key *@return* /
    public long sGetSetSize(String key) {
        try {
            return MyRedisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0; }}/** ** removes value * 0 **@paramKey key * 1 *@paramValues can be multiple *@returnNumber of removals */
    public long setRemove(String key, Object... values) {
        try {
            Long count = MyRedisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0; }}// ===============================list=================================
    /** * retrieve the contents of the list cache **@paramThe key key *@paramStart to *@paramEnd End 0 to -1 represent all values *@return* /
    public List<Object> lGet(String key, long start, long end) {
        try {
            return MyRedisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null; }}/** * Get the length of the list cache **@paramThe key key *@return* /
    public long lGetListSize(String key) {
        try {
            return MyRedisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0; }}/** * Get the value ** from the list by index@paramThe key key *@paramIndex index>=0, 0, 1, second element, and so on; Index <0, -1, end of the table, - next-to-last element, and so on *@return* /
    public Object lGetIndex(String key, long index) {
        try {
            return MyRedisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null; }}/** * put lSet into cache **@paramThe key key *@paramThe value value *@return* /
    public boolean lSet(String key, Object value) {
        try {
            MyRedisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * Put the list in the cache **@paramThe key key *@paramThe value value *@paramTime Time (seconds) *@return* /
    public boolean lSet(String key, Object value, long time) {
        try {
            MyRedisTemplate.opsForList().rightPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * put lSet into cache **@paramThe key key *@paramThe value value *@return* /
    public boolean lSet(String key, List<Object> value) {
        try {
            MyRedisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * Put the list in the cache **@paramThe key key *@paramThe value value *@paramTime Time (seconds) *@return* /
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            MyRedisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * Modify a list of data ** based on the index@paramThe key key *@paramThe index index *@paramThe value value *@return* /
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            MyRedisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * remove N values to value **@paramThe key key *@paramCount removes how many *@paramThe value value *@returnNumber of removals */
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = MyRedisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0; }}}Copy the code