spring cache在springboot中的应用

1、为什么使用缓存

我们都知道,一个程序的瓶颈通常都在数据库,很多场景需要获取相同的数据。比如网站页面数据等,
需要一次次的请求数据库,导致大部分时间都浪费在数据库查询和方法调用上,这时就可以利用到缓存来缓解这个问题。

2、声明式缓存

Spring 定义 CacheManager 和 Cache 接口用来统一不同的缓存技术。例如 JCache、 EhCache、 Hazelcast、 Guava、 Redis 等。
在使用 Spring 集成 Cache 的时候,我们需要注册实现的 CacheManager 的 Bean。
Spring Boot 为我们自动配置了 JcacheCacheConfiguration、 EhCacheCacheConfiguration、HazelcastCacheConfiguration、
GuavaCacheConfiguration、RedisCacheConfiguration、SimpleCacheConfiguration 等。

3、默认使用 ConcurrenMapCacheManager

在我们不使用其他第三方缓存依赖的时候,springboot自动采用ConcurrenMapCacheManager作为缓存管理器。

4、使用过程需要注意什么

1、明确哪些方法需要使用缓存,正确使用使得程序变得高效,不会导致编码累赘
2、用于解决哪些实际问题

5、下面是一个简单的例子,只截图了关键使用部分,springboot+mybatis+mysql+spring cahce实现的缓存效果

依赖

 <!-- mysql连接类-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
<!--alibaba连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.29</version>
        </dependency>
 <!--     开启web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
<!--          cache缓存环境-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
<!--springboot整合mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

properties.yml配置 cache无需配置,只配置了mysql#mysql数据库连接

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/hotel?serverTimezone=UTC
    username: root
    password: aaaaaa

开启缓存功能,需要正在启动类上加注解@EnableCaching

@SpringBootApplication
//开启缓存
@EnableCaching
public class DemoApplication {

    public static void main(String[] args) {

        SpringApplication.run(DemoApplication.class, args);
    }
}

此处实体类、dao层、service层省略了,只展示controller部分代码,因为该cache功能主要是用注解来实现缓存效果

package com.hotel.demo.web;
import com.hotel.demo.bean.Style;
import com.hotel.demo.dao.JpaStyleDao;
import com.hotel.demo.service.StyleService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;


import javax.transaction.Transactional;
import java.util.List;
import java.util.jar.JarEntry;

@RestController
@RequestMapping("/style")
@Transactional
public class StyleController {
    private static final Logger logger = LoggerFactory.getLogger(StyleController.class);
    @Autowired
    StyleService styleService;
    @Autowired
    JpaStyleDao jpaStyleDao;

    /*插入数据*/
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @ApiOperation(value = "添加房间类型", notes = "添加房间类型")
    @CachePut(value = "style")
    public int add() throws RuntimeException {
        Style style = new Style();
        style.setStyle("大房");
        style.setMoney(125.0);
        style.setFacilities("卫生间、健生房");
        style.setMessage("可住两人");
        return styleService.add(style);
    }

    //更新数据
    /*@PathVariable@RequestParam 一起使用 请求方式http://127.0.0.1:8080/style/update/5?style=大房*/
    @RequestMapping(value = "/update/{id}", method = RequestMethod.PUT)
    @ApiOperation(value = "更新数据", notes = "更新数据")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "style", value = "类型名", required = true, dataType = "String", paramType = "path"),
            @ApiImplicitParam(name = "id", value = "类型id", required = true, dataType = "int", paramType = "path")
    })
    @CachePut(value="style",key="#id")
    public int update(@PathVariable int id, @RequestParam(value = "style", required = true) String style) {
      /*  Style style = new Style();
        style.setId(id);
        style.setStyle(styles);
        style.setMoney(126.0);
        style.setFacilities("卫生间、健生房");
        style.setMessage("可住两人");
        return styleService.update(style);*/
        return styleService.update(style, id);
    }

    //删除数据
    @ApiOperation(value = "删除数据", notes = "删除数据")
    @ApiImplicitParam(name = "id", value = "类型ID", required = true, dataType = "int", paramType = "path")
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
    @CacheEvict(value="style",key="#id")
    public void delete(@PathVariable int id) {
        styleService.delete(id);
    }
    //按照ID查找数据
    @ApiOperation(value = "按照ID查找数据", notes = "按照ID查找数据")
    @ApiImplicitParam(name = "id", value = "类型ID", required = true, dataType = "int", paramType = "path")
    @RequestMapping(value = "/findById/{id}", method = RequestMethod.GET)
//打开该方法的缓存
    @Cacheable(value = "style", key = "#id")
    public Style findById(@PathVariable int id) {
        long startTime = System.currentTimeMillis();
        Style style = styleService.findById(id);
        long endTime = System.currentTimeMillis();
        logger.info("start -->end时间差" + (endTime - startTime));
        return style;

    }

    //查找所有数据
    @ApiIgnore//使用该注解忽略这个API
    @ApiOperation(value = "查找所有数据", notes = "查找所有数据")
    @RequestMapping(value = "/findAll", method = RequestMethod.GET)
    @Cacheable(value = "emp")
    public List<Style> findAll() {

        return styleService.findAll();

    }
}

大家还需要关注类方法上的注解@Cacheable()、 @CacheEvict()、@CachePut()

解释测试方法

1.add方法

方法中使用到了@CachePut注解,这个注解直接将返回值放入缓存中,通常用于保存和修改方法中

2.findAll、findById方法

方法中使用到了@Cacheable注解,这个注解在执行前先查看缓存中是不是已经存在了,如果存在,直接返回。如果不存在,将方法的返回值放入缓存。

3.delete方法

方法中使用到了@CacheEvict注解,这个注解在执行方法执行成功后会将操作的对象从缓存中移除,仅针对某一次的缓存
@CacheEvict也可以将所有缓存删除,写法为 @CacheEvict(value = “house”, allEntries = true) allEntries不写默认为false 只删除注解方法指定的缓存

参数解释

如@Cacheable(value = “style”, key = “#id”)中value指的是给该次缓存取一个名字自定义,key为该缓存的键

1.当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。 如

 @Cacheable(value = "emp" ,key = "targetClass + methodName +#p0")
    public List<NewJob> queryAll(User uid) {
        return newJobDao.findAllByUid(uid);
    }

2.使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。 如:

@Cacheable(value="users", key="#id")
public void delete(@PathVariable int id) {
        styleService.delete(id);
    }

@Cacheable(value="users", key="#p0")
public void delete(@PathVariable int id) {
        styleService.delete(id);
    }

注意

这个缓存注解对的意义是当查询有缓存存在时,直接返回缓存值,而不会再去执行注解的方法,
参考findById方法的时间差打印,执行两次findById,只会执行一次打印,第二次执行直接返回,没有执行该方法
如果大家想让缓存效果更明显一点,可以使用springboot+jpa+mybatis+cache,需要开启show-sql: true 打印sql语句
在执行的时候你会发现,当你执行第一次查询时会打印sql,第二次就不会打印;

发布了20 篇原创文章 · 获赞 10 · 访问量 5457

猜你喜欢

转载自blog.csdn.net/weixin_43784880/article/details/104282372