zoukankan      html  css  js  c++  java
  • SSM之整合Redis

    Redis安装与使用

    第一步当然是安装Redis,这里以Windows上的安装为例。

    • 首先下载Redis,可以选择msi或zip包安装方式
    • zip方式需打开cmd窗口,在解压后的目录下运行redis-server redis.windows.conf启动Redis
    • 采用msi方式安装后Redis默认启动,不需要进行任何配置
    • 可以在redis.windows.conf文件中修改Redis端口号、密码等配置,修改完成后使用redis-server redis.windows.conf命令重新启动
    • 在Redis安装目录下执行redis-cli -h 127.0.0.1 -p 6379 -a 密码打开Redis操作界面
    • 如果报错(error) ERR operation not permitted,使用auth 密码进行验证

    SSM整合Redis

    这里直接在上一篇SSM之框架整合的基础上进行Redis整合,这里需要注意,存入Redis的pojo类必须实现Serializable接口

    配置pom.xml引入Redis依赖

    <!--redis-->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
        <version>1.6.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.7.3</version>
    </dependency>
    

    redis.properties

    redis.host=127.0.0.1
    redis.port=6379
    redis.password=redis
    redis.maxIdle=100
    redis.maxWait=1000
    redis.testOnBorrow=true
    redis.timeout=100000
    defaultCacheExpireTime=3600
    

    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:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd">
    
        <!--引入Redis配置文件-->
        <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations">
                <list>
                    <value>classpath:redis.properties</value>
                </list>
            </property>
        </bean>
    
        <!-- jedis 连接池配置 -->
        <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>
        <!-- redis连接工厂 -->
        <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
            <property name="poolConfig" ref="poolConfig"/>
            <property name="port" value="${redis.port}"/>
            <property name="hostName" value="${redis.host}"/>
            <property name="password" value="${redis.password}"/>
            <property name="timeout" value="${redis.timeout}"></property>
        </bean>
        <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
            <property name="connectionFactory" ref="connectionFactory"/>
            <property name="keySerializer">
                <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
            </property>
            <property name="valueSerializer">
                <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
            </property>
        </bean>
        <!-- 缓存拦截器配置 -->
        <bean id="methodCacheInterceptor" class="com.zkh.interceptor.MethodCacheInterceptor">
            <property name="redisUtil" ref="redisUtil"/>
            <property name="defaultCacheExpireTime" value="${defaultCacheExpireTime}"/>
            <!-- 禁用缓存的类名列表 -->
            <property name="targetNamesList">
                <list>
                    <value></value>
                </list>
            </property>
            <!-- 禁用缓存的方法名列表 -->
            <property name="methodNamesList">
                <list>
                    <value></value>
                </list>
            </property>
        </bean>
        <bean id="redisUtil" class="com.zkh.util.RedisUtil">
            <property name="redisTemplate" ref="redisTemplate"/>
        </bean>
        <!--配置切面拦截方法 -->
        <aop:config proxy-target-class="true">
            <aop:pointcut id="controllerMethodPointcut" expression="
            execution(* com.zkh.service.impl.*.select*(..))"/>
            <aop:advisor advice-ref="methodCacheInterceptor" pointcut-ref="controllerMethodPointcut"/>
        </aop:config>
    </beans>
    

    MethodCacheInterceptor.java

    package com.zkh.interceptor;
    
    import com.zkh.util.RedisUtil;
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    
    import java.util.List;
    
    /**
     * Redis缓存过滤器
     */
    public class MethodCacheInterceptor implements MethodInterceptor {
        private RedisUtil redisUtil;
        private List<String> targetNamesList; // 禁用缓存的类名列表
        private List<String> methodNamesList; // 禁用缓存的方法列表
        private String defaultCacheExpireTime; // 缓存默认的过期时间
    
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            Object value = null;
    
            String targetName = invocation.getThis().getClass().getName();
            String methodName = invocation.getMethod().getName();
            if (!isAddCache(targetName, methodName)) {
                // 跳过缓存返回结果
                return invocation.proceed();
            }
            Object[] arguments = invocation.getArguments();
            String key = getCacheKey(targetName, methodName, arguments);
            try {
                // 判断是否有缓存
                if (redisUtil.exists(key)) {
                    return redisUtil.get(key);
                }
                // 写入缓存
                value = invocation.proceed();
                if (value != null) {
                    final String tkey = key;
                    final Object tvalue = value;
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            redisUtil.set(tkey, tvalue, Long.parseLong(defaultCacheExpireTime));
                        }
                    }).start();
                }
            } catch (Exception e) {
                e.printStackTrace();
                if (value == null) {
                    return invocation.proceed();
                }
            }
            return value;
        }
    
        /**
         * 是否加入缓存
         *
         * @return
         */
        private boolean isAddCache(String targetName, String methodName) {
            boolean flag = true;
            if (targetNamesList.contains(targetName)
                    || methodNamesList.contains(methodName) || targetName.contains("$$EnhancerBySpringCGLIB$$")) {
                flag = false;
            }
            return flag;
        }
    
        /**
         * 创建缓存key
         *
         * @param targetName
         * @param methodName
         * @param arguments
         */
        private String getCacheKey(String targetName, String methodName,
                                   Object[] arguments) {
            StringBuffer sbu = new StringBuffer();
            sbu.append(targetName).append("_").append(methodName);
            if ((arguments != null) && (arguments.length != 0)) {
                for (int i = 0; i < arguments.length; i++) {
                    sbu.append("_").append(arguments[i]);
                }
            }
            return sbu.toString();
        }
    
        public void setRedisUtil(RedisUtil redisUtil) {
            this.redisUtil = redisUtil;
        }
    
        public void setTargetNamesList(List<String> targetNamesList) {
            this.targetNamesList = targetNamesList;
        }
    
        public void setMethodNamesList(List<String> methodNamesList) {
            this.methodNamesList = methodNamesList;
        }
    
        public void setDefaultCacheExpireTime(String defaultCacheExpireTime) {
            this.defaultCacheExpireTime = defaultCacheExpireTime;
        }
    }
    

    RedisUtil.java 工具类

    package com.zkh.util;
    
    import org.apache.log4j.Logger;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.ValueOperations;
    
    import java.io.Serializable;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;
    
    /**
     * Redis工具类
     */
    public class RedisUtil {
        private RedisTemplate<Serializable, Object> redisTemplate;
    
        /**
         * 批量删除对应的value
         *
         * @param keys
         */
        public void remove(final String... keys) {
            for (String key : keys) {
                remove(key);
            }
        }
    
        /**
         * 批量删除key
         *
         * @param pattern
         */
        public void removePattern(final String pattern) {
            Set<Serializable> keys = redisTemplate.keys(pattern);
            if (keys.size() > 0)
                redisTemplate.delete(keys);
        }
    
        /**
         * 删除对应的value
         *
         * @param key
         */
        public void remove(final String key) {
            if (exists(key)) {
                redisTemplate.delete(key);
            }
        }
    
        /**
         * 判断缓存中是否有对应的value
         *
         * @param key
         * @return
         */
        public boolean exists(final String key) {
            return redisTemplate.hasKey(key);
        }
    
        /**
         * 读取缓存
         *
         * @param key
         * @return
         */
        public Object get(final String key) {
            Object result = null;
            ValueOperations<Serializable, Object> operations = redisTemplate
                    .opsForValue();
            result = operations.get(key);
            return result;
        }
    
        /**
         * 写入缓存
         *
         * @param key
         * @param value
         * @return
         */
        public boolean set(final String key, Object value) {
            boolean result = false;
            try {
                ValueOperations<Serializable, Object> operations = redisTemplate
                        .opsForValue();
                operations.set(key, value);
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 写入缓存
         *
         * @param key
         * @param value
         * @return
         */
        public boolean set(final String key, Object value, Long expireTime) {
            boolean result = false;
            try {
                ValueOperations<Serializable, Object> operations = redisTemplate
                        .opsForValue();
                operations.set(key, value);
                redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    
        public void setRedisTemplate(
                RedisTemplate<Serializable, Object> redisTemplate) {
            this.redisTemplate = redisTemplate;
        }
    }
    

    效果展示

    刚开始Redis中没有任何记录,接下来访问一下第一页记录

    再查看缓存,记录已经存如Redis,并且第一次访问会从Mysql中读取数据

    F5刷新页面,从Tomcat控制台可以看到没有进行SQL查询,而是直接从Redis中读取缓存数据,减轻了数据库的负担

    具体代码已发布在Github上,地址:SSM

    本文为作者kMacro原创,转载请注明来源:http://www.jianshu.com/p/7fecfad2970c。

  • 相关阅读:
    【大厂面试】字节跳动、京东等大厂面试题分享,已拿字节offer~
    听说这十道面试题,把百分之八十的程序员都淘汰了?不是吧,阿sir
    阿里大神的刷题笔记.pdf
    在家学了6个月,拿到阿里offer!
    【面试题】2020年底总结200道带答案的常见Java面试题!
    面试一家小公司,被问了 1 个小时并发编程。。全程已记录!
    分享一份技术书籍《Java 8 》PDF版,可自行下载
    Delphi的TDataSetProvider、TDataSet、TAdoQuery、TDataSource、TDataModule控件的组合使用
    初学Delphi与sql server的存储过程
    delphi简单的分页实现(高手可以不看)
  • 原文地址:https://www.cnblogs.com/zkh101/p/7612021.html
Copyright © 2011-2022 走看看