關(guān)于redis的安裝、配置及啟動,參考Redis簡單配置使用
1.添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.添加配置文件
#Redis數(shù)據(jù)庫索引(默認(rèn)為0)
spring.redis.database=0
#Redis服務(wù)器地址
spring.redis.host=localhost
#Redis服務(wù)器連接端口
spring.redis.port=6379
#Redis服務(wù)器連接密碼(默認(rèn)為空)
spring.redis.password=123456
#連接池最大連接數(shù)(使用負(fù)值表示沒有限制)
spring.redis.pool.max-active=8
#連接池最大阻塞等待時間(使用負(fù)值表示沒有限制)
spring.redis.pool.max-wait=-1
#連接池中的最大空閑連接
spring.redis.pool.max-idle=8
#連接池中的最小空閑連接
spring.redis.pool.min-idle=0
#連接超時時間(毫秒)
spring.redis.timeout=1000
3.添加配置類
Redis 不是應(yīng)用的共享內(nèi)存钢属,它只是一個內(nèi)存服務(wù)器,就像 MySql 门躯,我們需要將應(yīng)用連接到它并使用某種“語言”進行交互淆党,因此我們還需要一個連接工廠以及一個 Spring 和 Redis 對話要用的 RedisTemplate,這些都是 Redis 緩存所必需的配置.
Redis 可以存儲鍵與5種不同數(shù)據(jù)結(jié)構(gòu)類型之間的映射讶凉,這5種數(shù)據(jù)結(jié)構(gòu)類型分別為String(字符串)染乌、List(列表)、Set(集合)懂讯、Hash(散列)和 Zset(有序集合)慕匠。
代碼:
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object o, Method method, Object... objects) {
StringBuilder sb = new StringBuilder();
sb.append(o.getClass().getName());
sb.append(method.getName());
for (Object object:objects) {
sb.append(object.toString());
}
return sb.toString();
}
};
}
// 要啟用緩存支持,我們需要創(chuàng)建一個新的 CacheManager bean
@SuppressWarnings("rawtypes")
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager manager = new RedisCacheManager(redisTemplate);
return manager;
}
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
以下內(nèi)容是針對上面配置的一些解釋說明:
1.關(guān)于public KeyGenerator keyGenerator():
對于使用 @Cacheable 注解的方法域醇,每個緩存的 key 生成策略默認(rèn)使用的是參數(shù)名+參數(shù)值台谊,比如以下方法:
@Cacheable("users")
public User findByUsername(String username)
這個方法的緩存將保存于 key 為 users~keys 的緩存下蓉媳,對于 username 取值為 "趙德芳" 的緩存,key 為 "username-趙德芳"锅铅。一般情況下沒啥問題酪呻,但是如果方法 key 取值相等然后參數(shù)名也一樣的時候就出問題了,如:
@Cacheable("users")
public Integer getLoginCountByUsername(String username)
這個方法的緩存也將保存于 key 為 users~keys 的緩存下盐须。對于 username 取值為 "趙德芳" 的緩存玩荠,key 也為 "username-趙德芳",將另外一個方法的緩存覆蓋掉贼邓。
解決辦法是使用自定義緩存策略阶冈,對于同一業(yè)務(wù)(同一業(yè)務(wù)邏輯處理的方法,哪怕是集群/分布式系統(tǒng))塑径,生成的 key 始終一致女坑,對于不同業(yè)務(wù)則不一致:
于是上述兩個方法,對于 username 取值為 "趙德芳" 的緩存统舀,雖然都還是存放在 key 為 users~keys 的緩存下匆骗,但由于 key 分別為 "類名-findByUsername-username-趙德芳" 和 "類名-getLoginCountByUsername-username-趙德芳",所以也不會有問題誉简。
這對于集群系統(tǒng)碉就、分布式系統(tǒng)之間共享緩存很重要,真正實現(xiàn)了分布式緩存闷串。
2.RedisTemplate:
spring 封裝了 RedisTemplate 對象來進行對redis的各種操作瓮钥,它支持所有的 redis 原生的 api。
RedisTemplate默認(rèn)采用的是JDK的序列化策略烹吵,保存的key和value都是采用此策略序列化保存的碉熄。因此被緩存對象需要實現(xiàn)java.io.Serializable接口,否則緩存出錯年叮。(比如后面要用到的User)。
RedisTemplate中定義了對5種數(shù)據(jù)結(jié)構(gòu)操作
redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForHash();//操作hash
redisTemplate.opsForList();//操作list
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set
模板中的Redis key的類型(通常為String)如:RedisTemplate<String, Object>
注意:如果沒特殊情況玻募,切勿定義成RedisTemplate<Object, Object>只损,否則根據(jù)里氏替換原則,使用的時候會造成類型錯誤 七咧。
3.StringRedisTemplate與RedisTemplate
兩者的關(guān)系是StringRedisTemplate繼承RedisTemplate跃惫。
兩者的數(shù)據(jù)是不共通的;也就是說StringRedisTemplate只能管理StringRedisTemplate里面的數(shù)據(jù)艾栋,RedisTemplate只能管理RedisTemplate中的數(shù)據(jù)爆存。
SDR默認(rèn)采用的序列化策略有兩種,一種是String的序列化策略蝗砾,一種是JDK的序列化策略先较。
StringRedisTemplate默認(rèn)采用的是String的序列化策略携冤,保存的key和value都是采用此策略序列化保存的。
4.定一個User類
//RedisTemplate下被緩存的對象一定要實現(xiàn)Serializable接口
public class User implements Serializable {
private String name;
private int age;
private String email;
public User() {
super();
}
public User(String name, int age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
'}';
}
}
5.測試
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisTemplate redisTemplate;
@Test
public void contextLoads() {
stringRedisTemplate.opsForValue().set("myKey", "123456");
System.out.println(stringRedisTemplate.opsForValue().get("myKey"));
}
@Test
public void testObj() throws Exception {
User user = new User("archerLj", 27, "lj0011977@163.com");
ValueOperations<String, User> operations = redisTemplate.opsForValue();
operations.set("myUser", user);
operations.set("myUser2", user,1, TimeUnit.MINUTES); //設(shè)置緩存過期時間為1分鐘闲勺。
Thread.sleep(60000);
boolean exists = redisTemplate.hasKey("myUser");
if (exists) {
System.out.println("key myUser exists");
} else {
System.out.println("key myUser not exists");
}
boolean exists2 = redisTemplate.hasKey("myUser2");
if (exists2) {
System.out.println("key myUser2 exists");
} else {
System.out.println("key myUser2 not exists");
}
}
}
----------------------下面是注解方式的使用-----------
1.添加以下依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
使用mysql數(shù)據(jù)庫曾棕,JPA來做數(shù)據(jù)操作。
2.定義實體類User
package com.example.demo.domain;
@Entity
public class User implements Serializable {
@Id
private int id;
private String name;
private int age;
private String email;
public User() {
super();
}
public User(String name, int age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
'}';
}
}
3. 在啟動類添加實體類掃描目錄并開啟緩存菜循。
@EnableCaching
@ComponentScan("com.example.demo.domain")
public class DemoApplication {}
4.UserRepository接口定義
@CacheConfig(cacheNames = "users")
public interface UserRepository extends JpaRepository<User, Long> {
@Cacheable(key = "#p0")
User findByName(String name);
@CachePut(key = "#p0.name")
User save(User user);
}
5.啟動類添加兩個請求:
@RestController
@SpringBootApplication
@EnableCaching
@ComponentScan("com.example.demo.domain")
public class DemoApplication {
@Autowired
UserRepository userRepository;
@RequestMapping("/getUser")
public User getUser() {
User user = userRepository.findByName("archerLj");
return user;
}
@RequestMapping("/save")
public User save() {
User user = userRepository.findByName("archerLj");
user.setAge(102);
return userRepository.save(user);
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
6.修改配置
spring.datasource.url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop
spring.jpa.properties.hibernate.show_sql=true
數(shù)據(jù)庫:
use test1;
create table User(
id int primary key auto_increment,
name varchar(20),
age int,
email varchar(30)
) default charset=utf8;
insert into test1.User(name, age, email) values("archerLj", 27, "lj0011977@163.com");
7.測試:
訪問http://localhost:8080/getUser
翘地,第一次訪問,后臺會打印sql語句癌幕,第二次訪問會直接從緩存中獲取衙耕,不會再打印sql。
訪問http://localhost:8080/save
來修改用戶的age
屬性勺远,再訪問http://localhost:8080/getUser
橙喘,發(fā)現(xiàn)沒有打印sql,但age
屬性已經(jīng)隨著修改了谚中。修改的數(shù)據(jù)之所以能同步到緩存中渴杆,是因為@CachePut
注解起的作用。
參考:
如何使用RedisTemplate訪問Redis數(shù)據(jù)結(jié)構(gòu)
springboot(三):Spring boot中Redis的使用
Spring Boot中的緩存支持(二)使用Redis做集中式緩存