(六)SpringBoot2.0基礎篇- MyBatis、Redis整合(JedisCluster集羣鏈接)

1、環境

  Redis:4.0.9html

  SpringBoot:2.0.1java

  Redis安裝:Linux(Redhat)安裝Redisnode

2、SpringBoot整合Redis

  一、項目基本搭建:git

    咱們基於(五)SpringBoot2.0基礎篇- Mybatis與插件生成代碼 該項目來作Redis整合;web

  二、添加maven相關依賴和Redis的鏈接信息:redis

    Pom.xmlspring

<!-- Redis的依賴庫 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-redis</artifactId>
      <version>1.4.7.RELEASE</version>
    </dependency>

    <!-- fastJson 依賴庫 -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.28</version>
    </dependency>

    <!-- aop依賴庫-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

    application.properties:json

spring.redis.cluster.nodes=192.168.1.124:7001

  三、建立RedisProperties屬性類和RedisConfig配置類,將JedisCluster放入Spring容器中:緩存

    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的配置文件 * @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); } }

  四、建立封裝Redis的增刪改查(JedisService,JedisServiceImpl):mybatis

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: 是否存在 * @Param: * @return: * @Author: * @Date: 2018/5/16 */
    boolean exists(String key); /** * @Description:緩存set值 * @Param: seconds:緩存時間,不設置則爲0 * @return: * @Author: * @Date: 2018/5/16 */ String set(String key,String value,int seconds); /** * @Description: 從新緩存getSet值 * @Param: * @return: * @Author: * @Date: 2018/5/16 */ String getSet(String key,String value, int seconds); /** * @Description: 獲取set值 * @Param: * @return: * @Author: * @Date: 2018/5/16 */ String get(String key); /** * @Description: 添加地理位置 * @Param: * @return: * @Author: * @Date: 2018/5/16 */ Long geoadd(String key,double longitude,double latitude,byte[] obj); /** * @Description: 地理位置查詢 * @Param: * @return: * @Author: * @Date: 2018/5/16 */ List<GeoRadiusResponse> georadius(String key,double longitude,double latitude); /** * @Description: 刪除key * @Param: * @return: * @Author: * @Date: 2018/5/16 */ 
    void delKey(String key); /** * @Description: 刪除native key * @Param: * @return: * @Author: * @Date: 2018/5/16 */ 
    void delNativeKey(String key); /** * @Description: 獲取map格式的數據 * @Param: * @return: * @Author: * @Date: 2018/5/16 */ Map<String ,Object> getMapData(String key); /** * @Description: 加鎖,避免重複提交 * @Param: * @return: * @Author: * @Date: 2018/5/16 */ 
    boolean lock(String key,int seconds); /** * @Description: 解鎖 * @Param: * @return: * @Author: * @Date: 2018/5/16 */ 
    void unlock(String key); /** * @Description: 統計鎖定次數 * @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: 如爲第一次,則加上鎖,每次調用值會自動加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

  五、建立註解類和切面類(我使用註解來實現緩存的set和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: 加上該註解,代理service命中緩存則從緩存中讀取數據,不然從service業務邏輯得到,並存入緩存 * @Param: * @return: * @Author: * @Date: 2018/5/16 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD,ElementType.TYPE}) @Documented public @interface RedisCache { /** * @Description: 數據返回類型 * @Param: * @return: * @Author: * @Date: 2018/5/16 */ Class type(); /** * @Description: 數據緩存時間單位s秒 * @Param: 默認10分鐘 * @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 { //獲得類名、方法名和參數
        String redisResult = ""; String className = pjp.getTarget().getClass().getName(); String methodName = pjp.getSignature().getName(); Object[] args = pjp.getArgs(); //根據類名,方法名和參數生成key
        String key = genKey(className,methodName,args); logger.info("生成的key[{}]",key); //獲得被代理的方法
        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()); //獲得被代理的方法上的註解
        Class modelType = method.getAnnotation(RedisCache.class).type(); int cacheTime = method.getAnnotation(RedisCache.class).cacheTime(); Object result = null; if(!jedisService.exists(key)) { logger.info("緩存未命中"); //緩存不存在,則調用原方法,並將結果放入緩存中
            result = pjp.proceed(args); redisResult = JSON.toJSONString(result); jedisService.set(key,redisResult,cacheTime); } else{ //緩存命中
            logger.info("緩存命中"); redisResult = jedisService.get(key); //獲得被代理方法的返回值類型
            Class returnType = method.getReturnType(); result = JSON.parseObject(redisResult,returnType); } return result; } /** * @Description: 生成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(); } }

  六、在StudentServiceImpl中加入緩存註釋:

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

  七、啓動測試:

    第一次調用:

    

    查看控制檯:

    

    

    第二次調用:

    

    查看控制檯:

    

    發現第二次未打印出MyBatis的查詢日誌,而且顯示緩存命中,經過RedisDeskManager工具查看Redis緩存:

    

    

 

 

實例代碼:https://gitee.com/lfalex/spring-boot-example/tree/dev/spring-boot-mybatis-redis

相關文章
相關標籤/搜索