採用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)