說到redis緩存,我想先說下spring的默認緩存。spring對緩存的支持,是有着一套接入第三方緩存的規範的。第三方的緩存,如redis、Memcached等,如果需要在spring中使用,就要實現CacheManage。 使用spring緩存,一般需要用到三個註解:@Cacheable,@CachePut,@CacheEvict。
@Cacheable,可用於類上或者方法上。表示方法的返回值可以被緩存。當標記在一個類上時則表示該類所有的方法都是支持緩存的。對於一個支持緩存的方法,Spring會在其被調用後將其返回值緩存起來,以保證下次利用同樣的參數來執行該方法時可以直接從緩存中獲取結果,而不需要再次執行該方法。spring的緩存值是以鍵值對形式存在的,默認使用方法參數作爲key值,可以自定義key值生成策略,或自定義key值。@Cacheable可以指定兩個屬性,value、key。 value屬性是必須指定的,其表示當前方法的返回值是會被緩存在哪個Cache上的,對應Cache的名稱。 key屬性是用來指定Spring緩存方法的返回結果時對應的key的。該屬性支持SpringEL表達式。當我們沒有指定該屬性時,Spring將使用默認策略生成key。
@Cacheable(value = "coms", key = "#id")
public Component get(String id) {
return crudService.get(id, Component.class);
}
上例中,就是指定了get方法的緩存名稱爲coms,key值爲傳入的id值,緩存值爲Component。
@CachePut,可以用於類上或者方法上。表示方法的返回值可以被更新和緩存。@CachePut標註的方法在執行前不會去檢查緩存中是否存在之前執行過的結果,而是每次都會執行該方法,並將執行結果以鍵值對的形式存入指定的緩存中。@Cacheable和@CachePut經常聯合使用,但是前提是指定相同的緩存名稱和緩存key值。如下:
@Cacheable(value = "coms", key = "#id")
public Component get(String id) {
return crudService.get(id, Component.class);
}
@CachePut(value = "coms", key = "#id")
public Component update(String id) {
Component component = crudService.get(id, Component.class);
component.setCreateTime(new Date());
crudService.update(component);
return component;
}
調用update方法時,也會同步更新get方法對應的緩存。
@CacheEvict,是用來標註在需要清除緩存元素的方法或類上的。當標記在一個類上時表示其中所有的方法的執行都會觸發緩存的清除操作。@CacheEvict可以指定的重要屬性包括allEntries,allEntries=true則表示整個緩存名所代表的的緩存都被清空。
@CacheEvict(value = "coms", allEntries = true)
public void delete(String id) {
crudService.delete(id, Component.class);
}
SpringBoot中使用緩存:
1. 新建springboot項目,加入maven依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
2. 新建啓動類,加入@EnableCaching
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
3. 至此 ,項目已經可以啓動,使用默認端口8080。一個非常簡單的springboot項目搭好了。接來下編寫緩存測試類。由於spring-context包已經提供了默認的緩存類,所以不需要額外都緩存依賴。
@RequestMapping
@RestController
public class TestCacheController {
@GetMapping("/get")
@Cacheable(value = "user", key = "#id")
public User get(String id) {
System.out.println("調用方法本身--get");
User user = new User();
user.setId(id);
user.setName("第一");
return user;
}
@GetMapping("/update")
@CachePut(value = "user", key = "#id")
public User update(String id,String name) {
System.out.println("調用方法本身--update");
User user = new User();
user.setId(id);
user.setName(name);
return user;
}
@GetMapping("/delete")
@CacheEvict(value = "user", key = "#id")
public void delete(String id) {
System.out.println("調用方法本身--delete");
}
}
public class User implements Serializable{
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4.使用瀏覽器,輸入請求訪問多次測試結果,對比控制檯的輸出,驗證每個註解是否正常發揮作用。我這邊完全已經正常了,就不貼出截圖了。
Redis
一直都覺得redis是多麼高大上的東西,畢竟從來沒用過。
Redis是一個高性能的key-value型數據庫,同時還提供list,set,zset,hash等數據結構的存儲,支持數據的持久化。Redis的所有操作都是原子性的。具體的安裝、命令教程都可以從官網查看:http://www.redis.net.cn/tutorial/3501.html。
總結來說,就是一個redis分服務端和客戶端兩部分,服務端負責存儲數據,客戶端連接服務端之後,以命令的形式控制服務端。redis通常被用作系統和數據庫之間的臨時內存,系統從redis中獲取數據比從數據庫中直接獲取數據會快很多。
redis集成到spring中,需要實現CacheManager。並導入相關的依賴和配置。
SpringBoot中使用Redis
1. 使用上文搭建好的springboot作爲基礎,集成redis。
2.加入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
3. 加入application.properties的相關配置
# Redis數據庫索引(默認爲0)
spring.redis.database=0
# Redis服務器地址
spring.redis.host=192.168.65.45
# Redis服務器連接端口
spring.redis.port=6379
# Redis服務器連接密碼(默認爲空)
spring.redis.password=test
# 連接池最大連接數(使用負值表示沒有限制)
spring.redis.jedis.pool.max-active=8
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.jedis.pool.max-wait=-1
# 連接池中的最大空閒連接
spring.redis.jedis.pool.max-idle=8
# 連接池中的最小空閒連接
spring.redis.jedis.pool.min-idle=2
# 連接超時時間(毫秒)
spring.redis.timeout=3000
4. 加入配置類
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean("userTemplate")
public RedisTemplate<String, User> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, User> userRedisTemplate = new RedisTemplate<String, User>();
Jackson2JsonRedisSerializer<User> userJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<User>(User.class);
userRedisTemplate.setValueSerializer(userJackson2JsonRedisSerializer);
userRedisTemplate.setHashValueSerializer(userJackson2JsonRedisSerializer);
userRedisTemplate.setKeySerializer(new StringRedisSerializer());
userRedisTemplate.setHashKeySerializer(new StringRedisSerializer());
userRedisTemplate.setConnectionFactory(redisConnectionFactory);
return userRedisTemplate;
}
}
5.編寫測試類
@RequestMapping("/redis")
@RestController
public class TestRedisController {
@Autowired
@Qualifier("userTemplate")
private RedisTemplate<String,User> redisTemplate;
@GetMapping("/get")
public User get(String id) {
if (redisTemplate.opsForValue().get("user")!=null){
return redisTemplate.opsForValue().get("user");
}
System.out.println("調用方法本身--get");
User user = new User();
user.setId(id);
user.setName("第一");
redisTemplate.opsForValue().set("user",user);
return user;
}
}
瀏覽器訪問,第一次輸出“調用方法本身--get”,但是第二次沒有輸出在,證明緩存可用。並且,通過redis-cli連接到redis服務器,輸入“get user” ,就會發現確實存在着這麼一個緩存: