下面列出了怎么用org.springframework.data.redis.core.BoundValueOperations的API类实例代码及写法,或者点击链接到github查看源代码。
private void saveSecurityContext(HttpServletRequest request, HttpServletResponse response, SecurityContext context){
String sid = getSessionId(request);
if(StringUtils.isBlank(sid)){
SaveToSessionResponseWrapper responseWrapper = WebUtils.getNativeResponse(response, SaveToSessionResponseWrapper.class);
sid = responseWrapper.getSid();
saveSessionCookies(request, response, sid);
}
/*LoginUserDetails loginUser = SecurityUtils.getCurrentLoginUser(context);
if(loginUser!=null){
loginUser.setToken(sid);
}*/
BoundValueOperations<String, SecurityContext> bondOps = getSessionBoundOps(sid);
//当前spring-data-redis版本不支持setex,分成两个操作
bondOps.set(context);
setSecurityContextExpireTime(request);
}
@Override
public <T> T getCache(String key, Supplier<CacheData<T>> cacheLoader) {
String cacheKey = getCacheKey(key);
BoundValueOperations<Object, Object> ops = boundValueOperations(cacheKey);
Object value = ops.get();
if (value==null && cacheLoader!=null) {
CacheData<T> cacheData = getCacheData(ops, cacheKey, cacheLoader);
if (cacheData==null) {
throw new BaseException("can not load cache data.").put("key", key);
}
value = cacheData.getValue();
} else {
cacheStatis.addHit(1);
}
return (T)value;
}
/***
* auth server store accessToken
* tokenEndpoint store acessToken
*/
@Override
public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
DefaultOAuth2AccessToken at = (DefaultOAuth2AccessToken) token;
String tokenId = getTokenId(at);
Assert.hasLength(tokenId, "tokenId can not be null");
String key = getStoreKey(tokenId);
JwtStoredTokenValue value = JwtStoredTokenValue.builder()
.token(at.getValue())
.build();
BoundValueOperations<String, JwtStoredTokenValue> ops = redisTemplate.boundValueOps(key);
//保存到redis并设置过期时间
ops.set(value, at.getExpiresIn(), TimeUnit.MILLISECONDS);
//把tokenvalue置换为tokenId
at.setValue(tokenId);
}
/**
* 由于Redis是单线程模型,命令操作原子性,所以利用这个特性可以很容易的实现分布式锁。
* 获得一个锁
*
* @param bizName 业务名
* @param lockTimeout 线程占用锁的时间
* @param unit 单位
* @throws InterruptedException 锁可以被中断
*/
public void lock(String bizName, int lockTimeout, TimeUnit unit) throws InterruptedException {
// redisTemplate.getConnectionFactory().getConnection().setNX()
String redisKey;
if (StringUtils.isBlank(bizName)) {
LOGGER.warn("has no bizName. is not recommended!");
redisKey = DISTRIBUTED_LOCK_REDIS_KEY;
} else {
redisKey = DISTRIBUTED_LOCK_REDIS_KEY + bizName.trim();
}
BoundValueOperations<String, Long> valueOps = redisTemplate.boundValueOps(redisKey);
while (true) {
// https://redis.io/commands/setnx
long currentTimeMillis = System.currentTimeMillis();
long releaseLockTime = currentTimeMillis + unit.toMillis(lockTimeout) + 1;
//这两个if else不能混写,因为多个相同类型的线程竞争锁时,在锁超时时,设置的超时时间是一样的
if (valueOps.setIfAbsent(releaseLockTime)) {
/**
* 第一次获取锁
*/
redisTemplate.expire(redisKey, lockTimeout, unit);
return;
} else if (currentTimeMillis > valueOps.get()) {
/**
* 锁已经超时
*/
//如果其它线程占用锁,再重新设置的时间和原来时间的时间差,可以忽略
Long lockCurrentValue = valueOps.getAndSet(releaseLockTime);
//如果当前时间小于LockKey存放的时间,说明已经有其它线程加锁
if (currentTimeMillis > lockCurrentValue) {
redisTemplate.expire(redisKey, lockTimeout, unit);
return;
}
} else {
TimeUnit.MILLISECONDS.sleep(ThreadLocalRandom.current().nextInt(100, 1000));
}
}
}
protected void addOps(final EmailSchedulingData emailSchedulingData) {
final String orderingKey = orderingKey(emailSchedulingData);
final String valueKey = emailSchedulingData.getId();
final double score = calculateScore(emailSchedulingData);
BoundZSetOperations<String, String> orderingZSetOps = orderingTemplate.boundZSetOps(orderingKey);
orderingZSetOps.add(valueKey, score);
orderingZSetOps.persist();
BoundValueOperations<String, EmailSchedulingData> valueValueOps = valueTemplate.boundValueOps(valueKey);
valueValueOps.set(emailSchedulingData);
valueValueOps.persist();
}
private void setSecurityContextExpireTime(HttpServletRequest request){
String sid = getSessionId(request);
if(StringUtils.isBlank(sid))
return ;
BoundValueOperations<String, SecurityContext> bondOps = getSessionBoundOps(sid);
int invalidTime = request.getSession().getMaxInactiveInterval();
bondOps.expire(invalidTime, TimeUnit.SECONDS);
}
protected <T> CacheData<T> getCacheData(BoundValueOperations<Object, Object> ops, String cacheKey, Supplier<CacheData<T>> cacheLoader) {
return this.getRedisLockRunnerByKey(cacheKey).tryLock(() -> {
//double check...
Object value = ops.get();
if (value!=null) {
cacheStatis.addHit(1);
return CacheData.<T>builder().value((T)value).build();
}
cacheStatis.addMiss(1);
CacheData<T> cacheData = cacheLoader.get();
if(logger.isInfoEnabled()){
logger.info("run cacheLoader for key: {}", cacheKey);
}
if (cacheData.getExpire()!=null && cacheData.getExpire()>0) {
// ops.expire(cacheData.getExpire(), cacheData.getTimeUnit());
ops.set(cacheData.getValue(), cacheData.getExpire(), cacheData.getTimeUnit());
} else if (this.expires.containsKey(cacheKey)) {
Long expireInSeconds = this.expires.get(cacheKey);
ops.set(cacheData.getValue(), expireInSeconds, TimeUnit.SECONDS);
} else {
ops.set(cacheData.getValue());
}
return cacheData;
}/*, ()->{
//如果锁定失败,则休息1秒,然后递归……
int retryLockInSeconds = 1;
if(logger.isWarnEnabled()){
logger.warn("obtain redis lock error, sleep {} seconds and retry...", retryLockInSeconds);
}
LangUtils.await(retryLockInSeconds);
return getCacheData(ops, cacheKey, cacheLoader);
}*/);
}
protected final JwtStoredTokenValue getJwtStoredTokenValue(String tokenId){
String key = getStoreKey(tokenId);
BoundValueOperations<String, JwtStoredTokenValue> ops = redisTemplate.boundValueOps(key);
JwtStoredTokenValue storedTokenValue = ops.get();
if(storedTokenValue==null){
throw new ServiceException(JwtErrors.CM_ERROR_TOKEN);
}
return storedTokenValue;
}
@Test
public void testJsonRedisTemplate(){
String key = "test:data";
BoundValueOperations<Object, Object> ops = (BoundValueOperations<Object, Object>)jsonRedisTemplate.boundValueOps(key);
JsonData data = new JsonData();
data.setAge(111);
data.setName("testName");
ops.set(data);
JsonData data2 = (JsonData)ops.get();
assertThat(data2).isEqualTo(data);
jsonRedisTemplate.delete(key);
}
/**
* @param args
*/
public static void main(String[] args) {
JedisShardInfo jedisShardInfo1 = new JedisShardInfo(ip1);
jedisShardInfo1.setPassword(JedisConstant.password);
JedisShardInfo jedisShardInfo2 = new JedisShardInfo(ip2);
jedisShardInfo2.setPassword(JedisConstant.password);
List<JedisShardInfo> jedisShardInfos = new ArrayList<JedisShardInfo>();
jedisShardInfos.add(jedisShardInfo1);
jedisShardInfos.add(jedisShardInfo2);
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxActive(JedisConstant.maxActive);
poolConfig.setMaxIdle(JedisConstant.maxIdle);
poolConfig.setMaxWait(JedisConstant.maxWait);
poolConfig.setTestOnBorrow(JedisConstant.testOnBorrow);
poolConfig.setTestOnReturn(JedisConstant.testOnReturn);
ShardedJedisPool shardedJedisPool = new ShardedJedisPool(poolConfig, jedisShardInfos);
JedisConnectionFactory factory = new JedisConnectionFactory(jedisShardInfo1);
StringRedisTemplate template = new StringRedisTemplate(factory);
for (int i = 0; i < 2000; i++) {
String key = "howsun_" + i;
BoundValueOperations<String, String> v = template.boundValueOps(key);
//jedis.set(key, UUID.randomUUID().toString());
System.out.println(key + "\t" + v.get() + "\t" + factory.getHostName());
}
}
@SuppressWarnings("unchecked")
public static <V>BoundValueOperations<String,V> boundValueOps(final String key) {
return (BoundValueOperations<String, V>) redisTemplate.boundValueOps(key);
}
@Override
public BoundValueOperations<K, V> boundValueOps(K key) {
throw new MethodNotSupportException("myRedisTemplate not support this method : boundValueOps(K key) , please use opsForXX");
//return new DefaultBoundValueOperations<K, V>(key, this);
}
protected EmailSchedulingData getOps(final String id) {
//valueTemplate.
BoundValueOperations<String, EmailSchedulingData> boundValueOps = valueTemplate.boundValueOps(id);
EmailSchedulingData emailSchedulingData = boundValueOps.get();
return emailSchedulingData;
}
private BoundValueOperations<String, SecurityContext> getSessionBoundOps(String sid){
// String sid = getSessionId(httpSession);
String skey = getSecuritySessionKey(sid);
// return this.redisTemplate.boundHashOps(skey);
return this.redisTemplate.boundValueOps(skey);
}
protected BoundValueOperations<Object, Object> boundValueOperations(String key) {
return this.redisTemplate.boundValueOps(key);
}
@Around("simplePointcut() && @annotation(ehcache)")
public Object aroundLogCalls(ProceedingJoinPoint joinPoint,Ehcache ehcache)throws Throwable {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
String cacheKey ="";
if(StringUtils.isNotBlank(ehcache.cacheName())){
cacheKey=ehcache.cacheName();
}else{
cacheKey=getCacheKey(targetName, methodName, arguments);
}
Object result=null;
BoundValueOperations<String,Object> valueOps = redisTemplate.boundValueOps(cacheKey);
if(ehcache.eternal()){
//永久缓存
result = valueOps.get();
}else{
//临时缓存
result = valueOps.get();
valueOps.expire(20, TimeUnit.MINUTES);
}
if (result == null) {
if ((arguments != null) && (arguments.length != 0)) {
result = joinPoint.proceed(arguments);
} else {
result = joinPoint.proceed();
}
if(ehcache.eternal()){
//永久缓存
valueOps.set(result);
}else{
//临时缓存
valueOps.set(result,20, TimeUnit.MINUTES);
}
}
return result;
}