采用Redis作為Web系統的緩存。用Spring的Cache整合Redis。
}
}
}
一、關於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>
二、實體類
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 + "]";
}
}
三、數據訪問層
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);
四、業務處理層(關鍵)
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官方文檔:
| 名字 | 位置 | 描述 | 示例 |
| methodName |
root對象 |
當前被調用的方法名 |
|
| method |
root對象 |
當前被調用的方法 |
|
| target |
root對象 |
當前被調用的目標對象 |
|
| targetClass |
root對象 |
當前被調用的目標對象類 |
|
| args |
root對象 |
當前被調用的方法的參數列表 |
|
| caches |
root對象 |
當前方法調用使用的緩存列表(如@Cacheable(value={"cache1", "cache2"})),則有兩個cache |
|
| argument name |
執行上下文 |
當前被調用的方法的參數,如findById(Long id),我們可以通過#id拿到參數 |
#user.id |
| result |
執行上下文 |
方法執行后的返回值(僅當方法執行之后的判斷有效,如‘unless’,'cache evict'的beforeInvocation=false) |
|
條件緩存
有時,一個方法不總是適用於緩存。緩存注解通過帶有SpEL表達式的conditional參數來評估是true或者false能夠達到這種功能。如果返回時true,那么這個方法被緩存,如果不是,這個方法不會被緩存。一個例子,下面的方法將會被緩存,僅當參數name的長度小於32的時候:
@Cacheable(value="book", condition="#name.length < 32")
public Book findBook(String name)
