Spring Cloud | 总结 二: Mybatis多数据源+Redis二级缓存+Feign调用

一、简述

这几天补充了下文档,这里接《Spring Cloud终篇 | 总结 一:一个完整的企业级SpringCloud架构(Mybatis--多数据源)》之后,简述一下Redis二级缓存feign的调用方式。


源码案例:https://github.com/liujun19921020/SpringCloudDemo/blob/master/ProjectDemo/企业SpringCloud架构-xxljob-redis-elasticsearch
或 :链接:https://pan.baidu.com/s/1ooqaIRSeX6naOZ51aBWNHA  提取码:cwsw

这里是整了一个架构集合案例,其中的ES/xxl-job将在下两章讲解,该文主要源码为sc-muster-item-demo项目


二、概述Feign调用

案例中,在sc-muster-item-demo项目中调用sc-item-demo项目中的"/orderProduct/updateOrderStatus"接口(pom.xml引包、添加注解等详细操作步骤可回顾下《Spring Cloud教程 | 第四篇:服务消费者(Feign调用)》等)

在sc-muster-item-demo项目中配置调用sc-item-demo项目的FeignClient,这里把熔断类也加上了,实际使用中可根据情况看是否需要。

/**
 * 调用sc-item-demo服务
 */
@FeignClient(name = "sc-item-demo",fallback = ScItemDemoFeignHystrix.class)
public interface ScItemDemoFeignClient {

    /**
     * 根据 订单号(批量)/商品sku 修改订单状态
     * @param data
     * @return
     */
    @PostMapping("/orderProduct/updateOrderStatus")
    ResponseMsg updateOrderStatus(@RequestBody JSONObject data);
}

 

/**
 * 调用sc-item-demo服务熔断类
 */
@Component
public class ScItemDemoFeignHystrix implements ScItemDemoFeignClient {
    @Override
    public ResponseMsg updateOrderStatus(JSONObject data) {
        return null;
    }
}

然后我们通过Service调用对应的FeignClient方法即可,如下,

@Service
public class OrderAmazonDetailServiceImpl implements IOrderAmazonDetailService {

    @Autowired
    private ScItemDemoFeignClient scItemDemoFeignClient;

    /**
     * 根据 订单号/商品sku 批量修改订单状态(Feign方式调用)
     * @param data
     */
    @Override
    public void updateOrderStatus(JSONObject data) throws Exception {
        ResponseMsg responseMsg = scItemDemoFeignClient.updateOrderStatus(data);
        if (null == responseMsg) {// 调用服务失败
            throw new Exception("调用sc-item-demo服务失败");
        }
        if (responseMsg.getCode() != Code.SUCCESS) {// 调用服务报错
            throw new Exception(responseMsg.getMsg());
        }
        //List> categoryIdAndNameLine = JSON.parseObject(JSON.toJSONString(responseMsg.getData()), new TypeReference>>(){}.getType());//如果data中有list返回值,可以如图所示的转译
    }

}

通过调用sc-muster-item-demo项目的接口可以看到调用成功,Controller我就不贴出来了

Spring Cloud | 总结 二: Mybatis多数据源+Redis二级缓存+Feign调用_第1张图片


三、概述Redis使用

1、啥也不说,先配置数据源,没配置啥也不能干

#----------------------------------redis配置. 线上请用Redis Cluster---------------------------------------------
#spring.redis.cluster.nodes=39.108.60.150:7001,39.108.60.150:7002,119.23.237.229:7003,119.23.237.229:7004,120.77.157.244:7005,120.77.157.244:7006
spring.redis.host=192.168.71.146
spring.redis.port=23230
spring.redis.password=yibai_dev@redis
spring.redis.jedis.pool.max-active=1000
spring.redis.jedis.pool.max-idle=10
spring.redis.jedis.pool.min-idle=2
spring.redis.jedis.timeout=2000


2、先说说用Redis做二级缓存,需要实现Cache类。

/**
 * 使用Redis来做Mybatis的二级缓存
 * 实现Mybatis的Cache接口
 */
public class MybatisRedisCache implements Cache {

    private static final Logger logger = LoggerFactory.getLogger(MybatisRedisCache.class);

    // 读写锁
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);

    @Resource
    private RedisTemplate redisTemplate;

    private String id;

    public MybatisRedisCache(final String id) {
        if (id == null) {
            throw new IllegalArgumentException("Cache instances require an ID");
        }
        logger.info("Redis Cache id " + id);
        this.id = id;
    }

    @Override
    public String getId() {
        return this.id;
    }

    @Override
    public void putObject(Object key, Object value) {
        logger.info("key==================>" + key);
        if (value != null) {
            // 向Redis中添加数据,有效时间是2天
            redisTemplate.opsForValue().set(key.toString(), value, 2, TimeUnit.DAYS);
        }
    }

    @Override
    public Object getObject(Object key) {
        try {
            if (key != null) {
                Object obj = redisTemplate.opsForValue().get(key.toString());
                return obj;
            }
        } catch (Exception e) {
            logger.error("redis ");
        }
        return null;
    }

    @Override
    public Object removeObject(Object key) {
        try {
            if (key != null) {
                redisTemplate.delete(key.toString());
            }
        } catch (Exception e) {
        }
        return null;
    }

    @Override
    public void clear() {
        logger.debug("清空缓存");
        try {
            Set keys = redisTemplate.keys("*:" + this.id + "*");
            if (!CollectionUtils.isEmpty(keys)) {
                redisTemplate.delete(keys);
            }
        } catch (Exception e) {
        }
    }

    @Override
    public int getSize() {
        Long size = (Long) redisTemplate.execute(new RedisCallback() {
            @Override
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.dbSize();
            }
        });
        return size.intValue();
    }

    @Override
    public ReadWriteLock getReadWriteLock() {
        return this.readWriteLock;
    }
}

然后配置中指明实现二级缓存的方式,我这里是放在application.yml中配置的:
 

spring.cache.type=REDIS

接下来就可以对你需要缓存的语句进行声明了,通过Mapper接口的方式是
 

@CacheNamespace(implementation=(com.xxx.xxx.MybatisRedisCache.class))


3、再说说Redis做变量存储
配置一个RedisConfig类,实现CachingConfigurerSupport,然后写个RedisTemplate的实现方式通过@Bean初始化到工厂吧(源码案例中实现的功能要多些,可以自己去看看)

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    /**
     * 重写Redis序列化方式,使用Json方式:
     * 当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer。
     * Spring Data JPA为我们提供了下面的Serializer:
     * GenericToStringSerializer、Jackson2JsonRedisSerializer、JacksonJsonRedisSerializer、JdkSerializationRedisSerializer、OxmSerializer、StringRedisSerializer。
     * 在此我们将自己配置RedisTemplate并定义Serializer。
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        // 设置值(value)的序列化采用Jackson2JsonRedisSerializer。
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // 设置键(key)的序列化采用StringRedisSerializer。
        redisTemplate.setKeySerializer(new StringRedisSerializer());

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

} 
  

使用的时候,直接通过

redisTemplate.opsForValue().set(K var1, V var2);//写入   
redisTemplate.opsForValue().get(K var1);//读出

例如:

@RestController
@RequestMapping("/redisDemo")
public class RedisDemoController {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private RedisTemplate redisTemplate;

    private static final String REDIS_DEMO_CALL = "REDIS_DEMO_CALL";

    /**
     * 根据条件查询订单详细信息列表(分页)
     * @param data
     * @return
     */
    @PostMapping("/getRedisCall")
    public ResponseMsg getRedisCall(@RequestBody JSONObject data){
        try {
            String nowDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));//当前时间

            // 获取上次调用时间
            Object callDateObj = redisTemplate.opsForValue().get(REDIS_DEMO_CALL);
            String lastDateObj = callDateObj == null ? "未调用" : callDateObj.toString();

            // 更新时间
            redisTemplate.opsForValue().set(REDIS_DEMO_CALL, nowDate);

            return new ResponseMsg(Code.SUCCESS, lastDateObj,"查询上次调用时间成功!");
        } catch (Exception e) {
            logger.error("查询上次调用时间失败!", e);
            return new ResponseMsg<>(Code.FAIL, null, "查询上次调用时间失败==》" + e.getMessage());
        }
    }
}

调用2次的结果:

Spring Cloud | 总结 二: Mybatis多数据源+Redis二级缓存+Feign调用_第2张图片

 

 

你可能感兴趣的:(Spring,Cloud,Spring,Boot,Redis)