SpringCache与redis集成,优雅的缓存解决方案

5分钟搞定!用ZLMediaKit+GB28181搭建低成本外网视频监控(含避坑指南) 本文详细介绍了如何利用开源ZLMediaKit流媒体服务器与国标GB28181协议,快速搭建低成本、可外网访问的企业级视频监控系统。文章提供了从服务端部署、设备配置到外网访问优化的完整实战指南,并重点分享了网络配置、性能调优及常见问题的避坑方案,帮助用户实现高清视频流的稳定推送与多格式播放。 阅读详情

来源:cnblogs.com/chenkeyu/p/8028781.html

缓存可以说是加速服务响应速度的一种非常有效并且简单的方式。在缓存领域,有很多知名的框架,如EhCache 、Guava、HazelCast等。

Redis作为key-value型数据库,由于他的这一特性,Redis也成为一种流行的数据缓存工具。

在传统方式下对于缓存的处理代码是非常臃肿的。

例如:我们要把一个查询函数加入缓存功能,大致需要三步。

  • 在函数执行前,我们需要先检查缓存中是否存在数据,如果存在则返回缓存数据

  • 如果不存在,就需要在数据库的数据查询出来。

  • 最后把数据存放在缓存中,当下次调用此函数时,就可以直接使用缓存数据,减轻了数据库压力。

那么实现上面的三步需要多少代码呢?下面是一个示例:

上图中的红色部分都是模板代码,真正与这个函数有关的代码却只占了1/5,对于所有需要实现缓存功能的函数,都需要加上臃肿的模板代码。可谓是一种极不优雅的解决方案。

那么如何让臃肿的代码重回清新的当初呢?

AOP不就是专门解决这种模板式代码的最佳方案吗,幸运的是我们不需要再自己实现切面了,SpringCache已经为我们提供好了切面,我们只需要进行简单的配置,就可以重回当初了,像下面这样:

只需要加一个注解就可以了,对于原来的代码连改都不需要改,是不是已经跃跃欲试了?

对于配置SpringCache只需要三步:

第一步:加入相关依赖:

<dependency>  
   <groupId>redis.clients</groupId>  
   <artifactId>jedis</artifactId>  
  <version>2.9.0</version>  
</dependency>  
<dependency>  
   <groupId>org.springframework.data</groupId>  
   <artifactId>spring-data-redis</artifactId>  
   <version>1.6.0.RELEASE</version>  
</dependency> 
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>   <version>3.3.2</version>
</dependency>

第二步:配置SpringCache,Redis连接等信息

applicationContext-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"    
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"    
    xmlns:context="http://www.springframework.org/schema/context"    
    xmlns:mvc="http://www.springframework.org/schema/mvc"    
    xmlns:cache="http://www.springframework.org/schema/cache"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans      
                        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd      
                        http://www.springframework.org/schema/context      
                        http://www.springframework.org/schema/context/spring-context-4.2.xsd      
                        http://www.springframework.org/schema/mvc      
                        http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd  
                        http://www.springframework.org/schema/cache   
                        http://www.springframework.org/schema/cache/spring-cache-4.2.xsd">
    
  <!-- 配置文件加载 -->
  <context:property-placeholder location="classpath:*.properties"/>
<cache:annotation-driven cache-manager="cacheManager"/>
    <!-- redis连接池 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.maxIdle}" />     
         <property name="maxWaitMillis" value="${redis.maxWait}" />    
         <property name="testOnBorrow" value="${redis.testOnBorrow}" /> 
    </bean>
    <!-- 连接工厂 -->
    <bean id="JedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"    
       p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig"/>
    <!-- redis模板 -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">    
         <property name="connectionFactory" ref="JedisConnectionFactory" />    
    </bean>
     
    <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">    
         <property name="caches">    
            <set>    
                <!-- 这里可以配置多个redis -->  
                <bean class="com.cky.rest.utils.RedisCache">    
                     <property name="redisTemplate" ref="redisTemplate" />    
                     <property name="name" value="content"/>    
                     <!-- name对应的名称要在类或方法的注解中使用 -->  
                </bean>  
            </set>    
         </property>    
     </bean>    
</beans>

redis.properties文件:

# Redis settings  
# server IP  
redis.host=192.168.100.55 
# server port  
redis.port=6379  
# server pass  
redis.pass=
# use dbIndex  
redis.database=0 
#max idel instance of jedis
redis.maxIdle=300  
#if wait too long ,throw JedisConnectionException
redis.maxWait=3000  
#if true,it will validate before borrow jedis instance,what you get instance is all usefull
redis.testOnBorrow=true

第三步,编写Cache接口实现类

Spring对于缓存只是提供了抽象的接口,并且通过接口来调用功能,没有具体的实现类,所以需要我们自己实现具体的操作。搜索Java知音公众号,回复“后端面试”,送你一份Java面试题宝典

在上面配置中可知,每个实现类都会注入一个redisTemplate实例,我们就可以通过redisTemplate来操作redis

package com.cky.rest.utils;

import java.io.Serializable;

import org.apache.commons.lang3.SerializationUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;

public class RedisCache implements Cache {

    private RedisTemplate<String, Object> redisTemplate;
    private String name;

    @Override
    public void clear() {
        System.out.println("-------緩存清理------");
        redisTemplate.execute(new RedisCallback<String>() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                connection.flushDb();
                return "ok";
            }
        });
    }

    @Override
    public void evict(Object key) {
        System.out.println("-------緩存刪除------");
        final String keyf=key.toString();
        redisTemplate.execute(new RedisCallback<Long>() {
            @Override
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.del(keyf.getBytes());
            }
            
        });

    }

    @Override
    public ValueWrapper get(Object key) {
        System.out.println("------缓存获取-------"+key.toString());
        final String keyf = key.toString();
        Object object = null;
        object = redisTemplate.execute(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                byte[] key = keyf.getBytes();
                byte[] value = connection.get(key);
                if (value == null) {
                    System.out.println("------缓存不存在-------");
                    return null;
                }
                return SerializationUtils.deserialize(value);
            }
        });
        ValueWrapper obj=(object != null ? new SimpleValueWrapper(object) : null);
        System.out.println("------获取到内容-------"+obj);
        return  obj;
    }

    @Override
    public void put(Object key, Object value) {
        System.out.println("-------加入缓存------");
        System.out.println("key----:"+key);
        System.out.println("key----:"+value);
        final String keyString = key.toString();
        final Object valuef = value;
        final long liveTime = 86400;
        redisTemplate.execute(new RedisCallback<Long>() {
            @Override
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                byte[] keyb = keyString.getBytes();
                byte[] valueb = SerializationUtils.serialize((Serializable) valuef);
                connection.set(keyb, valueb);
                if (liveTime > 0) {
                    connection.expire(keyb, liveTime);
                }
                return 1L;
            }
        });

    }
    
    @Override
    public <T> T get(Object arg0, Class<T> arg1) {
        // TODO Auto-generated method stub
        return null;
    }
    
    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public Object getNativeCache() {
        return this.redisTemplate;
    }
    
    @Override
    public ValueWrapper putIfAbsent(Object arg0, Object arg1) {
        // TODO Auto-generated method stub
        return null;
    }

    public RedisTemplate<String, Object> getRedisTemplate() {
        return redisTemplate;
    }

    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void setName(String name) {
        this.name = name;
    }
}

在配置过程中曾经出现过两次错误:

  1. Xxxx.ClassNotFoundException 最后发现是jar下载不完整,把maven本地仓库的对应jar包文件夹删除完从新下载就好了

  2. Xxxx.MethodNotFoundException 这种情况是版本不对,换成第一步中的版本就可以了

SpringCache中常见注解的使用:

@Cacheable注解

最常用的注解,会把被注解方法的返回值缓存。工作原理是:首先在缓存中查找,如果没有执行方法并缓存结果,然后返回数据。此注解的缓存名必须指定,和cacheManager中的caches中的某一个Cache的name值相对应。可以使用value或cacheNames指定。

如果没有指定key属性,spring会使用默认的主键生成器产生主键。也可以自定义主键,在key中可以使用SpEL表达式。如下:

@Cacheable(cacheNames=”content”,key=”#user.userId”)
Public User getUser(User user){
    xxxxx
}     

可以使用condition属性,来给缓存添加条件,如下:

@Cacheable(cacheNames=”content”,key=”#user.userId”,condition=”#user.age<40”)
Public User getUser(User user){xxxxx}

@CachePut注解

先执行方法,然后将返回值放回缓存。可以用作缓存的更新。

@CacheEvict注解

该注解负责从缓存中显式移除数据,通常缓存数据都有有效期,当过期时数据也会被移除。

此注解多了两个属性:

allEntries是否移除所有缓存条目。

beforeInvocation:在方法调用前还是调用后完成移除操作。true/false

智能音箱开发者必看:CEVA-BX vs Cadence HiFi音频DSP实战选型指南(附功耗对比表) 本文深入对比了CEVA-BX和Cadence HiFi两大音频DSP架构在智能音箱开发中的性能差异,涵盖语音唤醒、多麦克风阵列处理等核心场景。通过实测数据和功耗对比表,为开发者提供选型参考,帮助优化产品性能和能效表现。 阅读详情

相关推荐

在银河麒麟V10上部署Atlas 300i Duo:从固件到驱动的一站式踩坑笔记

日期:2025-09-09关键词:鲲鹏920、Atlas 300i Duo、银河麒麟V10、NPU、驱动、固件。

weixin_41544125的博客 2819

缓存之SpringCache整合redis

Spring Cache 是 Spring 框架提供的一种缓存抽象,在应用中可以方便地使用它来进行方法级别的缓存。首先,确保你的 Spring Boot 项目中引入了相关的依赖。当方法被调用时,如果缓存中已经存在对应 key 的数据,则直接返回缓存中的数据;如果缓存中不存在对应 key 的数据,则执行方法体中的代码,并将结果存入缓存。然后,在你的 Spring Boot 应用中,定义一个 Service 类,并在其中使用 Spring Cache 注解来实现方法级别的缓存。

weixin_43784341的博客 994

版电力系统故障录波_故障录波识图与典型故障波形分析

1、设置故障录波的目的故障录波装置是对电力系统运行状况进行监控的一种自动化设备。系统正常运行时,录波装置不启动录波,当系统发生故障时,通过启动录波装置迅速启动录波器录波,直接记录反应故障装置安装处系统故障的电气量。2、故障录波的作用(1)正确评价继电保护和自动装置的工作。(2)正确分析事故的原因并研究防止对侧。(3)发现继电保护和自动装置缺陷。(4)发现一次设备缺陷,及时消除隐患。(5)帮助寻找故...

weixin_42495661的博客 1万+

SpringCache+Redis的整合(微服务)

SpringCache+Redis的整合(微服务)

m0_56336875的博客 1958

jmeter小白下载安装步骤

本文仅仅简单介绍了jmeter工具的下载安装,以及基础的操作步骤。

昔年@曦的博客 3498

基于Python的网络拓扑图绘制

最近写论文画了许多图,在这里记录一些。当然,如果仅仅是展示性图片的话也可以使用visio,但是这里我仍然想探究一下如何使用pyhon画出美观的网络拓扑图。(1)根据邻接矩阵画出网络拓扑图(2)画出网络拓扑图,并对节点和链路进行表示,包括对节点和链路的标号,颜色区分,以及尺寸区分。

m0_53961910的博客 7098

缓存之SpringCache整合redis(五)

springCache并没有对写模式进行特别的配置和处理,要根据不同的场景进行不同的操作。因为默认缓存,存的是JDK序列化的内容,如果我们要想存JSON怎么办呢?加随机时间 (time-to-live: 60000)。加锁 @Cacheable(sync = true)。:不影响方法执行,更新缓存。:共享缓存配置(类级别)。大量并发查询过期的缓存。查询为null的数据。

酷酷的馫博客 2309

Qt QWebEngine实战:手把手教你将Vue3/React前端项目嵌入C++桌面程序

本文详细介绍了如何利用Qt的QWebEngine模块将Vue3/React前端项目无缝嵌入C++桌面程序,实现现代前端框架与原生C++的深度整合。通过环境准备、项目架构设计、前端适配、Qt端集成、双向通信建立及性能优化等步骤,开发者可以高效构建兼具Web灵活性和本地系统能力的混合应用。

weixin_28736355的博客 391

Spring caching使用及整合Redis

springBoot caching 使用及redis 整合

819

AI人工智能代理工作流 AI Agent WorkFlow:在股票市场预测中的应用

AI人工智能代理工作流 AI Agent WorkFlow:在股票市场预测中的应用 作者:禅与计算机程序设计艺术 / Zen and the Art of Computer Programming 关键词: AI Agent, W

AI天才研究院 859

Pyinstaller打包为可执行文件编码错误的问题

Pyinstaller打包为可执行文件编码错误的问题 写好的python程序在vscode上运行没有任何问题,将程序利用pyinstaller打包后,运行程序发生了错误。 错误代码 UnicodeDecodeError: ‘utf-8' codec can't decode byte 0xce in position 20-21:invalid cotinuation byte 网上找到的解决方案是: 1.在命令行中输入 chcp 65001 2.按正常方式进行封装 pyinstaller

xuefeng_he的博客 1560

优雅的缓存解决方案--SpringCache和Redis集成(SpringBoot)

1. 前言 一个系统在于数据库交互的过程中,内存的速度远远快于硬盘速度,当我们重复地获取相同数据时,我们一次又一次地请求数据库或远程服务,者无疑时性能上地浪费(这会导致大量时间被浪费在数据库查询或者远程方法调用上致使程序性能恶化),于是有了“缓存”。 本文将介绍在spring boot项目开发中怎样使用spring提供的Spring Cache 与最近很火的 Redis 数据库来实现数据的缓存。 ...

米奇罗 1万+

电磁场仿真软件:COMSOL Multiphysics_(17).时域与频域分析

时域和频域分析是电磁场仿真中非常重要的两种方法,每种方法都有其独特的应用场景和优势。时域分析适用于瞬态响应和宽带信号的分析,而频域分析则适用于稳态响应和窄带信号的分析。在COMSOL Multiphysics中,通过合理设置物理场接口、材料属性、边界条件、网格划分和求解器,可以高效地进行这两种分析,并通过傅里叶变换将时域结果转换为频域结果,进一步拓展仿真应用的范围。合理的性能优化措施,如网格划分优化和并行计算,可以显著提高仿真的效率和准确性。

kkchenjj的博客 1978

SpringCache 集成 Redis,这才是优雅的缓存解决方案!

缓存可以说是加速服务响应速度的一种非常有效并且简单的方式。在缓存领域,有很多知名的框架,如EhCache 、Guava、HazelCast等。 Redis作为key-value型数据库,由于他的这一特性,Redis也成为一种流行的数据缓存工具。 在传统方式下对于缓存的处理代码是非常臃肿的。 例如:我们要把一个查询函数加入缓存功能,大致需要三步。 在函数执行前,我们需要先检查缓存中是否存在数据,如果存在则返回缓存数据 如果不存在,就需要在数据库的数据查询出来。 最后把数据存放在

是小木呀 350

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

redis spring 切面缓存_SpringCache与redis集成,优雅的缓存解决方案

缓存可以说是加速服务响应速度的一种非常有效并且简单的方式。在缓存领域,有很多知名的框架,如EhCache 、Guava、HazelCast等。Redis作为key-value型数据库,由于他的这一特性,Redis也成为一种流行的数据缓存工具。在传统方式下对于缓存的处理代码是非常臃肿的。例如:我们要把一个查询函数加入缓存功能,大致需要三步。在函数执行前,我们需要先检查缓存中是否存在数据,如果存在则返...

weixin_42501956的博客 119

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

上一篇: 天天在用Stream,那你知道如此强大的Stream的实现原理吗?
下一篇: 支付宝的架构到底有多牛逼?
Java思维导图
博客等级 码龄10年 306粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值