????????Redis的key可以设置有效期,过期之后在Redis中就无法查到这个key了,当key失效之后,就会出发Redis的监听回调函数onMessage,在回调函数里面将订单的状态改为无法支付就可以了。
直接看代码吧,懒得废话了:
配置文件:
开启Redis回调监听需要设置redis.conf配置文件中的notify-keyspace-events Ex给放开(更改redis.conf配置文件之后一定要重启Redis)
MySQL和Redis的连接都是最基本的,可以看往期文章。这里就省略了,直接上Java代码了:
实体类,这里的实体类是和MySQL数据库中的表对应的:
import lombok.Data;
@Data
public class Order {
private Integer id;
private String orderId;
private String tokenId;
}
?dao,将一条数据插入到MySQL数据库:
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface OrderDao {
@Insert("insert into redis_order values ( #{id}, #{orderId}, #{tokenId})")
int insertData(@Param("id") Integer id, @Param("orderId") String orderId, @Param("tokenId") String tokenId);
}
Redis工具类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtils {
/**
* 获取redis模板
*/
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 存入String类型
* @param key
* @param value
* @param timeOut
*/
public void setString(String key, String value, Long timeOut){
stringRedisTemplate.opsForValue().set(key, value);
if (timeOut != null){
//设置Redis的key的有效期
stringRedisTemplate.expire(key, timeOut, TimeUnit.SECONDS);
}
}
/**
* 获取String类型
* @param key
* @return
*/
public String getString(String key){
return stringRedisTemplate.opsForValue().get(key);
}
}
?控制层,这里设置了5秒钟的过期时间,然后随机生成了一个tokenId和一个orderId,先将数据存到Redis缓存中,tokenId当key,orderId当value,再将数据存入到MySQL
import javax.annotation.Resource;
import java.util.UUID;
@RestController
public class OrderController {
@Resource
private OrderDao orderDao;
@Resource
private RedisUtils redisUtils;
@GetMapping("/insertOrderData")
public String insertOrderData(){
//随机生成一个tokenId
String tokenId = UUID.randomUUID().toString();
//随机生成一个订单id
String orderId = UUID.randomUUID().toString();
//将数据缓存到redis
redisUtils.setString(tokenId, orderId, 5l);
return orderDao.insertData(1, orderId, tokenId) > 0 ? "success" : "fail";
}
}
监听回调函数:
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
@Component
public class RedisOrderListener extends KeyExpirationEventMessageListener {
public RedisOrderListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
/**
* key的监听回调时间
* @param message
* @param pattern
*/
@Override
public void onMessage(Message message, byte[] pattern) {
String key = message.toString();
System.out.println(key + " 失效了");
//key失效了之后,利用这个key去MySQL数据库中将订单改为无法支付即可
//这里的逻辑省略 主要模拟一下key失效的效果
}
}
这里使用到的RedisMessageListenerContainer需要手动注入一下:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory){
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}
访问一下地址:
http://localhost:8080/insertOrderData
看看效果:
看看Redis前后的变化,当我们点击url执行时,redis会出现缓存,将存入数据库的key,也就是tokenId拿出来去Redis中去查询,查询出来的数据就是orderId。
?当数据失效之后:
这个key就是上面的tokenId,再利用这个key去查询一下Redis:
已经为空了,key失效了,Redis就查询不到了。?
?
|