缓存(Cache)
简介
当我们需要重复地获取相同的数据的时候,我们一次又一次的请求数据库或者远程服务,导致大量的时间耗费在数据库查询或者远程方法的调用上,导致程序性能的恶化,这便是缓存要解决的问题。
实战
1:新建Spring Boot项目,添加依赖JPA、Web和Cache,并导入数据库驱动
2:配置属性
application.properties
//数据源
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/book
spring.datasource.username=root
spring.datasource.password=123456
//JPA
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jackson.serialization.indent-output=true
实体类Person
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
private String name;
private Integer age;
private String address;
public Person() {
super();
}
public Person(Long id, String name, Integer age, String address) {
super();
this.id = id;
this.name = name;
this.age = age;
this.address = address;
}
public Long getId() {
return id;
}
public void setId(Long 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;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
实体类Repository
public interface PersonRepository extends JpaRepository<Person, Long> {
}
服务接口
public interface DemoService {
public Person save(Person person);
public void remove(Long id);
public Person findOne(Person person);
}
服务接口的实现
@Service
public class DemoServiceImpl implements DemoService {
@Autowired
PersonRepository personRepository;
@Override
//@CachePut缓存新增的或更新的数据到缓存,其中缓存名称为people,数据的key是person的id
@CachePut(value = "people", key = "#person.id")
public Person save(Person person) {
Person p = personRepository.save(person);
System.out.println("为id、key为:"+p.getId()+"数据做了缓存");
return p;
}
@Override
//@CacheEvict从缓存people中删除key为id的数据
@CacheEvict(value = "people")
public void remove(Long id) {
System.out.println("删除了id、key为"+id+"的数据缓存");
//这里不做实际删除操作
}
@Override
//@Cacheable缓存key为person的id数据到缓存people中,如果没有指定key,则方法参数作为key保存到缓存中
@Cacheable(value = "people", key = "#person.id")
public Person findOne(Person person) {
Person p = personRepository.findOne(person.getId());
System.out.println("为id、key为:"+p.getId()+"数据做了缓存");
return p;
}
}
控制器CacheController
@RestController
public class CacheController {
@Autowired
DemoService demoService;
@RequestMapping("/put")
public Person put(Person person){
return demoService.save(person);
}
@RequestMapping("/able")
public Person cacheable(Person person){
return demoService.findOne(person);
}
@RequestMapping("/evit")
public String evit(Long id){
demoService.remove(id);
return "ok";
}
}
AppConfig.java
@Configuration
@EnableCaching //Spring Boot中还是要使用@EnableCaching 开启缓存支持
public class AppConfig {
}
运行测试:
测试@Cacheable:
再次访问,此时控制台不会再次输入Hibernate的查询语句,以及“为id、key为:1数据做了缓存”字样。表示没有调用这个方法,页面直接从数据缓存中获得数据;
测试@CachePut(@CachePut注解的方法总是会被执行)
控制台输出如下:
再次访问,控制台仍会输出:
测试@CacheEvit:
从缓存中删除key为1的缓存数据:
再次访问:
切换缓存技术
Redis
只需添加下面依赖即可:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
非关系型数据库NoSQL
Redis
实战
1:新建Spring Boot项目,添加依赖Redis和Web,并导入数据库驱动
2:配置属性(Spring Boot默认数据库连接满足我们当前测试要求,所以无需在application.properties配置连接信息)
3:领域模型类
public class Person implements Serializable{
private static final long serialVersionUID = 1L;
private String id;
private String name;
private Integer age;
public Person() {
super();//使用Jackson做序列化需要一个空构造
}
public Person(String id,String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
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;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
4:数据访问
@Repository
public class PersonDao {
@Autowired
StringRedisTemplate stringRedisTemplate; //注入StringRedisTemplate
@Resource(name="stringRedisTemplate")
ValueOperations<String,String> valOpsStr; //使用@Resource注解指定stringRedisTemplate,可注入基于字符串的简单属性操作方法
@Autowired
RedisTemplate<Object, Object> redisTemplate; //注入RedisTemplate
@Resource(name="redisTemplate")
ValueOperations<Object, Object> valOps; 使用@Resource注解指定redisTemplate,可注入基于对象的简单属性操作方法
public void stringRedisTemplateDemo(){ //set方法,存储字符串类型
valOpsStr.set("xx", "yy");
}
public void save(Person person){ //set方法,存储对象类型
valOps.set(person.getId(),person);
}
public String getString(){//get方法,获取字符串
return valOpsStr.get("xx");
}
public Person getPerson(){//get方法,获取对象
return (Person) valOps.get("1");
}
}
控制器DataController
@RestController
public class DataController {
@Autowired
PersonDao personDao;
@RequestMapping("/set") //设置字符及对象
public void set(){
Person person = new Person("1","wyf", 32);
personDao.save(person);
personDao.stringRedisTemplateDemo();
}
@RequestMapping("/getStr") //获得字符
public String getStr(){
return personDao.getString();
}
@RequestMapping("/getPerson") //获得对象
public Person getPerson(){
return personDao.getPerson();
}
}
运行测试:
参考书籍:Spring Boot实战
以上只是学习所做的笔记,以供日后参考!!!