`

使用redis和spring集成实际中遇到的问题

阅读更多
最近使用redis遇到一些问题,记录一下。
格式就不排了,有时间再弄吧。

一、版本信息
spring 4.2.5
mysql 5.1.18
mybatis 3.2.8
mybatis-spring 1.2.4
jedis 2.8.0
spring-data 1.7.1
...  ...


二、jedis和spring集成
1. 配置数据源
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="${redis.maxTotal}" />
		<property name="maxIdle" value="${redis.maxIdle}" />
		<property name="minIdle" value="${redis.minIdle}" />
		<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
		<!--对拿到的connection进行validateObject校验 -->
		<property name="testOnBorrow" value="${redis.testOnBorrow}" />
		<!--在进行returnObject对返回的connection进行validateObject校验 -->
		<property name="testOnReturn" value="${redis.testOnReturn}" />
		<!--定时对线程池中空闲的链接进行validateObject校验 -->
		<property name="testWhileIdle" value="${redis.testWhileIdle}" />
	</bean>

	<bean id="redisConnectionFactory"
		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
		<property name="hostName" value="${redis.host}"/>
		<property name="port" value="${redis.port}"/>
		<property name="password" value="${redis.password}" />
		<property name="timeout" value="${redis.timeout}" />
		<property name="database" value="${redis.default.database}" />
		<property name="poolConfig" ref="jedisPoolConfig"/>
	</bean>
	<bean id="redis4CacheConnectionFactory"
		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
		<property name="hostName" value="${redis.host}"/>
		<property name="port" value="${redis.port}"/>
		<property name="password" value="${redis.password}" />
		<property name="timeout" value="${redis.timeout}" />
		<property name="database" value="${redis.cache.database}" />
		<property name="poolConfig" ref="jedisPoolConfig"/>
	</bean>


2.配置Template
	<bean id="stringRedisSerializer"
		class="org.springframework.data.redis.serializer.StringRedisSerializer" />
	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="redisConnectionFactory" />
		<property name="keySerializer" ref="stringRedisSerializer" />
		<property name="hashKeySerializer" ref="stringRedisSerializer" />
		<!-- 默认即为 jdkRedisSerializer -->
		<!-- <property name="valueSerializer" ref="jdkRedisSerializer" />
		<property name="hashValueSerializer" ref="jdkRedisSerializer" /> -->
		<!-- <property name="enableTransactionSupport" value="true" /> -->
	</bean>

注:在spring事务中不执行Lua脚本可使用enableTransactionSupport,否则报java.lang.unsupportedclassversion

三、与springCache集成
	<bean id="redis4CacheTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="redis4CacheConnectionFactory" />
		<property name="keySerializer" ref="stringRedisSerializer" />
	</bean>

	<!-- 开启缓存注解 -->
	<cache:annotation-driven/>

	<!-- declare Redis Cache Manager -->
	<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
		<constructor-arg name="redisOperations" ref="redis4CacheTemplate" />
		<!-- 是否事务提交,如果事务回滚,缓存也回滚,默认false -->
		<property name="transactionAware" value="true" />
		<!-- 默认有效期1d 3600*24 -->
		<property name="defaultExpiration" value="86400" />
	</bean>


public abstract class BaseCache {
	public String generateKey(String... args) {
		return RedisUtil.generateKey(args);
	}
	@CacheEvict(allEntries = true)
	public abstract void clearCaches(Class<?> clazz);
}

@Component(ActivityCache.SERVICE_NAME)
@CacheConfig(cacheNames = {ActivityCache.SERVICE_NAME})
public class ActivityCache extends BaseCache {
	
	/**
	 * SERVICE_NAME:服务名
	 */
	public static final String SERVICE_NAME = "activityCache";
	
	@Autowired
	private ActivityDao activityDao;
	@Cacheable(key="#root.target.generateKey(#root.targetClass.getSimpleName(), #activityCode)",
			unless="#result == null")
	public Activity getActivityInfo(String activityCode){
		Activity activity = null;
		try {
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		}
		return activity;
	}

	@CachePut(key="#root.target.generateKey(#root.targetClass.getSimpleName(), #activity.activityCode)",
			unless="#result == null")
	public Activity saveOrUpdateActivityInfo(Activity activity)

	@CachePut(key="#root.target.generateKey(#root.targetClass.getSimpleName(), #activityCode)",
			unless="#result == null")
	public int delActivity(String activityCode)

	@CacheEvict(allEntries = true)
	public void clearCaches(Class<?> clazz)
	
}


四、关于取值异常问题
Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.io.NotSerializableException


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring/spring.xml"
//		,
//		"classpath:spring/spring-mvc.xml",
//		"file:src/main/java/com/sinowel/eacpc/**/mapping/*.xml"
		})
public class TestBase {
	
	@Before
	public void setUp() throws Exception {
	}
	
}


public class TestLua2 extends TestBase {
	private final Logger logger = LoggerFactory.getLogger(TestLua2.class);
	
	@Resource(name = RedisService.SERVICE_NAME)
	private RedisService redisService; // redis
	
	@Resource(name = "redisTemplate")
	private RedisTemplate<String, Object> redisTemplate; // redis

	@Test
	public void testInject() throws Exception {
		// 在服务器redis-cli连接预存入Hash key=tt1 field=t1,t2的数值
		String redisKey = "tt1";
		List<String> fieldList = Arrays.asList(new String[] {"t1", "t2"});
		List<Long> list = redisService.getMultiHash(redisKey, fieldList, null);
		System.out.println(list.get(0).longValue());

		// 存入时使用stringRedisSerializer,取值时使用jdkRedisSerializer。xml RedisTemplate时配置
		// 异常,先存,再次取,配置文件切换配置
		String redisKey = "tt2";
		List<String> fieldList = Arrays.asList(new String[] {"t1", "t2"});
		redisService.setHash(redisKey, "t1", "1");
		redisService.setHash(redisKey, "t2", "2");
		BoundHashOperations<String, String, Long> bhOps = redisTemplate
				.boundHashOps(redisKey);
		List<Long> list = bhOps.multiGet(fieldList);
		System.out.println(list.get(0));
		
		// keySerializer 和 hashKeySerializer 设置 stringRedisSerializer
		// valueSerializer 和 hashValueSerializer 设置成默认 jdkRedisSerializer
		// 则可以取得指定值,否则都使用stringRedisSerializer,取到的值一定是String类型
		String redisKey = "tt3";
		List<String> fieldList = Arrays.asList(new String[] {"t1", "t2"});
		BoundHashOperations<String, String, Long> bhOps = redisTemplate
				.boundHashOps(redisKey);
		bhOps.put("t1", 1L);
		bhOps.put("t2", 2L);
		List<Long> list = bhOps.multiGet(fieldList);
		System.out.println(list.get(0));
	}
}


redis-cli取到序列化后的值【1】
stringRedisSerializer:
"\xac\xed\x00\x05t\x00\x011"

jdkRedisSerializer:
"\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x01"

总结:各个RedisSerializer序列化的值存入redis后,取值时,是不能切换取值的。因为序列化方式不同。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics