RedisTemplate在项目中的应用

RedisTemplate在项目中的应用

如下主要通去年无聊做的 "涂涂影院后台管理系统" 一个 demo,看 RedisTemplate 的使用。

主要用到地方:视频首页轮播图的获取,以及搜索检索界面,如下图所示:


由于是非maven非springboot项目,故配置有所繁琐,但正所谓有繁才有简,在下面会带大家看一下springboot中配置redis是怎样简单。

好了,先回到 "涂涂影院" 来吧。

本项目环境

开发工具:Eclipse

JDK:1.8

Redis;

eclipse中截图eclipse中截图

相信非springboot项目里的配置大家都应该很熟悉吧,主要就是配置繁琐的 xml,搭建一个 ssm 项目可参考之前的例子:SSM(Spring+SpringMVC+Mybatis)框架环境搭建

1、spring-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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd 
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd"
>


    <!-- 缓存的层级-->
     <context:component-scan base-package="com.jeenotes.common.cache" />

     <!-- 配置 读取properties文件 jeenotes.properties -->
    <context:property-placeholder location="classpath:resources/jeenotes.properties"  ignore-unresolvable="true"/>

    <!-- Redis 配置 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!-- 控制一个pool可分配多少个jedis实例 -->
        <property name="maxTotal" value="${redis.pool.maxTotal}" /><!--  -->
        <!-- 连接池中最多可空闲maxIdle个连接 ,这里取值为20,表示即使没有数据库连接时依然可以保持20空闲的连接,
               而不被清除,随时处于待命状态。 -->

        <property name="maxIdle" value="${redis.pool.maxIdle}" /><!--  -->
        <!-- 最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以毫秒计数),超过时间则抛出异常 -->
        <property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}" /><!--  -->
        <!-- 在获取连接的时候检查有效性 -->
        <property name="testOnBorrow" value="${redis.pool.testOnBorrow}" /><!--  -->
    </bean>


    <!-- redis单节点数据库连接配置 -->
    <!-- Spring-redis连接池管理工厂 -->  
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.ip}" /><!--  -->
        <property name="port" value="${redis.port}" /><!--  -->
        <property name="password" value="${redis.pass}" /><!--  -->
        <property name="poolConfig" ref="jedisPoolConfig" />
    </bean> 

    <!-- redisTemplate配置,redisTemplate是对Jedis的对redis操作的扩展,有更多的操作,
           封装使操作更便捷 -->

    <!-- SDR默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。
        StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。
        RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。
                    就是因为序列化策略的不同,即使是同一个key用不同的Template去序列化,结果是不同的。
                    所以根据key去删除数据的时候就出现了删除失败的问题。 
     -->

    <!-- redis 序列化策略 ,通常情况下key值采用String序列化策略, -->
    <!-- 如果不指定序列化策略,StringRedisTemplate的key和value都将采用String序列化策略; -->
    <!-- 但是RedisTemplate的key和value都将采用JDK序列化 这样就会出现采用不同template保存的数据不能用同一个template删除的问题 -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <!-- 我们通常所用的序列化操作:
                JDK的序列化——类上implements Serializable接口
                XML和Json
                protocol buffer(简称protobuf)Google的、 本项目采用中-->

        <!-- <property name="keySerializer" ref="stringRedisSerializer" />
        <property name="hashKeySerializer" ref="stringRedisSerializer" />
        <property name="valueSerializer" ref="stringRedisSerializer"/> -->


    </bean>

</beans>

注释比较详细,简要概述,jedisPoolConfig 用来配置 redis 连接池的一些配置,JedisConnectionFactory 则作为连接池的工厂类;还记得上文中提到的 redis 序列化问题吗?上边配置中(StringRedisTemplate)正是用到了 String 序列化策略。

2、RedisCache.java

/**
 * redis缓存
 * 
 * @author niceyoo
 *
 */

@Component
public class RedisCache {


    public final static String CAHCENAME="cache";//缓存名
    public final static int CAHCETIME=300;//默认缓存时间   以秒计算的

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public <T> boolean putCache(String key, T obj) {
        final byte[] bkey = key.getBytes();
        final byte[] bvalue = ProtoStuffSerializerUtil.serialize(obj);
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.setNX(bkey, bvalue);
            }
        });
        return result;
    }

    public <T> void putCacheWithExpireTime(String key, T obj, final long expireTime) {
        final byte[] bkey = key.getBytes();
        final byte[] bvalue = ProtoStuffSerializerUtil.serialize(obj);
        redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                connection.setEx(bkey, expireTime, bvalue);
                return true;
            }
        });
    }

    public <T> boolean putListCache(String key, List<T> objList) {
        final byte[] bkey = key.getBytes();
        final byte[] bvalue = ProtoStuffSerializerUtil.serializeList(objList);
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.setNX(bkey, bvalue);
            }
        });
        return result;
    }

    public <T> boolean putListCacheWithExpireTime(String key, List<T> objList, final long expireTime) {
        final byte[] bkey = key.getBytes();
        final byte[] bvalue = ProtoStuffSerializerUtil.serializeList(objList);
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                connection.setEx(bkey, expireTime, bvalue);
                return true;
            }
        });
        return result;
    }

    public <T> getCache(final String key, Class<T> targetClass) {
        byte[] result = redisTemplate.execute(new RedisCallback<byte[]>() {
            @Override
            public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.get(key.getBytes());
            }
        });
        if (result == null) {
            return null;
        }
        return ProtoStuffSerializerUtil.deserialize(result, targetClass);
    }

    public <T> List<T> getListCache(final String key, Class<T> targetClass) {
        byte[] result = redisTemplate.execute(new RedisCallback<byte[]>() {
            @Override
            public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.get(key.getBytes());
            }
        });
        if (result == null) {
            return null;
        }
        return ProtoStuffSerializerUtil.deserializeList(result, targetClass);
    }

    /**
     * 精确删除key
     * 
     * @param key
     */

    public void deleteCache(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 模糊删除key
     * 
     * @param pattern
     */

    public void deleteCacheWithPattern(String pattern) {
        Set<String> keys = redisTemplate.keys(pattern);
        redisTemplate.delete(keys);
    }

    /**
     * 清空所有缓存
     */

    public void clearCache() {
        deleteCacheWithPattern(RedisCache.CAHCENAME+"|*");
    }
}

RedisCache.java 实现了对对数据增删改查的几种方法,如何使用呢?

我们以首页的轮播图为例:

在需要使用的类中注入该组件:

看一下如下方法:

@ResponseBody
@RequestMapping("huandeng")
public ResultMobileBannerBean huandeng(Model model) {

    String cache_key = RedisCache.CAHCENAME + "|getPcHomeHuanDengList";
    ResultMobileBannerBean result_cache = cache.getCache(cache_key, ResultMobileBannerBean.class);

    if(result_cache != null){
        return result_cache;
    }

    ResultMobileBannerBean bannerBean = new ResultMobileBannerBean();
    bannerBean.setCode("000000");
    List<HomeBanner> homeBannerList = homeManagerService.findMobileHomeBannerList();
    bannerBean.setBannerList(homeBannerList);
    cache.putCacheWithExpireTime(cache_key, bannerBean, RedisCache.CAHCETIME);

    return bannerBean;
}

主要是 ResultMobileBannerBean result_cache = cache.getCache(cache_key, ResultMobileBannerBean.class); 在去数据库请求数据之前,先去 redis 中读取缓存信息,如果返回的数据非空的话,则返回该数据,否则去数据库查询数据,查询后在存放在 redis 中。

项目源码:https://gitee.com/niceyoo/jeenotes-ssm.git


springboot 中是如何引用 redis 的呢?

1、maven依赖

<!-- Redis-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
<!-- Gson 可暂时忽略-->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.5</version>
</dependency>

2、yml配置信息

spring:
  # Redis
  redis:
    host: 127.0.0.1
    password:
    # 数据库索引 默认0
    database: 0
    port: 6379
    # 超时时间 Duration类型 3秒
    timeout: 3S

3、项目中引用

@Autowired
private StringRedisTemplate redisTemplate;

@RequestMapping(value = "/getByParentId/{parentId}", method = RequestMethod.GET)
@ApiOperation(value = "通过parentId获取")
public Result<List<Department>> getByParentId(@PathVariable String parentId,
                                              @ApiParam("是否开始数据权限过滤"@RequestParam(required = false, defaultValue = "true") Boolean openDataFilter){

    List<Department> list = new ArrayList<>();
    User u = securityUtil.getCurrUser();
    String key = "department::"+parentId+":"+u.getId()+"_"+openDataFilter;
    String v = redisTemplate.opsForValue().get(key);
    if(StrUtil.isNotBlank(v)){
        list = new Gson().fromJson(v, new TypeToken<List<Department>>(){}.getType());
        return new ResultUtil<List<Department>>().setData(list);
    }
    list = departmentService.findByParentIdOrderBySortOrder(parentId, openDataFilter);
    list = setInfo(list);
    redisTemplate.opsForValue().set(key,
            new GsonBuilder().registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY).create().toJson(list));
    return new ResultUtil<List<Department>>().setData(list);
}

RedisTemplate 定义了 5 种数据结构操作:

  1. redisTemplate.opsForValue();//操作字符串
  2. redisTemplate.opsForHash();//操作hash
  3. redisTemplate.opsForList();//操作list
  4. redisTemplate.opsForSet();//操作set
  5. redisTemplate.opsForZSet();//操作有序set

最优补充

从上文可看出 RedisTemplate 在 springboot 中应用尤为简单,所以赶快切到 springboot 中吧~

如果文章有错的地方欢迎指正,大家互相留言交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:niceyoo

posted @ 2019-05-07 23:47 niceyoo 阅读(...) 评论(...) 编辑 收藏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/414474.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 蓝牙开发,搜索蓝牙列表,蓝牙连接,蓝牙通讯

申请打开蓝牙 <!-- 蓝牙权限 --> <uses-permission android:name"android.permission.BLUETOOTH" /> <uses-permission android:name"android.permission.BLUETOOTH_ADMIN" />private final int BLUE_REQUEST_CODE 551; public void s…

jeecg uedit 自定义图片上传路径

jeecg uedit 图片上传配置自定义物理路径&#xff0c;简单描述&#xff1a;我们知道 jeecg 中使用的 uedit 默认图片上传路径为 “当前项目\plug-in\ueditor\jsp\uploadx\日期\图片.png”&#xff0c;但是把图片放在项目中显然是很不友好的&#xff0c;所以我们自定义上传路径。…

了解一下Elasticsearch的基本概念

了解一下Elasticsearch的基本概念 一、前文介绍 Elasticsearch&#xff08;简称ES&#xff09;是一个基于Apache Lucene(TM)的开源搜索引擎&#xff0c;无论在开源还是专有领域&#xff0c;Lucene 可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。注意&#x…

简单的对象定位与登录实例的简单操作

①元素对应的定位方法&#xff1a; ②登录实例&#xff08;暂不考虑验证环节&#xff09; 注意&#xff1a;在实践过程中出现过&#xff0c;密码输入之后又被清空的情况&#xff0c;应该是被处理过&#xff0c;换个别的简单的登录界面试下看看如果没有出现前面所说的情况&#…

百度OCR文字识别API使用心得 com.baidu.ocr.sdk.exception.SDKError[283604]

百度OCR文字识别API使用心得 com.baidu.ocr.sdk.exception.SDKError[283604] 本文转载自好基友upuptop&#xff1a;https://blog.csdn.net/pyfysf/article/details/77455330 效果图&#xff1a; 如下为文章正文&#xff1a; 最近有个小项目使用到了OCR技术&#xff0c;顺便到网…

Android studio ERROR: Software caused connection abort: recv failed 解决方法

使用Android studio打开kotlin项目时报错&#xff1a;ERROR: Software caused connection abort: recv failed 解决方法&#xff1a;修改三个文件即可 1、修改gradle-wrapper.properties 修改为当前Android studio的gradle版本 2、修改项目build.gradle 修改为当前Android st…

Android获取手机联系人或通讯录的基本信息(如姓名、电话)

1、添加权限 <uses-permission android:name"android.permission.READ_CONTACTS"/> <uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name"android.permission.READ_EXTERNAL…

百度OCR文字识别-Android安全校验

百度OCR文字识别-Android安全校验 本文转载自好基友upuptop&#xff1a;https://blog.csdn.net/pyfysf/article/details/86438769 效果图&#xff1a; 如下为文章正文&#xff1a; 百度OCR接口使用总结&#xff1a;之前总结一下关于百度OCR文字识别接口的使用步骤&#xff08;…

Android vector矢量图应用实例

在drawable文件夹下创建vector.xml文件 <?xml version"1.0" encoding"utf-8"?> <vector xmlns:android"http://schemas.android.com/apk/res/android"android:height"64dp"android:width"64dp"android:viewpo…

Lint found fatal errors while assembling a release target

在打包APK时报错&#xff1a;Lint found fatal errors while assembling a release target Android在debug模式下应用没有问题&#xff0c;但是在打包release版本时出现一下问题&#xff1a; 解决方法&#xff1a; 1、打开app下build文件夹下reports文件夹下的lint-results-rel…

自定义注解-aop实现日志记录

关于注解&#xff0c;平时接触的可不少&#xff0c;像是 Controller、Service、Autowried 等等&#xff0c;不知道你是否有过这种疑惑&#xff0c;使用 Service 注解的类成为我们的业务类&#xff0c;使用 Controller 注解的类就成了请求的控制器&#xff0c;使用 Autowried 注…

JPA EnableJpaAuditing 审计功能

关于自动填充或更新实体中的 CreateDate、CreatedBy 等在之前有一篇 jeecg 默认为空的字段值是如何被填充的? 有提到通过拦截器的方式实现&#xff0c;但是今天带大家了解一下如果使用 JPA 的审计功能是如何简单实现该操作的。 JPA Audit 说明 在 Spring JPA 中&#xff0c;支…

前端学习(2789):改进导航栏并跳转

第一步:动态数据 第二步 页面渲染

Android 图片识别、图像识别

实现效果 基于百度智能云实现的图片识别 实现步骤 1、到百度智能云注册图像识别应用 https://console.bce.baidu.com/ai/?_1574674029784&fromai1#/ai/imagerecognition/overview/index 2、配置ID与key 3、实现demo&#xff1a;https://download.csdn.net/download/meix…

WebSocket 实现前后端通信的笔记

之前在做站内信时&#xff0c;用到了 WebSocket &#xff0c;整理了一些笔记分享如下。 本文基于 SpringBoot 2.1.5&#xff0c;本文不涉及环境搭建。 引入依赖 在 Spring 中要使用 WebSocket 功能&#xff0c;需要在pom中引入依赖&#xff1a; <dependency><groupI…

Android 地图搜索商家,检索关键字(高德地图,百度地图),地址搜索

1、高德地图 实现效果 打印数据 实现步骤&#xff1a; 1、首先去高德开放平台注册应用 高德开放平台&#xff1a;https://lbs.amap.com/ 2、点击 我的应用 ——>设置 注&#xff1a;SHA1获取方法&#xff1a;https://blog.…