介绍

Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。

Spring Cache提供了一层抽象,底层可以切换不同的cache实现。具体就是通过CacheManager接口来统一不同的缓存技术。

CacheManager是Spring提供的各种缓存技术抽象接口。

针对不同的缓存技术需要实现不同的CacheManager:

CacheManager 描述
EhCacheCacheManager 使用EhCache作为缓存技术
GuavaCacheManager 使用Google的GuavaCache作为缓存技术
RedisCacheManager 使用Redis作为缓存技术

常用注解

注解 说明
@EnableCaching 开启缓存注解功能
@Cacheable 在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中
@CachePut 将方法的返回值放到缓存中
@CacheEvict 将一条或多条数据从缓存中删除

在Spring Boot项目中,使用缓存技术只需在项目中导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存支持即可。

例如,使用Redis作为缓存技术,只需要导入spring-boot-starter-data-redis的Maven坐标即可。

实际测试

使用Spring Cache(默认缓存ConcurrentMapCacheManager

创建Spring Boot项目,使用MybatisX插件生成对应的mapper、service、实体类等,导入相关依赖,修改配置文件,创建数据库

pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.itheima</groupId>
    <artifactId>cache_demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.23</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.4.5</version>
            </plugin>
        </plugins>
    </build>
</project>

application.yml如下:

server:
  port: 8080
spring:
  application:
    #应用的名称,可选
    name: cache_demo
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/cache_demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
      username: root
      password: 123456
mybatis-plus:
  configuration:
    #在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: ASSIGN_ID

数据库SQL如下:

/*
 Navicat Premium Data Transfer
 Source Server         : Aiw
 Source Server Type    : MySQL
 Source Server Version : 50528
 Source Host           : localhost:3306
 Source Schema         : cache_demo
 Target Server Type    : MySQL
 Target Server Version : 50528
 File Encoding         : 65001
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` bigint(20) NOT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `age` int(11) NULL DEFAULT NULL,
  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1568896554487369729, 'Aiw', 22, '湖北省');
SET FOREIGN_KEY_CHECKS = 1;

在启动类上添加@EnableCaching注解

package com.itheima;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@Slf4j
@SpringBootApplication
@EnableCaching  // 开启缓存注解功能
public class CacheDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(CacheDemoApplication.class,args);
        log.info("项目启动成功...");
    }
}

创建UserController

package com.itheima.controller;
import com.itheima.entity.User;
import com.itheima.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
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 java.util.List;
import java.util.Objects;
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
    @Autowired
    private CacheManager cacheManager;
    @Autowired
    private UserService userService;
    /**
     * CachePut:将方法返回值放入缓存
     * value:缓存的名称,每个缓存名称下面可以有多个key
     * key:缓存的key
     */
    @CachePut(value = "userCache", key = "#user.id")
    @PostMapping
    public User save(User user) {
        userService.save(user);
        return user;
    }
    /**
     * CacheEvict:清理指定缓存
     * value:缓存的名称,每个缓存名称下面可以有多个key
     * key:缓存的key
     */
    @CacheEvict(value = "userCache", key = "#p0")
    //@CacheEvict(value = "userCache",key = "#root.args[0]")
    //@CacheEvict(value = "userCache",key = "#id")
    @DeleteMapping("/{id}")
    public void delete(@PathVariable Long id) {
        userService.removeById(id);
    }
    //@CacheEvict(value = "userCache",key = "#p0.id")
    //@CacheEvict(value = "userCache",key = "#user.id")
    //@CacheEvict(value = "userCache",key = "#root.args[0].id")
    @CacheEvict(value = "userCache", key = "#result.id")
    @PutMapping
    public User update(User user) {
        userService.updateById(user);
        return user;
    }
    /**
     * Cacheable:在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中
     * value:缓存的名称,每个缓存名称下面可以有多个key
     * key:缓存的key
     * condition:条件,满足条件时才缓存数据
     * unless:满足条件则不缓存
     */
    @Cacheable(value = "userCache", key = "#id", unless = "#result == null")
    @GetMapping("/{id}")
    public User getById(@PathVariable Long id) {
        return userService.getById(id);
    }
    @Cacheable(value = "userCache", key = "#user.id   '_'   #user.name")
    @GetMapping("/list")
    public List<User> list(User user) {
        return userService.lambdaQuery()
                .eq(Objects.nonNull(user.getId()), User::getId, user.getId())
                .eq(Objects.nonNull(user.getName()), User::getName, user.getName())
                .list();
    }
}

以上不同写法均等价

使用ApiPost进行接口测试

打断点调试,发送请求,可以看到已存入缓存

该缓存底层基于Map实现,默认ConcurrentHashMap基于内存,重启服务会清空缓存数据

使用Spring Cache(redis缓存RedisCacheManager

导入Maven坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

修改配置文件

server:
  port: 8080
spring:
  application:
    #应用的名称,可选
    name: cache_demo
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/cache_demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
      username: root
      password: 123456
  redis:
    host: localhost
    port: 6379
#    password: root@123456
    database: 0
  cache:
    redis:
      time-to-live: 1800000 #设置缓存过期时间(单位:秒),可选
mybatis-plus:
  configuration:
    #在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: ASSIGN_ID

启动项目,再次请求接口

启动redis命令行窗口,查看

当请求不存在的id时,不会执行缓存操作(@Cacheable注解的unless条件起作用)

到此这篇关于Spring Cache框架应用介绍的文章就介绍到这了,更多相关Spring Cache框架内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Spring Cache框架应用介绍的更多相关文章

  1. xcode6.1 – Xcode 6.1中项目模板中缺少类前缀

    项目模板上曾经有一个类前缀字段,这有助于区分项目类和框架类.Xcode6.1项目模板中不再提供此功能.这背后的意图是什么?

  2. ios – 伞框架

    错误.应用程序,通常位于…错误仍然存在你也可以在这里添加(子)框架的路径.

  3. ios – UIView框架大小的问题

    我正在开发一个iPad项目,目前正在使用Landscape视图.我试着这样做:为什么这总是返回960?虽然在景观中,视图本身的高度尺寸应为768对吗?

  4. 安装自定义cocoa框架的最佳方法

    我有一个自定义框架,遵循Apple的框架编程指南>>中的建议.Installingyourframework我在/Library/Frameworks中安装.我通过使用以下脚本添加RunScript构建阶段来完成此操作:在我的项目中,我然后链接/Library/Frameworks/MyFramework并将其导入我的类中,如下所示:这非常有效,除了我总是在调试器控制台中看到以下消息:Loadin

  5. ios – 在设备上构建和运行时,仅将嵌入式框架与其他动态框架链接失败

    TL;博士将您的嵌入式框架与其他框架链接,并且不将其他框架与您的应用程序链接,导致Build&在设备上运行.描述:建立:我的设置非常简单(Swift2.3&XcodeXcode8.0;Build版本8S162m):>使用Carthage(0.17.2)我用xcodebuild8.0和TOOLCHAINS=com.apple.dt.toolchain.Swift_2_3carthagebui

  6. iOS 8嵌入式框架中的头文件

    我正在尝试创建一个用于iOS8的嵌入式框架.在创建一个名为SampleKit(BTW;这里有任何约定,我应该使用前缀吗?)之后,它包含一个令我困惑的头文件:我知道FOUNDATION_EXPORT是extern或extern“C”的宏,但我不确定这两个常量.我应该在哪里为他们设定价值?解决方法项目>构建设置>版本控制>当前项目版本:

  7. 在Monotouch上模拟.NET的框架?

    有没有人使用过他们发现与Monotouch兼容的.NET模拟框架?在尝试使用之前,我很好奇与NMock,NSubstitute,Moq和其他框架的兼容性.Xamarin刚刚加强了它的单元测试支持,但没有提到模拟框架.仅供参考,我希望在VS2010上为非UI位做很多开发,并在UI进入时移动到iOS平台.谢谢您的帮助.解决方法我建议只使用手动模拟:如果我不得不猜测RhinoMocks,Moq等大量使用Reflection.Emit(你怎么能做他们能做的疯狂?),这将无法在MonoTouch上使用AOT编译器运

  8. 在ios上使用来自框架的boost :: filesysystem路径

    我一直在使用Boost作为PeteGoodliffe脚本构建的框架已有一段时间了.效果很好.最近我遇到了一个问题,可以通过将以下代码放入另一个全新的XCode项目中的视图控制器的viewDidLoad中来重现:当路径对象被销毁时会导致EXC_BAD_ACCESS.有没有其他人遇到这个问题?

  9. ios – 在约束依赖于框架的自定义视图中使用自动布局

    我正在编写一个以编程方式初始化的自定义视图.我重写updateConstraints以添加此视图所需的所有约束.:问题是self.bounds返回CGRectZero的等价物.我做了我的研究并根据这个objc.ioarticle,这是预期的,因为在调用layoutSubviews之前框架不会被设置.它也提到了Toforcethesystemtoupdatethelayoutofaviewtreei

  10. ios – “禁用模块时使用’@import’”错误 – 启用模块和链接框架= YES

    我有一个使用CocoaPods并使用’SCLAlertView-Objective-C’窗格的项目.该pod使用@importUIKit;模块样式导入.我在目标和项目设置中将“启用模块(C&Objective-C)”和“自动链接框架”设置为YES.当模块被禁用时,我仍然得到“使用’@import’错误.有没有什么可以阻止Xcode能够启用模块,如使用.pch文件,任何链接器标志,或者我没有提到的任

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部