首先,在Spring中使用Redis需要jedis.jar和spring-data-redis.jar
Spring整合Redis有两种方式,一种为注解,另一种为xml配置文件,根据你的Spring IoC配置形式进行选择,下面来分别进行讲解:
如果你的IoC容器是以xml文件形式配置的,则在你的IoC配置文件中加入如下代码:
redisCacheManager
解释一下上述配置信息:
如果你的IoC容器是以java形式配置的,则你需要新建一个redis的配置类RedisConfig.java(自命名):
package com.ssm.config;
import java.util.ArrayList;
import java.util.Collection;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;import redis.clients.jedis.JedisPoolConfig;
//代表这个类为一个配置类
@Configuration
//开启缓存机制
@EnableCaching
@SuppressWarnings({"rawtypes","unchecked"})
public class RedisConfig {@Bean(name="redisTemplate")
public RedisTemplate initRedisTemplate() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
//最大空闲数
poolConfig.setMaxIdle(50);
//最大连接数
poolConfig.setMaxTotal(100);
//最大等待毫秒数
poolConfig.setMaxWaitMillis(20000);
//创建Jedis连接工厂
JedisConnectionFactory connectionFactory = new JedisConnectionFactory(poolConfig);
connectionFactory.setHostName("localhost");
connectionFactory.setPort(6379);
//调用后初始化方法,没有它将抛出异常
connectionFactory.afterPropertiesSet();
//自定义redis序列化器
RedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
RedisSerializer stringRedisSerializer = new StringRedisSerializer();
//定义RedisTemplate,并设置连接工程
RedisTemplate redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
//设置序列化器
redisTemplate.setDefaultSerializer(stringRedisSerializer);
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(jdkSerializationRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jdkSerializationRedisSerializer);
return redisTemplate;
}
//定义缓存管理器
@Bean(name="redisCacheManager")
public RedisCacheManager initRedisCacheManager(@Autowired RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
//设置超时时间为10分钟
cacheManager.setDefaultExpiration(600L);
//设置缓存名称
CollectioncacheNames = new ArrayList ();
cacheNames.add("redisCacheManager");
cacheManager.setCacheNames(cacheNames);
return cacheManager;
}
}
这里的 配置类和之前的xml配置形式其实是一模一样的,只不过一个是以xml,一个是以java形式,所以完全可以参照xml配置的讲解。
到这里缓存的配置就完成了,那么如何使用配置好的缓存呢?
我们先定义一个增删改查的接口RoleService.java:
package com.ssm.service;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.ssm.pojo.Role;
public interface RoleService {
public Role getRole(Long id);
public int deleteRole(Long id);
public Role insert(Role role);
public Role updateRole(Role role);
public ListfindRoles(@Param("roleName") String roleName,@Param("note") String note); }
下面是接口的实现类RoleServiceImpl.java:
package com.ssm.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;import com.ssm.dao.RoleDao;
import com.ssm.pojo.Role;
import com.ssm.service.RoleService;@Service
public class RoleServiceImpl implements RoleService {@Autowired
private RoleDao roleDao = null;
/*
* 使用@Cacheable定义缓存策略
* 当缓存中有值,则返回缓存数据,否则访问方法得到数据
* 通过value引用缓存管理器,通过key定义键
* @param id 角色编号
* @return 角色
*/
@Override
@Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
@Cacheable(value="redisCacheManager",key="'redis_role'+#id")
public Role getRole(Long id) {
return roleDao.getRole(id);
}
/*
* 使用@CachePut则表示无论如何都会执行该方法,最后将方法的返回值再保存到缓存中
* 使用在插入数据的地方,则表示保存到数据库后,会同期插入Redis缓存中
* @param role角色对象
* @return 角色对象
*/
@Override
@Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
@CachePut(value="redisCacheManager",key="'redis_role'+#result.id")
public Role insert(Role role) {
roleDao.insertRole(role);
return role;
}
/*
* 使用@CachePut,表示更新数据库的同时,也会同步更新缓存
* @param role 角色对象
* @return 角色对象
*/
@Override
@Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
@CachePut(value="redisCacheManager",key="'redis_role'+#result.id")
public Role updateRole(Role role) {
roleDao.updateRole(role);
return role;
}
/*
* 使用@CacheEvict删除缓存对应的key
* @param id 角色编号
* @return 返回删除的记录数
*/
@Override
@Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
@CacheEvict(value="redisCacheManager",key="'redis_role'+#id")
public int deleteRole(Long id) {
return roleDao.deleteRole(id);
}@Override
public ListfindRoles(String roleName, String note) {
return roleDao.findRoles(roleName, note);
}}
在实现类中我们分别对增删改查定义了不同的缓存策略,分别为:@Cacheable、@CachePut、@CacheEvict,结合代码段我们对这些缓存策略分别给出讲解:
实现类写好了,下面给出测试:
在测试之前,为了能够更好的看到效果,我们使用log4j进行监控执行过程,在src下创建文件log4j.properties并写入配置属性,其中其配置属性如下:
log4j.rootLogger=DEBUG,stdout
log4j.logger.org.springframework=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n
首先获取ioc容器,如果你的ioc是以xml文件形式配置的,采用这种方式获取(参数为你的xml文件名带路径):
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
如果你的ioc容器是以java形式配置的,采用这种(参数为所有你的ioc相关的配置类):
ApplicationContext ctx = new AnnotationConfigApplicationContext(RootConfig.class,RedisConfig.class)
下面是测试代码:
//获取IoC容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器中获取service实现类
RoleService roleService = ctx.getBean(RoleService.class);
//创建实体对象
Role role = new Role();
role.setRoleName("程序员");
role.setNote("人生苦短,我恨编程!");
//插入到数据库
roleService.insert(role);
//从数据库中获取刚刚插入的对象
Role getRole = roleService.getRole(7l);
//打印
System.out.println(getRole.getRoleName()+":"+getRole.getNote());
运行上述代码段,在插入实体对象到数据库的时候,同时会将对象同步更新到缓存中,当从数据库中再取出插入的对象时,首先会检查缓存中是否存在该对象,若存在,直接返回,不会再去数据库中拿。 所以观察log4j在控制台打印出的日志你会发现只有一条sql语句的出现,因为在取出数据的时候是直接从缓存中拿的,并没有经过数据库,也就不会有sql语句的执行。