(6) Spring Boot 2.0 Foundation - MyBatis, Redis Integration (Jedis Cluster Cluster Connection)

Keywords: Java Redis Spring Jedis

I. environment

  Redis:4.0.9

  SpringBoot:2.0.1

Redis installation: Linux(Redhat) Installation of Redis

2. SpringBook Integration Redis

1. Basic construction of the project:

We are based on (5) SpringBoot 2.0 Foundation - Mybatis and Plug-in Generation Code Redis integration for this project;

2. Add maven-related dependencies and Redis connection information:

    Pom.xml

    <!-- Redis Dependency Library -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-redis</artifactId>
      <version>1.4.7.RELEASE</version>
    </dependency>

    <!-- fastJson Dependency Library -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.28</version>
    </dependency>

    <!-- aop Dependency Library-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

    application.properties:

spring.redis.cluster.nodes=192.168.1.124:7001

3. Create RedisProperties attribute class and RedisConfig configuration class, and put JedisCluster into Spring container:

    RedisConfigurationProperties:
package com.cn.common.redis;

import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @program: spring-boot-example
 * @description:
 * @author:
 * @create: 2018-05-16 15:15
 **/
@Configuration
@ConfigurationProperties(prefix = "spring.redis.cluster")
public class RedisConfigurationProperties {

    private List<String> nodes = new ArrayList<>();

    public List<String> getNodes() {
        return nodes;
    }

    public void setNodes(List<String> nodes) {
        this.nodes = nodes;
    }
}
    RedisConfig:
package com.cn.common.redis;

import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

/**
 * @program: spring-boot-example
 * @description: Redis Configuration file
 * @author:
 * @create: 2018-05-16 15:01
 **/
@Configuration
public class RedisConfig {

    @Autowired
    private RedisConfigurationProperties redisConfigurationProperties;

    @Bean
    public JedisCluster jedisCluster() {
        Set<HostAndPort> nodeSet = new HashSet<>();
        for(String node :redisConfigurationProperties.getNodes()) {
            String[] split = node.split(":");
            nodeSet.add(new HostAndPort(split[0],Integer.valueOf(split[1])));
        }
        return new JedisCluster(nodeSet);
    }

}

4. Create a Jedis Service (Jedis Service Impl) encapsulating Redis:

package com.cn.common.service;

import java.util.List;
import java.util.Map;
import redis.clients.jedis.GeoRadiusResponse;

/**
 * @program: spring-boot-example
 * @description:
 * @author:
 * @create: 2018-05-16 15:27
 **/
public interface JedisService {

    /**
     * @Description: Does it exist?
     * @Param:
     * @return:
     * @Author:
     * @Date: 2018/5/16
     */
    boolean exists(String key);

    /**
     * @Description:Cache set value
     * @Param:  seconds:Cache time, not set to 0
     * @return:
     * @Author:
     * @Date: 2018/5/16
     */
    String set(String key,String value,int seconds);

    /**
     * @Description:  Recaching getSet values
     * @Param:
     * @return:
     * @Author:
     * @Date: 2018/5/16
     */
    String getSet(String key,String value, int seconds);

    /**
     * @Description: Get set value
     * @Param:
     * @return:
     * @Author:
     * @Date: 2018/5/16
     */
    String get(String key);

    /**
     * @Description: Adding Geographical Location
     * @Param:
     * @return:
     * @Author:
     * @Date: 2018/5/16
     */
    Long geoadd(String key,double longitude,double latitude,byte[] obj);

    /**
     * @Description: Geographical Location Query
     * @Param:
     * @return:
     * @Author: 
     * @Date: 2018/5/16
     */
    List<GeoRadiusResponse> georadius(String key,double longitude,double latitude);
    
    /** 
     * @Description: Delete key 
     * @Param:  
     * @return:  
     * @Author: 
     * @Date: 2018/5/16 
     */ 
    void delKey(String key);
    
    /** 
     * @Description: Delete native key 
     * @Param:  
     * @return:  
     * @Author: 
     * @Date: 2018/5/16 
     */ 
    void delNativeKey(String key);
    
    /** 
     * @Description: Get data in map format 
     * @Param:  
     * @return:  
     * @Author: 
     * @Date: 2018/5/16 
     */ 
    Map<String ,Object> getMapData(String key);
    
    /** 
     * @Description: Lock to avoid duplicate submission 
     * @Param:  
     * @return:  
     * @Author: 
     * @Date: 2018/5/16 
     */ 
    boolean lock(String key,int seconds);
    
    /** 
     * @Description: Unlock 
     * @Param:  
     * @return:  
     * @Author: 
     * @Date: 2018/5/16 
     */ 
    void unlock(String key);    
    
    /** 
     * @Description: Statistical lockout times
     * @Param:  
     * @return:  
     * @Author:
     * @Date: 2018/5/16 
     */ 
    String getLocakValue(String key);
}
JedisService.java
package com.cn.common.service;

import com.alibaba.fastjson.JSON;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.GeoRadiusResponse;
import redis.clients.jedis.JedisCluster;

/**
 * @program: spring-boot-example
 * @description:
 * @author:
 * @create: 2018-05-16 15:45
 **/
@Service
public class JedisServiceImpl implements JedisService {


    @Autowired
    private JedisCluster jedisCluster;

    @Override
    public boolean exists(String key) {
        boolean flag = false;
        flag = jedisCluster.exists(key);
        return flag;
    }

    @Override
    public String set(String key, String value, int seconds) {
        String responseResult = jedisCluster.set(key,value);
        if(seconds!=0)
            jedisCluster.expire(key,seconds);
        return responseResult;
    }

    @Override
    public String getSet(String key, String value, int seconds) {
        String jedisClusterSet = jedisCluster.getSet(key, value);
        jedisCluster.expire(key,seconds);
        return jedisClusterSet;
    }

    @Override
    public String get(String key) {
        String str = jedisCluster.get(key);
        return str;
    }

    @Override
    public Long geoadd(String key, double longitude, double latitude, byte[] obj) {
        return null;
    }

    @Override
    public List<GeoRadiusResponse> georadius(String key, double longitude, double latitude) {
        return null;
    }

    @Override
    public void delKey(String key) {
        jedisCluster.del(key);
    }

    @Override
    public void delNativeKey(String key) {
        jedisCluster.del(key);
    }

    @Override
    public Map<String, Object> getMapData(String key) {
        String str = jedisCluster.get(key);
        Map<String,Object> map = JSON.parseObject(str, Map.class);
        return map;
    }

    /** 
     * @Description: For the first time, a lock is added, and the value of each call is automatically increased by 1.
     * @Param:
     * @return:  
     * @Author:
     * @Date: 2018/5/16 
     */ 
    @Override
    public boolean lock(String key, int seconds) {
        if(jedisCluster.incr(key)==1) {
            jedisCluster.expire(key,seconds);
            return false;
        }
        return true;
    }

    @Override
    public void unlock(String key) {
        jedisCluster.del(key);
    }

    @Override
    public String getLocakValue(String key) {
        return jedisCluster.get(key);
    }

}
JedisServiceImpl.java

5. Create annotation classes and aspect classes (I use annotations to implement cached set and get):

    RedisCache:
package com.cn.common.redis;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @Description: With this annotation, the proxy service hit cache reads data from the cache, otherwise it is obtained from the service business logic and stored in the cache.
 * @Param:
 * @return:
 * @Author:
 * @Date: 2018/5/16
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
@Documented
public @interface RedisCache {

    /**
     * @Description: Data return type
     * @Param:
     * @return:
     * @Author:
     * @Date: 2018/5/16
     */
    Class type();

    /**
     * @Description: Data caching time unit s seconds
     * @Param:  Default 10 minutes
     * @return:
     * @Author:
     * @Date: 2018/5/16
     */
    int cacheTime() default 600;

}

    RedisCacheAspect:

package com.cn.common.redis;


import com.alibaba.fastjson.JSON;
import com.cn.common.service.JedisService;
import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @program: spring-boot-example
 * @description:
 * @author:
 * @create: 2018-05-16 16:29
 **/

@Aspect
@Component
public class RedisCacheAspect {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private JedisService jedisService;

    @Pointcut("execution(public * com.cn.service..*.*(..))")
    public void webAspect(){}

    @Around("webAspect()")
    public Object redisCache(ProceedingJoinPoint pjp) throws Throwable {
        //Get the class name, method name, and parameters
        String redisResult = "";
        String className = pjp.getTarget().getClass().getName();
        String methodName = pjp.getSignature().getName();
        Object[] args = pjp.getArgs();
        //Generate method names and parameters based on class names key
        String key = genKey(className,methodName,args);
        logger.info("Generated key[{}]",key);
        //The Method of Obtaining the Agent
        Signature signature = pjp.getSignature();
        if(!(signature instanceof MethodSignature)){
            throw  new IllegalArgumentException();
        }
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = pjp.getTarget().getClass().getMethod(methodSignature.getName(),methodSignature.getParameterTypes());
        //Obtain annotations on the method of the agent
        Class modelType = method.getAnnotation(RedisCache.class).type();
        int cacheTime = method.getAnnotation(RedisCache.class).cacheTime();
        Object result = null;
        if(!jedisService.exists(key)) {
            logger.info("Cache Miss");
            //If the cache does not exist, the original method is called and the result is put into the cache.
            result = pjp.proceed(args);
            redisResult = JSON.toJSONString(result);
            jedisService.set(key,redisResult,cacheTime);
        } else{
            //Cache Hit
            logger.info("Cache Hit");
            redisResult = jedisService.get(key);
            //Get the return value type of the proxy method
            Class returnType = method.getReturnType();
            result = JSON.parseObject(redisResult,returnType);
        }
        return result;
    }

    /**
     * @Description: Generate key
     * @Param:
     * @return:
     * @Author:
     * @Date: 2018/5/16
     */
    private String genKey(String className, String methodName, Object[] args) {
        StringBuilder sb = new StringBuilder("SpringBoot:");
        sb.append(className);
        sb.append("_");
        sb.append(methodName);
        sb.append("_");
        for (Object object: args) {
            logger.info("obj:"+object);
            if(object!=null) {
                sb.append(object+"");
                sb.append("_");
            }
        }
        return sb.toString();
    }

}

6. Add caching annotations in Student Service Impl:

    StudentServiceImpl:

package com.cn.service;

import com.cn.common.redis.RedisCache;
import com.cn.entity.Student;
import com.cn.mapper.StudentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @program: spring-boot-example
 * @description:
 * @author:
 * @create: 2018-05-11 10:55
 **/
@Service
public class StudentServiceImpl implements StudentService{

    @Autowired
    private StudentMapper studentMapper;

    @Override
    @RedisCache(type = Student.class)
    public Student getStudentByPrimaryKey(int id) {
        return studentMapper.selectByPrimaryKey(id);
    }
}

7. Start the test:

First call:

    

View the console:

    

    

Second call:

    

View the console:

    

Discovered that MyBatis's query log was not printed for the second time, and displayed the cache hit. View the Redis cache through the RedisDeskManager tool:

    

    

 

 

Example code: https://gitee.com/lfalex/spring-boot-example/tree/dev/spring-boot-mybatis-redis

Posted by ponies3387 on Tue, 05 Feb 2019 07:18:16 -0800