点击上方“方志朋”,选择“设为星标”

回复”666“获取新整理的面试文章

来源: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;@Overridepublic void clear() {System.out.println("-------緩存清理------");redisTemplate.execute(new RedisCallback<String>() {@Overridepublic String doInRedis(RedisConnection connection) throws DataAccessException {connection.flushDb();return "ok";}});}@Overridepublic void evict(Object key) {System.out.println("-------緩存刪除------");final String keyf=key.toString();redisTemplate.execute(new RedisCallback<Long>() {@Overridepublic Long doInRedis(RedisConnection connection) throws DataAccessException {return connection.del(keyf.getBytes());}});}@Overridepublic ValueWrapper get(Object key) {System.out.println("------缓存获取-------"+key.toString());final String keyf = key.toString();Object object = null;object = redisTemplate.execute(new RedisCallback<Object>() {@Overridepublic 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;}@Overridepublic 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>() {@Overridepublic 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;}});}@Overridepublic <T> T get(Object arg0, Class<T> arg1) {// TODO Auto-generated method stubreturn null;}@Overridepublic String getName() {return this.name;}@Overridepublic Object getNativeCache() {return this.redisTemplate;}@Overridepublic ValueWrapper putIfAbsent(Object arg0, Object arg1) {// TODO Auto-generated method stubreturn 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指定。搜索Java知音公众号,回复“后端面试”,送你一份Java面试题宝典

如果没有指定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

热门内容:Spring Boot 最流行的 16 条实践解读,值得收藏!Mybatis 框架下 SQL 注入攻击的 3 种方式,真是防不胜防!Java8 快速实现List转map 、分组、过滤等操作
SpringBoot 三招组合拳,手把手教你打出优雅的后端接口
最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ

SpringCache与redis集成,优雅的缓存解决方案相关推荐

  1. 优雅的缓存解决方案--设置过期时间

    1. 前言 上篇文章介绍了利用 SpringCache 和 Redis 设置缓存,但是SpringCache 注解并不支持设置缓存时间,确实很令人头疼.这篇文章将叫你用最简单的方式解决 SpringC ...

  2. Spring Boot之基于Redis实现MyBatis查询缓存解决方案

    转载自 Spring Boot之基于Redis实现MyBatis查询缓存解决方案 1. 前言 MyBatis是Java中常用的数据层ORM框架,笔者目前在实际的开发中,也在使用MyBatis.本文主要 ...

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

    缓存可以说是加速服务响应速度的一种非常有效并且简单的方式.在缓存领域,有很多知名的框架,如EhCache .Guava.HazelCast等. Redis作为key-value型数据库,由于他的这一特 ...

  4. Redis持久化机制及缓存失效解决方案

    Redis集群故障监测及哨兵机制原理解析 Redis海量数据存储方案Redis Cluster 前言 在之前的文章写过redis的实用功能,包括数据结构,主从复制结构,以及应对高并发海量数据场景下的分 ...

  5. 有赞多级缓存解决方案怎么做的,你知道吗?

    一.引子 1-1. TMC 是什么 TMC,即"透明多级缓存(Transparent Multilevel Cache)",是有赞 PaaS 团队给公司内应用提供的整体缓存解决方案 ...

  6. 有赞透明多级缓存解决方案(TMC)设计思路

    引子 TMC 是什么 TMC,即"透明多级缓存(Transparent Multilevel Cache)",是有赞 PaaS 团队给公司内应用提供的整体缓存解决方案. TMC 在 ...

  7. Spring Boot(十一)Redis集成从Docker安装到分布式Session共享

    2019独角兽企业重金招聘Python工程师标准>>> 一.简介 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并 ...

  8. SpringCache与Redis

    文章目录 SpringCache简介 常⽤注解Cacheable 自定义CacheManager配置和过期时间 自定义缓存KeyGenerator 常用注解CachePut 和 CacheEvict ...

  9. redis集成spring_将Redis集成到您的Spring项目中

    redis集成spring 本文介绍如何通过注释配置将Redis缓存集成到您的spring项目中. 我们将从Gradle配置开始. 我们将使用jedis驱动程序. group 'com.gkatzio ...

最新文章

  1. 移动端网站建设——一如既往地简洁大方
  2. Linux日志系统-04:logrotate命令格式
  3. 实战并发编程 - 09多线程Guarded Suspension模式案例实战
  4. 避免入坑:如何知道一个导师的人品?
  5. 【Acwing 219. 剪纸游戏】
  6. 地图大数据来了!中国人口吸引力城市TOP 10
  7. 录制怎么没有耳机设备_录制现场演示,第1部分:选择设备
  8. 【算法】剑指 Offer 58 - I. 翻转单词顺序
  9. asp.net模板控件示例
  10. 直接使用editbox.clear()清空时,有时会无法清除完全,此时有清空文本框的另一种方法...
  11. UVZ转成PDF并添加目录
  12. css配色大全和色彩原理
  13. xadsafe做暗刷_XADsafe去广告热心网友共享规则库部分开源(11月13更新)
  14. 用JavaScript写一个简单的网页倒计时插件
  15. 几个好中的计算机类EI源刊
  16. 育儿心得,所有适龄女青年都该看一下(转)
  17. 机器人SLAM与自主导航——(四)Gazebo仿真机器人导航
  18. quartus II SignalTap 在线调试
  19. 侍魂胧月传说服务器维护,侍魂胧月传说手游7月1日停机维护更新公告
  20. 如何将英文的PDF文档翻译成中文简体?

热门文章

  1. opensuse安装nginx
  2. Hadoop学习之路(三)Hadoop-2.7.5在CentOS-6.7上的编译
  3. Nodejs.热部署方法
  4. JConsole的使用
  5. LPC1768基本输入输出GPIO使用
  6. Cocos2d-x lua 编译到Android设备
  7. mysql的binlog太多太大占用了空间的解决办法
  8. Java 线程 笔记(1)
  9. UpdateDate()函数的作用
  10. 【青少年编程】【蓝桥杯】水仙花数