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,第二次就不會打印;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章