在Spring Boot中使用数据缓存

170 篇文章 58 订阅
92 篇文章 16 订阅

关注公众号【江南一点雨】,专注于 Spring Boot+微服务以及前后端分离等全栈技术,定期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货!


春节就要到了,在回家之前要赶快把今年欠下的技术债还清。so,今天继续。Spring Boot前面已经预热了n篇博客了,今天我们来继续看如何在Spring Boot中解决数据缓存问题。本篇博客是以初识在Spring Boot中使用JPA为基础的,先了解如何实现数据访问,然后才好实现数据缓存。OK,对于Spring Boot尚有疑问的小伙伴可以先移步这里从SpringMVC到Spring Boot,老司机请略过。
OK,废话不多说,开始今天的技术之旅吧。
在实际开发中,对于要反复读写的数据,最好的处理方式是将之在内存中缓存一份,频繁的数据库访问会造成程序效率低下,同时内存的读写速度本身就要强于硬盘。Spring在这一方面给我们提供了诸多的处理手段,而Spring Boot又将这些处理方式进一步简化,接下来我们就来看看如何在Spring Boot中解决数据缓存问题。


#创建Project并添加数据库驱动
Spring Boot的创建方式还是和我们前文提到的创建方式一样,不同的是这里选择添加的依赖不同,这里我们添加Web、Cache和JPA依赖,如下图:
这里写图片描述
创建成功之后,接下来添加数据库驱动,我还是使用MySql,在pom.xml中添加数据库驱动,如下:

<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.40</version>
		</dependency>

#配置application.properties
这个application.properties的配置还是和初识在Spring Boot中使用JPA一样,各个参数的含义我这里也不再赘述,我们直接来看代码:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/sang?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=sang

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jackson.serialization.indent_output=true

#创建实体类

@Entity
public class Person {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    private String address;
    private Integer age;

    public Person() {
    }

    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 String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Person(Long id, String name, String address, Integer age) {
        this.id = id;
        this.name = name;
        this.address = address;
        this.age = age;
    }
}

#创建实体类的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;

    @CachePut(value = "people", key = "#person.id")
    @Override
    public Person save(Person person) {
        Person p = personRepository.save(person);
        System.out.println("为id、key为" + p.getId() + "数据做了缓存");
        return p;
    }

    @CacheEvict(value = "people")
    @Override
    public void remove(Long id) {
        System.out.println("删除了id、key为" + id + "的数据缓存");
        personRepository.delete(id);
    }

    @Cacheable(value = "people", key = "#person.id")
    @Override
    public Person findOne(Person person) {
        Person p = personRepository.findOne(person.getId());
        System.out.println("为id、key为" + p.getId() + "数据做了缓存");
        return p;
    }
}@Service
public class DemoServiceImpl implements DemoService {
    @Autowired
    PersonRepository personRepository;

    @CachePut(value = "people", key = "#person.id")
    @Override
    public Person save(Person person) {
        Person p = personRepository.save(person);
        System.out.println("为id、key为" + p.getId() + "数据做了缓存");
        return p;
    }

    @CacheEvict(value = "people")
    @Override
    public void remove(Long id) {
        System.out.println("删除了id、key为" + id + "的数据缓存");
        personRepository.delete(id);
    }

    @Cacheable(value = "people", key = "#person.id")
    @Override
    public Person findOne(Person person) {
        Person p = personRepository.findOne(person.getId());
        System.out.println("为id、key为" + p.getId() + "数据做了缓存");
        return p;
    }
}

关于这个实现类我说如下几点:

1.@CachePut表示缓存新添加的数据或者更新的数据到缓存中,两个参数value表示缓存的名称为people,key表示缓存的key为person的id
2.@CacheEvict表示从缓存people中删除key为id的数据
3.@Cacheable表示添加数据到缓存中,缓存名称为people,缓存key为person的id属性。


#创建Controller

@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";
    }
}

OK ,做完这一切我们就可以来测试我们刚刚写的缓存了。
#测试
看我们的Controller,我们有三个地址要测试,一个一个来。当然,在 测试之前,我们先来看看初始状态下的数据库是什么样子的:
这里写图片描述


首先我们在浏览器中访问http://localhost:8080/able?id=1,得到如下访问结果:
这里写图片描述
这个时候查看控制台,输出内容如下:
这里写图片描述
说是数据已经被缓存了,这个时候我们再继续在浏览器中刷新继续请求id为1的数据,会发现控制台不会继续打印日志出来,就是因为数据已被存于缓存之中了。


接下来我们向浏览器中输入http://localhost:8080/put?age=47&name=奥巴牛&address=米国,访问结果如下:
这里写图片描述
这个时候查看控制台打印的日志如下:
这里写图片描述
再查看数据表,数据已插入成功:
这里写图片描述
此时,我们在浏览器中输入http://localhost:8080/able?id=106,访问刚刚插入的这条数据,结果如下:
这里写图片描述
这个时候查看控制台,发现并没有数据数据,就是因为数据已经处于缓存中了。


最后我们在浏览器中输入http://localhost:8080/evit?id=106,将数据从缓存中移除,访问结果如下:
这里写图片描述
这个时候查看控制台,已经提示缓存移除掉了:
这里写图片描述
同时数据也从数据库删除掉了,这个时候如果还需要该数据则需要我们继续向表中添加数据。

#缓存技术切换
Spring Boot默认情况下使用ConcurrentMapCacheManager作为缓存技术,有的时候你可能想替换为其他的缓存方式,在Spring Boot中进行缓存的切换非常简单,我这里以Google提供的Guava为例,如果要使用这种缓存策略,只需要添加相应的依赖即可,如下:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>20.0</version>
</dependency>

就这样就可以了。实际上在Spring Boot中,底层使用哪一种缓存我们并不必做过多考虑,切换的方式也很简单,如上文引入相应的依赖即可,我们只需要把上层的逻辑写好即可。

本文案例下载:
本文GitHub地址https://github.com/lenve/JavaEETest/tree/master/Test25-Cache.

更多Spring Boot案例请移步这里从SpringMVC到Spring Boot

以上。

参考资料:

《JavaEE开发的颠覆者 Spring Boot实战》第八章

  • 13
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
Spring Boot 使用 Redis 作为数据缓存,需要以下步骤: 1. 添加 Redis 依赖 在 pom.xml 文件添加 Jedis 或 Lettuce 依赖,例如: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.6.0</version> </dependency> ``` 2. 配置 Redis 在 application.properties 或 application.yml 文件配置 Redis 相关信息,例如: ```properties spring.redis.host=localhost spring.redis.port=6379 spring.redis.password= spring.redis.database=0 ``` 3. 创建 RedisTemplate 在 Spring Boot ,可以使用 RedisTemplate 来操作 Redis 数据库。通常情况下,我们需要自己创建一个 RedisTemplate 的 Bean,并注入到需要使用 Redis 的地方。例如: ```java @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(connectionFactory); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return redisTemplate; } } ``` 4. 使用 Redis 在需要使用 Redis 缓存的地方,注入 RedisTemplate,并使用其提供的操作方法,例如: ```java @Service public class UserServiceImpl implements UserService { @Autowired private RedisTemplate<String, Object> redisTemplate; @Override public User getUserById(Long id) { String key = "user:id:" + id; User user = (User) redisTemplate.opsForValue().get(key); if (user == null) { user = userRepository.findById(id).orElse(null); if (user != null) { redisTemplate.opsForValue().set(key, user); } } return user; } } ``` 在上述代码,我们通过 Redis 缓存了用户信息,如果缓存不存在该用户信息,则从数据查询并将查询结果存入 Redis 缓存,下次查询先从缓存查询。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值