Redis的集成和简单使用

姓名:王玉刚       学号:17021211232

【嵌牛导读】:利用Mybatis-Plus这个第三方的ORM框架进行数据库访问,在实际工作中,在存储一些非结构化或者缓存一些临时数据及热点数据时,一般上都会用上mongodb和redis进行这方面的需求。所以这一章节准备讲下缓存数据库Redis的集成,同时会介绍下基于Redis和注解驱动的Spring Cache的简单使用。

【嵌牛鼻子】:Redis  SpringBoot

【嵌牛提问】:SpringBoot还有其他的相关软件集成吗?

【嵌牛正文】:SpringBoot的Redis集成

1.pom依赖

org.springframework.bootspring-boot-starter-data-redis

直接引入,相关依赖会自动加载的,这就是springboot让人愉悦之处呀。

2.application.properties配置加入redis相关配置

配置自动加载类为:org.springframework.boot.autoconfigure.data.redis.RedisProperties,可在属性文件中点击某属性快捷跳转。注意到其启动类为org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration。这里就不介绍了,后面会写一篇关于Springboot自动加载配置的文章。

# REDIS (RedisProperties)# Redis数据库索引(默认为0)spring.redis.database=0# Redis服务器地址spring.redis.host=127.0.0.1# Redis服务器连接端口spring.redis.port=6379# Redis服务器连接密码(默认为空)spring.redis.password=# 连接池最大连接数(使用负值表示没有限制)spring.redis.pool.max-active=8# 连接池最大阻塞等待时间(使用负值表示没有限制)spring.redis.pool.max-wait=-1# 连接池中的最大空闲连接spring.redis.pool.max-idle=8# 连接池中的最小空闲连接spring.redis.pool.min-idle=0# 连接超时时间(毫秒)spring.redis.timeout=0

3.一般上通过以上两步就可使用了,但工作中一般上是通过StringRedisTemplate(默认采用string的序列化,保存key和值时都是通过此序列化策略)接口进行操作,所以这里直接配置了StringRedisTemplatebean类。 

/** *  *@authoroKong * */@ConfigurationpublicclassRedisConfig{/**    *  定义 StringRedisTemplate ,指定序列化和反序列化的处理类    *@paramfactory    *@return*/@BeanpublicRedisTemplateredisTemplate(RedisConnectionFactory factory){        StringRedisTemplate template =newStringRedisTemplate(factory);        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer =newJackson2JsonRedisSerializer<>(                Object.class);        ObjectMapper om =newObjectMapper();        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);        jackson2JsonRedisSerializer.setObjectMapper(om);//序列化 值时使用此序列化方法template.setValueSerializer(jackson2JsonRedisSerializer);        template.afterPropertiesSet();returntemplate;    }}

4.编写控制类,测试集成是否生效。

@RestController@RequestMapping("/redis")@Api(tags ="redis 测试API")publicclassRedisController{@AutowiredStringRedisTemplate redisTemplate;@GetMapping("set/{key}/{value}")@ApiOperation(value="设置缓存")publicStringset(@PathVariable("key")String key,@PathVariable("value")String value){//注意这里的 key不能为null spring 内部有检验redisTemplate.opsForValue().set(key, value);returnkey +","+ value;}@GetMapping("get/{key}")@ApiOperation(value="根据key获取缓存")publicStringget(@PathVariable("key")String key){return"key="+ key +",value="+ redisTemplate.opsForValue().get(key);}}

5.set值 

get值 

查看redis记录:

至此,redis就集成好了。实际中可根据业务需要进行相关操作,比如缓存session记录,缓存菜单列表等。

Spring Cache 和 redis 使用。

Spring Cache是Spring框架提供的对缓存使用的抽象类,支持多种缓存,比如Redis、EHCache等,集成很方便。同时提供了多种注解来简化缓存的使用,可对方法进行缓存。

0.修改RedisConfig配置类,加入注解@EnableCaching,同时设置CacheManager缓存管理类,这里使用RedisCacheManager,其他的管理类还有:SimpleCacheManager、ConcurrentMapCacheManager等,默认提供的在类org.springframework.cache.support下,可自行查阅。

/** *  *@authoroKong * */@Configuration@EnableCachingpublicclassRedisConfig{/**    *  定义 StringRedisTemplate ,指定序列号和反序列化的处理类    *@paramfactory    *@return*/@BeanpublicRedisTemplateredisTemplate(RedisConnectionFactory factory){        StringRedisTemplate template =newStringRedisTemplate(factory);        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer =newJackson2JsonRedisSerializer<>(                Object.class);        ObjectMapper om =newObjectMapper();        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);        jackson2JsonRedisSerializer.setObjectMapper(om);//序列化 值时使用此序列化方法template.setValueSerializer(jackson2JsonRedisSerializer);        template.afterPropertiesSet();returntemplate;    }@BeanpublicCacheManagercacheManager(RedisTemplate redisTemplate){        RedisCacheManager rcm =newRedisCacheManager(redisTemplate);//使用前缀rcm.setUsePrefix(true);//缓存分割符 默认为 ":"//        rcm.setCachePrefix(new DefaultRedisCachePrefix(":"));//设置缓存过期时间//rcm.setDefaultExpiration(60);//秒returnrcm;    }}

1.改造UserController控制层,引入@Cacheable等注解。

/** * 用户控制层 简单演示增删改查及分页 * 新增了swagger文档内容 2018-07-21 * 新增了@caching使用 2018-07-23 *@authoroKong * */@RestController@RequestMapping("/user")@Api(tags="用户API")publicclassUserController{@AutowiredIUserService userService;@PostMapping("add")@ApiOperation(value="用户新增")//正常业务时, 需要在user类里面进行事务控制,控制层一般不进行业务控制的。//@Transactional(rollbackFor = Exception.class)publicMapaddUser(@Valid @RequestBody UserReq userReq){                User user =newUser();        user.setCode(userReq.getCode());        user.setName(userReq.getName());//由于设置了主键策略 id可不用赋值 会自动生成//user.setId(0L);userService.insert(user);        Map result =newHashMap();        result.put("respCode","01");        result.put("respMsg","新增成功");//事务测试//System.out.println(1/0);returnresult;    }@PostMapping("update")@ApiOperation(value="用户修改")//更新时 直接删除缓存 以保证下次获取时先从数据库中获取最新数据@CacheEvict(value="OKONG", key="#userReq.id")publicMapupdateUser(@Valid @RequestBody UserReq userReq){if(userReq.getId() ==null||"".equals(userReq.getId())) {thrownewCommonException("0000","更新时ID不能为空");        }        User user =newUser();        user.setCode(userReq.getCode());        user.setName(userReq.getName());        user.setId(Long.parseLong(userReq.getId()));                userService.updateById(user);        Map result =newHashMap();        result.put("respCode","01");        result.put("respMsg","更新成功");returnresult;    }@GetMapping("/get/{id}")@ApiOperation(value="用户查询(ID)")@ApiImplicitParam(name="id",value="查询ID",required=true)@Cacheable(value="OKONG",key="#id")publicMapgetUser(@PathVariable("id")String id){//查询User user = userService.selectById(id);if(user ==null) {thrownewCommonException("0001","用户ID:"+ id +",未找到");        }        UserResp resp = UserResp.builder()                .id(user.getId().toString())                .code(user.getCode())                .name(user.getName())                .status(user.getStatus())                .build();        Map result =newHashMap();        result.put("respCode","01");        result.put("respMsg","成功");        result.put("data", resp);returnresult;    }@GetMapping("/page")@ApiOperation(value="用户查询(分页)")publicMappageUser(intcurrent,intsize){//分页Page page =newPage<>(current, size);        Map result =newHashMap();        result.put("respCode","01");        result.put("respMsg","成功");        result.put("data", userService.selectPage(page));returnresult;    }        }

2.利用Swagger控制页面,新增一个用户,然后获取用户,会发现缓存里已经有此id的用户数据了。

redis查看: 

再次获取,会发现这次没有直接访问数据库了,而是直接从缓存读取。大家可在观察下控制台的输出情况(可先清空控制台,然后在请求)。

 此时控制台无任何输出,但前端已经获取到值了。

关于SpringCache 注解的简单介绍

@Cacheable:标记在一个方法上,也可以标记在一个类上。主要是缓存标注对象的返回结果,标注在方法上缓存该方法的返回值,标注在类上,缓存该类所有的方法返回值。 参数: value缓存名、 key缓存键值、 condition满足缓存条件、unless否决缓存条件

@CacheEvict:从缓存中移除相应数据。

@CachePut:方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

@Caching:多个Cache注解使用,比如新增用户时,删除用户属性等需要删除或者更新多个缓存时,集合以上三个注解。

SpEL上下文数据

Spring Cache提供了一些供我们使用的SpEL上下文数据,下表直接摘自互联网

名称位置描述示例

methodNameroot对象当前被调用的方法名root.methodName

methodroot对象当前被调用的方法root.method.name

targetroot对象当前被调用的目标对象root.target

targetClassroot对象当前被调用的目标对象类root.targetClass

argsroot对象当前被调用的方法的参数列表root.args[0]

cachesroot对象当前方法调用使用的缓存列表(如@Cacheable(value={“cache1”, “cache2”})),则有两个cacheroot.caches[0].name

argument name执行上下文当前被调用的方法的参数,如findById(Long id),我们可以通过#id拿到参数user.id

result执行上下文方法执行后的返回值(仅当方法执行之后的判断有效,如‘unless’,’cache evict’的beforeInvocation=false)result

@CacheEvict(value ="user", key ="#user.id", condition ="#root.target.canCache() and #root.caches[0].get(#user.id).get().username ne #user.username", beforeInvocation =true)publicvoidconditionUpdate(User user)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 放弃一个人,从来都不是一瞬间的事,当全部的爱慕和关心一点点被消磨干净,我也渐渐的攒够了失望和无奈。当初那么喜欢,现...
    灰太狼爱美羊羊1108阅读 212评论 0 0
  • 1.减少购买欲,不买不需要之物 2.减少使用社交网络 3.定期整理房间 4.作息规律 5.穿着简洁,不花哨
    简单215阅读 247评论 0 0
  • 这是个人气还不错的幼儿画画培训机构,离我家挺远,我和老公考察了两个类似的培训机构之后选择了这家,怎么说呢,对于我和...
    山下一支竹阅读 122评论 0 0