spring和redis的整合

本文详细介绍如何使用Spring框架整合Redis,包括使用spring-data-redis和直接使用Jedis进行整合的两种方式。通过具体代码示例,展示了如何配置Redis连接池、执行CRUD操作,并提供了完整的项目结构和依赖配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

               

超越昨天的自己系列(7)

 

 扯淡:

 

 最近一直在慢慢多学习各个组件,自己搭建出一些想法。是一个涉猎的过程,慢慢意识到知识是可以融汇贯通举一反三的,不过前提好像是研究的比较深,有了自己的见解。自认为学习能力不咋地,速度慢不说,还容易放弃,大多数时候都是回头捡起来补的那种情况。

 

所以,我想:自我监督的能力是否决定了一个人学习的高度,也限制了见识的高度呢?

 

随着年纪的增长,越来越觉得学习知识的那种迫切性,专业方面的,自我修养方面的,都需要急切的得到满足。我知道很多人其实已经放弃看书了,基本刷刷微博,看看新闻,就满足自己的阅读欲望了。但有时候,静下心来的时候,很自己的心田上什么也没有,后悔自己没种棵树,或掘口井什么的。

 

不知道你们是否有这样的感觉?

 


主题:(以下例子都使用maven构建)

 

redis的知识:官网

 

1,利用spring-data-redis整合

 

项目使用的pom.xml:

 
      
   
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0</modelVersion>  <groupId>com.x.redis</groupId>  <artifactId>Spring_redis</artifactId>  <version>1.0-SNAPSHOT</version>  <packaging>jar</packaging>  <name>Spring_redis</name>  <url>http://maven.apache.org</url>  <properties>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  </properties>  <dependencies>     <dependency>          <groupId>org.springframework.data</groupId>          <artifactId>spring-data-redis</artifactId>          <version>1.0.2.RELEASE</version>      </dependency>      <dependency>          <groupId>org.springframework</groupId>          <artifactId>spring-core</artifactId>          <version>3.1.2.RELEASE</version>      </dependency>            <dependency>          <groupId>redis.clients</groupId>          <artifactId>jedis</artifactId>          <version>2.1.0</version>      </dependency>             <dependency>          <groupId>junit</groupId>          <artifactId>junit</artifactId>          <version>4.8.2</version>          <scope>test</scope>      </dependency>                  <dependency>                <groupId>org.slf4j</groupId>                <artifactId>slf4j-api</artifactId>                <version>1.6.1</version>            </dependency>            <!-- 将现有的jakarta commons logging的调用转换成lsf4j的调用。 -->            <dependency>                <groupId>org.slf4j</groupId>                <artifactId>jcl-over-slf4j</artifactId>                <version>1.6.1</version>            </dependency>            <!-- Hack:确保commons-logging的jar包不被引入,否则将和jcl-over-slf4j冲突 -->            <dependency>                <groupId>commons-logging</groupId>                <artifactId>commons-logging</artifactId>                <version>1.1.1</version>                <scope>provided</scope>            </dependency>            <!-- slf4j的实现:logback,用来取代log4j。更快、更强! -->            <dependency>                <groupId>ch.qos.logback</groupId>                <artifactId>logback-classic</artifactId>                <version>0.9.24</version>                <scope>runtime</scope>            </dependency>  </dependencies></project>
  
   View Code
 

除了log部分,只有一个spring core 和 spring-data-redis了

 

项目文件目录结构:

 

 

 

applicationContext.xml:

 

1,context:property-placeholder 标签用来导入properties文件。从而替换${redis.maxIdle}这样的变量。

 

2,context:component-scan 是为了在com.x.redis.dao报下的类能够实用spring的注解注入的方式。

 

3,事实上我们只需要把JedisPoolConfig配数来就好了,接下来就是spring的封装了。所以直接看UserDAOImpl的实现就明白了。

 
  
<?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:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"      xmlns:aop="http://www.springframework.org/schema/aop"      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:property-placeholder location="classpath:redis.properties" />      <context:component-scan base-package="com.x.redis.dao">    </context:component-scan>    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">          <property name="maxIdle" value="${redis.maxIdle}" />          <property name="maxActive" value="${redis.maxActive}" />          <property name="maxWait" value="${redis.maxWait}" />          <property name="testOnBorrow" value="${redis.testOnBorrow}" />      </bean>            <bean id="connectionFactory" 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"/>            <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">          <property name="connectionFactory"   ref="connectionFactory" />      </bean>                   <bean id="userDAO" class="com.x.redis.dao.impl.UserDAOImpl" />   </beans> 
 
 

redis.properties:

 
      
   
# Redis settings#redis.host=192.168.20.101#redis.port=6380#redis.pass=foobaredredis.host=127.0.0.1redis.port=6379redis.pass=  redis.maxIdle=300redis.maxActive=600redis.maxWait=1000redis.testOnBorrow=true
  
   View Code
 

 

 

UserDAOImpl:

 

1,spring对dao层的封装很多用了类似于下面代码的模板方式。

 

2,RedisTemplate就是spring对redis的一个封装而已。

 
  
public class UserDAOImpl implements UserDAO {    @Autowired    protected RedisTemplate<Serializable, Serializable> redisTemplate;    public void saveUser(final User user) {        redisTemplate.execute(new RedisCallback<Object>() {            @Override            public Object doInRedis(RedisConnection connection) throws DataAccessException {                connection.set(redisTemplate.getStringSerializer().serialize("user.uid." + user.getId()),                               redisTemplate.getStringSerializer().serialize(user.getName()));                return null;            }        });    }    @Override    public User getUser(final long id) {        return redisTemplate.execute(new RedisCallback<User>() {            @Override            public User doInRedis(RedisConnection connection) throws DataAccessException {                byte[] key = redisTemplate.getStringSerializer().serialize("user.uid." + id);                if (connection.exists(key)) {                    byte[] value = connection.get(key);                    String name = redisTemplate.getStringSerializer().deserialize(value);                    User user = new User();                    user.setName(name);                    user.setId(id);                    return user;                }                return null;            }        });    }}
 
 

其他:

 

User:

 
      
   
public class User {    private long id;    private String name;        public long getId() {        return id;    }        public void setId(long id) {        this.id = id;    }        public String getName() {        return name;    }        public void setName(String name) {        this.name = name;    }}
  
   View Code
 

测试代码:

 
  
    public static void main(String[] args) {        ApplicationContext ac =  new ClassPathXmlApplicationContext("classpath:/applicationContext.xml");        UserDAO userDAO = (UserDAO)ac.getBean("userDAO");        User user1 = new User();        user1.setId(1);        user1.setName("obama");        userDAO.saveUser(user1);        User user2 = userDAO.getUser(1);        System.out.println(user2.getName());    }
 
 

 

 

2,不利用spring-data-redis整合

 

个人觉得这样整合灵活度更大,能够更加明了的完成任务。

 

pom.xml:

 
      
   
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0</modelVersion>  <groupId>com.d.work</groupId>  <artifactId>Redis_Templete</artifactId>  <version>1.0-SNAPSHOT</version>  <packaging>jar</packaging>  <name>Redis_Templete</name>  <url>http://maven.apache.org</url>  <properties>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  </properties>  <dependencies>    <dependency>      <groupId>junit</groupId>      <artifactId>junit</artifactId>      <version>3.8.1</version>      <scope>test</scope>    </dependency>    <dependency>          <groupId>redis.clients</groupId>          <artifactId>jedis</artifactId>          <version>2.1.0</version>      </dependency>          <dependency>          <groupId>org.springframework</groupId>          <artifactId>spring-core</artifactId>          <version>3.1.2.RELEASE</version>      </dependency>          <dependency>          <groupId>org.springframework</groupId>          <artifactId>spring-beans</artifactId>          <version>3.1.2.RELEASE</version>      </dependency>         <dependency>          <groupId>org.springframework</groupId>          <artifactId>spring-context</artifactId>          <version>3.1.2.RELEASE</version>      </dependency>     <dependency>                <groupId>org.slf4j</groupId>                <artifactId>slf4j-api</artifactId>                <version>1.6.1</version>            </dependency>            <!-- 将现有的jakarta commons logging的调用转换成lsf4j的调用。 -->            <dependency>                <groupId>org.slf4j</groupId>                <artifactId>jcl-over-slf4j</artifactId>                <version>1.6.1</version>            </dependency>            <!-- Hack:确保commons-logging的jar包不被引入,否则将和jcl-over-slf4j冲突 -->            <dependency>                <groupId>commons-logging</groupId>                <artifactId>commons-logging</artifactId>                <version>1.1.1</version>                <scope>provided</scope>            </dependency>            <!-- slf4j的实现:logback,用来取代log4j。更快、更强! -->            <dependency>                <groupId>ch.qos.logback</groupId>                <artifactId>logback-classic</artifactId>                <version>0.9.24</version>                <scope>runtime</scope>            </dependency>  </dependencies></project>
  
   View Code
 

目录结构:

 

 

data-source.xml

 

1,context:property-placeholder 和 context:component-scan 前面解释过啦。

 

2,配置了一个ShardedJedisPool,在jdeis里 还有个JedisPool。这两个的区别:

 
  一个是分片形式,可以连接有主备的redis服务端,一个是单个的。详细后续学习
 
   
 
  3,因为不使用spring-data-redis的封装,所以自己要自己封装一个
 
  
<?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:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"      xmlns:aop="http://www.springframework.org/schema/aop"      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:property-placeholder location="classpath:redis.properties" />      <context:component-scan base-package="com.d.work.main">    </context:component-scan>        <context:component-scan base-package="com.d.work.redis">    </context:component-scan>    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">        <property name="maxActive" value="50" />        <property name="maxIdle" value="8" />        <property name="maxWait" value="1000" />        <property name="testOnBorrow" value="true"/>        <property name="testOnReturn" value="true"/>        <!-- <property name="testWhileIdle" value="true"/> -->    </bean>    <bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool"  scope="singleton">        <constructor-arg index="0" ref="jedisPoolConfig" />        <constructor-arg index="1">            <list>                <bean class="redis.clients.jedis.JedisShardInfo">                    <constructor-arg name="host" value="${redis.host}" />                    <constructor-arg name="port" value="${redis.port}" />                    <constructor-arg name="timeout" value="${redis.timeout}" />                    <constructor-arg name="weight" value="1" />                </bean>            </list>        </constructor-arg>    </bean></beans>
 
 

 

 

RedisDataSource:定义三个方法

 
  
public interface RedisDataSource {    public abstract ShardedJedis getRedisClient();    public void returnResource(ShardedJedis shardedJedis);    public void returnResource(ShardedJedis shardedJedis,boolean broken);}
 
 

 

 

实现redisDataSource:

 

1, 注入配置好的ShardedJedisPool,这三个方法的作用:

 

 

 
getRedisClient() : 取得redis的客户端,可以执行命令了。
 
returnResource(ShardedJedis shardedJedis) : 将资源返还给pool
 
returnResource(ShardedJedis shardedJedis, boolean broken) : 出现异常后,将资源返还给pool (其实不需要第二个方法)
 

 

 
  
@Repository("redisDataSource")public class RedisDataSourceImpl implements RedisDataSource {    private static final Logger log = LoggerFactory.getLogger(RedisDataSourceImpl.class);    @Autowired    private ShardedJedisPool    shardedJedisPool;    public ShardedJedis getRedisClient() {        try {            ShardedJedis shardJedis = shardedJedisPool.getResource();            return shardJedis;        } catch (Exception e) {            log.error("getRedisClent error", e);        }        return null;    }    public void returnResource(ShardedJedis shardedJedis) {        shardedJedisPool.returnResource(shardedJedis);    }    public void returnResource(ShardedJedis shardedJedis, boolean broken) {        if (broken) {            shardedJedisPool.returnBrokenResource(shardedJedis);        } else {            shardedJedisPool.returnResource(shardedJedis);        }    }}
 
 

 

 

第二层的封装:RedisClientTemplate,例子实现了放值和取值。最后代码提供了全部命令的实现。

 

代码就是映射性质的又一次调用jedis的方法而已,用了个broken来做标示符,决定返还资源的方式。

 

这一层的目的主要也是让再上层的调用不需要关心pool中链接的取得和返还问题了。

 
  
@Repository("redisClientTemplate")public class RedisClientTemplate {    private static final Logger log = LoggerFactory.getLogger(RedisClientTemplate.class);    @Autowired    private RedisDataSource     redisDataSource;    public void disconnect() {        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        shardedJedis.disconnect();    }    /**     * 设置单个值     *      * @param key     * @param value     * @return     */    public String set(String key, String value) {        String result = null;        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.set(key, value);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    /**     * 获取单个值     *      * @param key     * @return     */    public String get(String key) {        String result = null;        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.get(key);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }}
 
 

测试代码:

 
  
    public static void main(String[] args) {        ApplicationContext ac =  new ClassPathXmlApplicationContext("classpath:/data-source.xml");        RedisClientTemplate redisClient = (RedisClientTemplate)ac.getBean("redisClientTemplate");        redisClient.set("a", "abc");        System.out.println(redisClient.get("a"));    }
 
 

附上RedisClientTemplate全部实现:

 
      
   
@Repository("redisClientTemplate")public class RedisClientTemplate {    private static final Logger log = LoggerFactory.getLogger(RedisClientTemplate.class);    @Autowired    private RedisDataSource     redisDataSource;    public void disconnect() {        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        shardedJedis.disconnect();    }    /**     * 设置单个值     *      * @param key     * @param value     * @return     */    public String set(String key, String value) {        String result = null;        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.set(key, value);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    /**     * 获取单个值     *      * @param key     * @return     */    public String get(String key) {        String result = null;        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.get(key);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    public Boolean exists(String key) {        Boolean result = false;        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.exists(key);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    public String type(String key) {        String result = null;        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.type(key);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    /**     * 在某段时间后实现     *      * @param key     * @param unixTime     * @return     */    public Long expire(String key, int seconds) {        Long result = null;        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.expire(key, seconds);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    /**     * 在某个时间点失效     *      * @param key     * @param unixTime     * @return     */    public Long expireAt(String key, long unixTime) {        Long result = null;        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.expireAt(key, unixTime);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    public Long ttl(String key) {        Long result = null;        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.ttl(key);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    public boolean setbit(String key, long offset, boolean value) {        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        boolean result = false;        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.setbit(key, offset, value);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    public boolean getbit(String key, long offset) {        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        boolean result = false;        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.getbit(key, offset);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    public long setrange(String key, long offset, String value) {        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        long result = 0;        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.setrange(key, offset, value);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    public String getrange(String key, long startOffset, long endOffset) {        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        String result = null;        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.getrange(key, startOffset, endOffset);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    public String getSet(String key, String value) {        String result = null;        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.getSet(key, value);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    public Long setnx(String key, String value) {        Long result = null;        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.setnx(key, value);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    public String setex(String key, int seconds, String value) {        String result = null;        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.setex(key, seconds, value);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        return result;    }    public Long decrBy(String key, long integer) {        Long result = null;        ShardedJedis shardedJedis = redisDataSource.getRedisClient();        if (shardedJedis == null) {            return result;        }        boolean broken = false;        try {            result = shardedJedis.decrBy(key, integer);        } catch (Exception e) {            log.error(e.getMessage(), e);            broken = true;        } finally {            redisDataSource.returnResource(shardedJedis, broken);        }        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值