<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- 用于java bean存redis序列化 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="redisConnectionFactory"/>
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
</property>
</bean>
<!-- 用于基础对象存储 -->
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="redisConnectionFactory"/>
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
</bean>
<!-- turn on declarative caching -->
<cache:annotation-driven/>
<!-- declare Redis Cache Manager -->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
<constructor-arg ref="redisTemplate"></constructor-arg>
</bean>
</beans>
2.redis.propties
system.cache.enable=true
redis.type=cluster
redis.cluster.url=10.200.2.105:7000,10.200.2.105:7001,10.200.2.105:7002,10.200.2.105:7003,10.200.2.105:7004,10.200.2.105:7005
redis.single.url=192.168.0.63:12200
3.pom.xml
<!-- redis -->
<dependency>
<groupId>biz.paluch.redis</groupId>
<artifactId>lettuce</artifactId>
<version>4.3.2.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.8.3.RELEASE</version>
</dependency>
4.redis config ,java类
package com.lvtu.csa.framework.conf;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import com.google.common.collect.Sets;
@Configuration
public class RedisConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(RedisConfig.class);
@Value("${redis.type}")
private String type;
@Value("${redis.cluster.url}")
private String REDIS_CLUSTER_URL;
@Value("${redis.single.url}")
private String REDIS_SINGLE_URL;
@Bean(name = "redisNodes")
public Iterable<RedisNode> getRedisNodes() {
if(StringUtils.isBlank(REDIS_CLUSTER_URL)) {
LOGGER.warn("REDIS配置文件为空");
return null;
}
String[] urls = StringUtils.split(REDIS_CLUSTER_URL, ',');
Set<RedisNode> nodes = Sets.newHashSetWithExpectedSize(urls.length);
for (String url : urls) {
String[] splits = url.split(":");
nodes.add(new RedisNode(splits[0], Integer.parseInt(splits[1])));
}
return nodes;
}
@Bean(name = "redisClusterConfiguration")
public RedisClusterConfiguration getClusterConfiguration(Iterable<RedisNode> redisNodes) {
if(redisNodes == null) {
return null;
}
RedisClusterConfiguration configuration = new RedisClusterConfiguration();
configuration.setClusterNodes(redisNodes);
configuration.setMaxRedirects(5);
return configuration;
}
@Bean(name = "redisConnectionFactory")
public RedisConnectionFactory getRedisConnectionFactory(RedisClusterConfiguration redisClusterConfiguration) {
if("single".equals(type)) {
if(StringUtils.isEmpty(REDIS_SINGLE_URL) || !REDIS_SINGLE_URL.contains(":")) {
throw new RuntimeException("请检查redis配置,单点配置不正确");
}
String[] split = REDIS_SINGLE_URL.split(":");
return new LettuceConnectionFactory(split[0], Integer.parseInt(split[1]));
}
if("cluster".equals(type)) {
if(redisClusterConfiguration == null) {
throw new RuntimeException("请检查redis配置,集群配置不正确");
}
return new LettuceConnectionFactory(redisClusterConfiguration);
}
return null;
}
}
redis 工具类方法
package com.lvtu.csa.framework.cache;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.util.concurrent.TimeUnit;
/**
* Created by Administrator on 2016/9/22.
*/
@Component
public class RedisCache {
@Autowired
RedisTemplate<String, Object> redisTemplate;
public Object get(CacheKey cacheKey) {
Assert.hasText(cacheKey.getKey(), "缓存KEY不能为空");
if(StringUtils.isEmpty(cacheKey.getName())) {
return redisTemplate.opsForValue().get(cacheKey.getKey());
} else {
return redisTemplate.opsForHash().get(cacheKey.getName(), cacheKey.getKey());
}
}
public void put(CacheKey cacheKey, Object result) {
Assert.hasText(cacheKey.getKey(), "缓存KEY不能为空");
if(StringUtils.isEmpty(cacheKey.getName())) {
redisTemplate.opsForValue().set(cacheKey.getKey(), result);
} else {
redisTemplate.opsForHash().put(cacheKey.getName(), cacheKey.getKey(), result);
}
}
public void put(CacheKey cacheKey, Object result, int second) {
Assert.hasText(cacheKey.getKey(), "缓存KEY不能为空");
if(StringUtils.isEmpty(cacheKey.getName())) {
redisTemplate.opsForValue().set(cacheKey.getKey(), result, second, TimeUnit.SECONDS);
} else {
redisTemplate.opsForHash().put(cacheKey.getName(), cacheKey.getKey(), result);
redisTemplate.expire(cacheKey.getName(), second, TimeUnit.SECONDS);
}
}
public void evict(CacheKey cacheKey) {
Assert.hasText(cacheKey.getKey(), "缓存KEY不能为空");
if(StringUtils.isEmpty(cacheKey.getName())) {
redisTemplate.delete(cacheKey.getKey());
} else {
redisTemplate.opsForHash().delete(cacheKey.getName(), cacheKey.getKey());
}
}
}
redis注解自动生成:
package com.lvtu.csa.framework.cache;
import com.google.common.collect.Lists;
import com.lvtu.csa.framework.annotation.CacheEvict;
import com.lvtu.csa.framework.annotation.Cacheable;
import com.lvtu.csa.framework.aspect.CacheAspect;
import org.springframework.expression.EvaluationContext;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.lang.reflect.Method;
import java.util.List;
/**
* Created by Administrator on 2016/9/22.
*/
public abstract class CacheAspectSupport {
private final ExpressionEvaluator evaluator = new ExpressionEvaluator();
private SimpleKeyGenerator keyGenerator = new SimpleKeyGenerator();
protected CacheOperationContext getOperationContext(Method method, Object[] args, Object target, Class<?> targetClass) {
return new CacheOperationContext(method, args, target, targetClass);
}
protected class CacheOperationContext {
private final Method method;
private final Object[] args;
private final Object target;
private final Class<?> targetClass;
private final MethodCacheKey methodCacheKey;
public CacheOperationContext(Method method, Object[] args, Object target, Class<?> targetClass) {
this.method = method;
this.args = extractArgs(method, args);
this.target = target;
this.targetClass = targetClass;
this.methodCacheKey = new MethodCacheKey(method, targetClass);
}
public Object getTarget() {
return this.target;
}
public Method getMethod() {
return method;
}
public Object[] getArgs() {
return this.args;
}
public Class<?> getTargetClass() {
return targetClass;
}
private Object[] extractArgs(Method method, Object[] args) {
if (!method.isVarArgs()) {
return args;
}
Object[] varArgs = ObjectUtils.toObjectArray(args[args.length - 1]);
Object[] combinedArgs = new Object[args.length - 1 + varArgs.length];
System.arraycopy(args, 0, combinedArgs, 0, args.length - 1);
System.arraycopy(varArgs, 0, combinedArgs, args.length - 1, varArgs.length);
return combinedArgs;
}
/**
* Compute the key for the given caching operation.
*
* @return the generated key, or {@code null} if none can be generated
*/
public CacheKey generateKey(Cacheable cacheable, CacheOperationContext result) {
if (StringUtils.hasText(cacheable.key())) {
EvaluationContext evaluationContext = createEvaluationContext(result);
String key = evaluator.key(cacheable.key(), this.methodCacheKey, evaluationContext).toString();
if(StringUtils.hasText(cacheable.name())) {
String name = evaluator.key(cacheable.name(), this.methodCacheKey, evaluationContext).toString();
return CacheKey.create(CacheAspect.LVTU_CACHE_PREFIX + name, key);
} else {
return CacheKey.create(CacheAspect.LVTU_CACHE_PREFIX + key);
}
}
return CacheKey.create(keyGenerator.generate(this, cacheable));
}
public List<CacheKey> generateKey(CacheEvict cacheEvict, CacheOperationContext result) {
List<CacheKey> cacheKeys = Lists.newArrayList();
EvaluationContext evaluationContext = createEvaluationContext(result);
for (String key : cacheEvict.key()) {
cacheKeys.add(CacheKey.create(evaluator.key(key, this.methodCacheKey, evaluationContext).toString()));
}
return cacheKeys;
}
private EvaluationContext createEvaluationContext(Object result) {
return evaluator.createEvaluationContext(this.method, this.args, this.target, this.targetClass, result);
}
}
}
package com.lvtu.csa.framework.aspect;
import com.google.common.base.Optional;
import com.lvtu.csa.framework.annotation.CacheEvict;
import com.lvtu.csa.framework.annotation.Cacheable;
import com.lvtu.csa.framework.cache.CacheAspectSupport;
import com.lvtu.csa.framework.cache.CacheKey;
import com.lvtu.csa.framework.cache.RedisCache;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.List;
@Component
@Aspect
public class CacheAspect extends CacheAspectSupport {
private final static Logger LOGGER = LoggerFactory.getLogger(CacheAspect.class);
public final static String LVTU_CACHE_PREFIX = "LVTU_CACHE:";
@Value("${system.cache.enable}")
private Boolean cacheEnable;
@Autowired
RedisCache redisCache;
@SuppressWarnings("unchecked")
@Around("@annotation(cacheable)")
public Object doAround(ProceedingJoinPoint pjp, Cacheable cacheable) throws Throwable {
if (!cacheEnable) {
return pjp.proceed();
}
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
Method targetMethod = AopUtils.getMostSpecificMethod(methodSignature.getMethod(), pjp.getTarget().getClass());
CacheOperationContext context = getOperationContext(targetMethod, pjp.getArgs(), pjp.getTarget(), pjp.getTarget().getClass());
CacheKey key = context.generateKey(cacheable, context);
Object value = redisCache.get(key); //从缓存获取数据
if (LOGGER.isDebugEnabled()) {
LOGGER.warn("[CacheAspect]缓存Key=" + key + ", Value=" + (value == null ? "MISS" : "HIT"));
}
if (value != null) {
if (methodSignature.getReturnType() == Optional.class) {
return Optional.of(value);
}
if (methodSignature.getReturnType() == java.util.Optional.class) {
return java.util.Optional.of(value);
}
if (matchClass(methodSignature.getReturnType(), value.getClass())) {
return value; //如果有数据,则直接返回
} else {
LOGGER.warn("[CacheAspect]缓存中数据类型不匹配, need=" + methodSignature.getReturnType()
+ ", actual=" + value.getClass() + ", key=" + key);
redisCache.evict(key);
}
}
value = pjp.proceed(); //跳过缓存,到后端查询数据
if (value != null) { //取值存在,才存入缓存
if (value instanceof java.util.Optional) {
java.util.Optional optional = (java.util.Optional) value;
if (optional.isPresent()) {
setCache(cacheable, key, optional.get());
}
} else if (value instanceof Optional) {
Optional optional = (Optional) value;
if (optional.isPresent()) {
setCache(cacheable, key, optional.get());
}
} else {
setCache(cacheable, key, value);
}
}
return value;
}
@AfterReturning("@annotation(cacheEvict)")
public void doEvict(JoinPoint jp, CacheEvict cacheEvict) throws Throwable {
if (!cacheEnable || ArrayUtils.isEmpty(cacheEvict.key())) {
return;
}
MethodSignature methodSignature = (MethodSignature) jp.getSignature();
Method targetMethod = AopUtils.getMostSpecificMethod(methodSignature.getMethod(), jp.getTarget().getClass());
CacheOperationContext context = getOperationContext(targetMethod, jp.getArgs(), jp.getTarget(), jp.getTarget().getClass());
List<CacheKey> keys = context.generateKey(cacheEvict, context);
for (CacheKey key : keys) {
redisCache.evict(key);
}
}
private void setCache(Cacheable cacheable, CacheKey key, Object value) {
if (cacheable.expire() <= 0) { //如果没有设置过期时间,则无限期缓存
redisCache.put(key, value);
} else { //否则设置缓存时间
redisCache.put(key, value, cacheable.expire());
}
}
@SuppressWarnings("unchecked")
private boolean matchClass(Class need, Class actual) {
return need.isAssignableFrom(actual)
|| ((need == boolean.class || need == Boolean.class) && (actual == boolean.class || actual == Boolean.class))
|| ((need == byte.class || need == Byte.class) && (actual == byte.class || actual == Byte.class))
|| ((need == short.class || need == Short.class) && (actual == short.class || actual == Short.class))
|| ((need == int.class || need == Integer.class) && (actual == int.class || actual == Integer.class))
|| ((need == long.class || need == Long.class) && (actual == long.class || actual == Long.class))
|| ((need == char.class || need == Character.class) && (actual == char.class || actual == Character.class))
|| ((need == float.class || need == Float.class) && (actual == float.class || actual == Float.class))
|| ((need == double.class || need == Double.class) && (actual == double.class || actual == Double.class));
}
}
redis配置:
package com.lvmama.cobra.cache; import com.google.common.collect.Sets; import org.apache.commons.lang3.StringUtils; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.ClusterServersConfig; import org.redisson.config.Config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisClusterConfiguration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisNode; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import java.util.Set; @Configuration public class RedisConfig { private static final Logger LOGGER = LoggerFactory.getLogger(RedisConfig.class); @Value("${redis.blacklist.type}") private String blacklistType; @Value("${redis.blacklist.cluster.url}") private String REDIS_BLACKLIST_CLUSTER_URL; @Value("${redis.blacklist.single.url}") private String REDIS_BLACKLIST_SINGLE_URL; @Value("${redis.token.type}") private String tokenType; @Value("${redis.token.cluster.url}") private String REDIS_TOKEN_CLUSTER_URL; @Value("${redis.token.single.url}") private String REDIS_TOKEN_SINGLE_URL; @Bean(name = "redisBlacklistNodes") public Iterable<RedisNode> getRedisBlacklistNodes() { return getRedisNodes(REDIS_BLACKLIST_CLUSTER_URL); } @Bean(name = "redisTokenNodes") public Iterable<RedisNode> getRedisTokenNodes() { return getRedisNodes(REDIS_TOKEN_CLUSTER_URL); } private Iterable<RedisNode> getRedisNodes(String clutterUrl) { if(StringUtils.isBlank(clutterUrl)) { LOGGER.warn("REDIS配置文件为空"); return null; } String[] urls = StringUtils.split(clutterUrl, ','); Set<RedisNode> nodes = Sets.newHashSetWithExpectedSize(urls.length); for (String url : urls) { String[] splits = url.split(":"); nodes.add(new RedisNode(splits[0], Integer.parseInt(splits[1]))); } return nodes; } @Bean(name = "redisBlacklistClusterConfiguration") public RedisClusterConfiguration getBlacklistClusterConfiguration(@Qualifier("redisBlacklistNodes") Iterable<RedisNode> redisNodes) { return getRedisClusterConfiguration(redisNodes); } @Bean(name = "redisTokenClusterConfiguration") public RedisClusterConfiguration getTokenClusterConfiguration(@Qualifier("redisTokenNodes") Iterable<RedisNode> redisNodes) { return getRedisClusterConfiguration(redisNodes); } private RedisClusterConfiguration getRedisClusterConfiguration(Iterable<RedisNode> redisNodes) { if(redisNodes == null) { return null; } RedisClusterConfiguration configuration = new RedisClusterConfiguration(); configuration.setClusterNodes(redisNodes); configuration.setMaxRedirects(5); return configuration; } @Bean(name = "redisBlacklistConnectionFactory") public RedisConnectionFactory getRedisBlacklistConnectionFactory( @Qualifier("redisBlacklistClusterConfiguration") RedisClusterConfiguration redisClusterConfiguration) { return getRedisConnectionFactory(blacklistType, REDIS_BLACKLIST_SINGLE_URL, redisClusterConfiguration); } @Bean(name = "redisTokenConnectionFactory") public RedisConnectionFactory getRedisTokenConnectionFactory( @Qualifier("redisTokenClusterConfiguration") RedisClusterConfiguration redisClusterConfiguration) { return getRedisConnectionFactory(tokenType, REDIS_TOKEN_SINGLE_URL, redisClusterConfiguration); } private RedisConnectionFactory getRedisConnectionFactory(String type, String singleURL, RedisClusterConfiguration redisClusterConfiguration) { if("single".equals(type)) { if(StringUtils.isEmpty(singleURL) || !singleURL.contains(":")) { throw new RuntimeException("请检查redis配置,单点配置不正确"); } String[] split = singleURL.split(":"); return new LettuceConnectionFactory(split[0], Integer.parseInt(split[1])); } if("cluster".equals(type)) { if(redisClusterConfiguration == null) { throw new RuntimeException("请检查redis配置,集群配置不正确"); } return new LettuceConnectionFactory(redisClusterConfiguration); } return null; } @Bean(name = "redissionConfig") public Config getRedissionConfig() { if("single".equals(tokenType)) { if(StringUtils.isEmpty(REDIS_TOKEN_SINGLE_URL) || !REDIS_TOKEN_SINGLE_URL.contains(":")) { throw new RuntimeException("请检查redis配置,单点配置不正确"); } Config config = new Config(); config.useSingleServer().setAddress(REDIS_TOKEN_SINGLE_URL); return config; } if("cluster".equals(tokenType)) { if(StringUtils.isBlank(REDIS_TOKEN_CLUSTER_URL)) { throw new RuntimeException("请检查redis配置,集群配置不正确"); } Config config = new Config(); ClusterServersConfig clusterConfig = config.useClusterServers() .setScanInterval(2000); // 集群状态扫描间隔时间,单位是毫秒 String[] urls = StringUtils.split(REDIS_TOKEN_CLUSTER_URL, ','); clusterConfig.addNodeAddress(urls); return config; } return null; } @Bean(name = "redissonClient") public RedissonClient getRedissonClient(Config config) { if(config == null) { throw new RuntimeException("请检查redis配置,Redisson配置不正确"); } return Redisson.create(config); } }
rediscache:
package com.lvmama.cobra.cache; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.Assert; import java.util.Set; import java.util.concurrent.TimeUnit; @Component public class RedisCache { @Autowired @Qualifier("redisBlacklistTemplate") RedisTemplate<String, Object> redisTemplate; public Object get(CacheKey cacheKey) { Assert.hasText(cacheKey.getKey(), "缓存KEY不能为空"); if(StringUtils.isEmpty(cacheKey.getName())) { return redisTemplate.opsForValue().get(cacheKey.getKey()); } else { return redisTemplate.opsForHash().get(cacheKey.getName(), cacheKey.getKey()); } } public void put(CacheKey cacheKey, Object result) { Assert.hasText(cacheKey.getKey(), "缓存KEY不能为空"); if(StringUtils.isEmpty(cacheKey.getName())) { redisTemplate.opsForValue().set(cacheKey.getKey(), result); } else { redisTemplate.opsForHash().put(cacheKey.getName(), cacheKey.getKey(), result); } } public void put(CacheKey cacheKey, Object result, int second) { Assert.hasText(cacheKey.getKey(), "缓存KEY不能为空"); if(StringUtils.isEmpty(cacheKey.getName())) { redisTemplate.opsForValue().set(cacheKey.getKey(), result, second, TimeUnit.SECONDS); } else { redisTemplate.opsForHash().put(cacheKey.getName(), cacheKey.getKey(), result); redisTemplate.expire(cacheKey.getName(), second, TimeUnit.SECONDS); } } public void evict(CacheKey cacheKey) { Assert.hasText(cacheKey.getKey(), "缓存KEY不能为空"); if(StringUtils.isEmpty(cacheKey.getName())) { redisTemplate.delete(cacheKey.getKey()); } else { redisTemplate.opsForHash().delete(cacheKey.getName(), cacheKey.getKey()); } } public void putSet(CacheKey cacheKey, Object value) { if(StringUtils.isEmpty(cacheKey.getName())) { redisTemplate.opsForSet().add(cacheKey.getName(), value); } else { redisTemplate.opsForHash().put(cacheKey.getName(), cacheKey.getKey(), value); } } /** * SET ADD * @see http://redis.io/commands/sadd * @param cacheKey * @param value */ public void sadd(CacheKey cacheKey, Object value) { redisTemplate.opsForSet().add(cacheKey.getKey(), value); } public void srem(CacheKey cacheKey, Object value) { redisTemplate.opsForSet().remove(cacheKey.getKey(), value); } public boolean sismember(CacheKey cacheKey, Object value) { return redisTemplate.opsForSet().isMember(cacheKey.getKey(), value); } public Set<Object> sget(CacheKey cacheKey) { Assert.hasText(cacheKey.getKey(), "缓存KEY不能为空"); return redisTemplate.opsForSet().members(cacheKey.getKey()); } public void removeAll(CacheKey cacheKey) { redisTemplate.delete(cacheKey.getKey()); } }spring-redis
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="luaResource" class="org.springframework.scripting.support.ResourceScriptSource"> <constructor-arg><value>classpath:rate_limiter.lua</value></constructor-arg> </bean> <bean id="luaScript" class="org.springframework.data.redis.core.script.DefaultRedisScript"> <property name="scriptSource" ref="luaResource" /> <property name="resultType" value="java.lang.Boolean"/> </bean> <!-- 用于存取黑名单,业务用Redis --> <bean id="redisBlacklistTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="redisBlacklistConnectionFactory"/> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="hashValueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> </bean> <!-- 用于存取令牌,非业务用Redis --> <bean id="redisTokenTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="redisTokenConnectionFactory"/> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="hashValueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> </bean> <!-- 用于执行lua脚本 --> <bean id="redisLuaTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="redisTokenConnectionFactory"/> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="hashValueSerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> </bean> </beans>