采用Redis做为Web系统的缓存。用Spring的Cache整合Redis。
1、关于redis的相关xml文件的写法
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
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">
<!-- 开启缓存注解 -->
<cache:annotation-driven />
<!-- jedis客户端链接工厂 -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="192.168.1.200" p:port="6379"/>
<!-- redisTemplate模板 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnectionFactory"/>
<!-- redis缓存管理器 -->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" c:template-ref="redisTemplate"/>
</beans>
2、实体类
public class Student implements Serializable{
/**
*
*/
private static final long serialVersionUID = -4676194082313592019L;
private Integer id;
private String name;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
3、数据访问层
public interface StudentMapper {
@Insert ("insert into student(id,name,age) values(#{id},#{name},#{age})")
public void insert(Student student);
@Delete ("delete from student where id = #{id}")
public void delete(@Param ("id")Integer id);
@Update ("update student set name=#{name},age=#{age} where id=#{id}")
public void update(Student student);
@Select("select * from student where id=#{id}")
public Student queryById(@Param("id")Integer id);
}
4、业务处理层(关键)
public interface IStudentService {
public void add(Student student);
public void delete(Integer id);
public void update(Student student);
public Student queryById(Integer id);
}
public class StudentServiceImpl extends BaseService implements IStudentService{
private StudentMapper mapper;
@CachePut
(key="#student.id",value="student")
@Override
public void add(Student student) {
mapper = writableSQLSession.getMapper(StudentMapper.class);
mapper.insert(student);
}
@Override
public void delete(Integer id) {
mapper = writableSQLSession.getMapper(StudentMapper.class);
mapper.delete(id);
}
@Override
public void update(Student student) {
mapper = writableSQLSession.getMapper(StudentMapper.class);
mapper.update(student);
}
@Cacheable(key="#id",value="student")
@Override
public Student queryById(Integer id) {
mapper = readonlySQLSession.getMapper(StudentMapper.class);
return mapper.queryById(id);
}
}
最重要的三个注解是@Cacheable()和@CacheEvict()和@CachePut()
对于缓存声明,缓存抽象类提供两个Java注解:@Cacheable和@CacheEvict,这两个注解能够容许方法触发缓存或者缓存抽取。
@Cacheable缓存
应用到读取数据的方法上,便可缓存的方法,如查找方法。
就像注解名字的含义同样,@Cacheable用于区别可缓存的方法,指的是方法运行的结果被装入缓存的方法,所以,在随后的方法调用中,在缓存的值被返回,在实际上没有执行这个方法。最简单的构成,注解声明须要和被缓存的方法有关系的缓存名字:
@Cacheable("books")
public Book findBook(ISBN isbn) {...}
在上面的片断,findBook方法是和名字为books的缓存有关系的。方法每次被调用,这个缓存被检查去查看是否这个调用已经执行而且没有被重复。在大多数的状况下,只有一个缓存被声明,注解容许多个被指定的名字以致于不知一个缓存被正在使用。在这种状况下,每一个缓存将会在执行方法以前被检查,若是至少一个缓存被选中,那么相关的值将被返回:
(注意:全部其余的没有包含这个方法的缓存将会被更新,即便这个被缓存的方法实际上没有被执行)
@Cacheable({ "books", "isbns" })
public Book findBook(ISBN isbn) {...}
默认键的生成
因为缓存其实是键值对存贮的,一个被缓存的方法每一次的调用须要被转换成一个合适的键为了缓存访问。在这个盒子以外,缓存抽象类用一个简单的KeyGenerator(键生成器)基于如下的算法:
1.若是没有给参数,返回SimpleKey.EMPTY。
2.若是仅仅给了一个参数,返回那个实例。
3.若是不仅一个参数被指定,返回一个SimpleKey包含全部参数。
只要参数具备natural keys而且实现有效的hashCode()和equals()方法,这种处理方式对于大多数用例运行完美;若是这不符合这种场景,键的生成策略须要改变。
提供一个不一样的默认键生成器,须要实现
org.springframework.cache.KeyGenerator接口。一旦配置,这个生成器将会用于每一个没有特殊指定它本身的键生成策略的声明中。
用户自定义键生成器声明
由于缓存是一个通用类,它很是像有多种不能简单映射在缓存结构的顶部的签名的目标方法。当目标方法有多个
超出了适用于缓存的
参数时,这将变得明显。例如:
@Cacheable("books")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
第一眼看去,两个布尔型的参数影响找书的方式,他们对于缓存是没用的。
对于这种场景,@Cacheable注解容许用户经过key属性指定键的生成策略。开发和能够用SpEL去获取参数(或者他们包含的属性),执行的方式甚至不用写任何代码或者实现任何借口调用不一样的方法。这是在默认生成器以外推荐的方法。
应用到写数据的方法上,如新增/修改方法
即应用到移除数据的方法上,如删除方法
提供的SpEL上下文数据
Spring Cache提供了一些供咱们使用的SpEL上下文数据,下表直接摘自Spring官方文档: redis
名字 |
位置 |
描述 |
示例 |
methodName 算法 |
root对象 spring |
当前被调用的方法名 缓存 |
#root.methodName app |
method less |
root对象 ide |
当前被调用的方法 this |
#root.method.name spa |
target .net |
root对象 |
当前被调用的目标对象 |
#root.target |
targetClass |
root对象 |
当前被调用的目标对象类 |
#root.targetClass |
args |
root对象 |
当前被调用的方法的参数列表 |
#root.args[0] |
caches |
root对象 |
当前方法调用使用的缓存列表(如@Cacheable(value={"cache1", "cache2"})),则有两个cache |
#root.caches[0].name |
argument name |
执行上下文 |
当前被调用的方法的参数,如findById(Long id),咱们能够经过#id拿到参数 |
#user.id |
result |
执行上下文 |
方法执行后的返回值(仅当方法执行以后的判断有效,如'unless’,'cache evict'的beforeInvocation=false) |
#result
|
条件缓存
有时,一个方法不老是适用于缓存。缓存注解经过带有SpEL表达式的conditional参数来评估是true或者false可以达到这种功能。若是返回时true,那么这个方法被缓存,若是不是,这个方法不会被缓存。一个例子,下面的方法将会被缓存,仅当参数name的长度小于32的时候:
@Cacheable(value="book", condition="#name.length < 32")
public Book findBook(String name)