欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解java之redis篇(spring-data-redis整合)

程序员文章站 2024-03-08 13:11:16
1,利用spring-data-redis整合 项目使用的pom.xml:

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>

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

项目文件目录结构:

详解java之redis篇(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=foobared
redis.host=127.0.0.1
redis.port=6379
redis.pass=
 
redis.maxidle=300
redis.maxactive=600
redis.maxwait=1000
redis.testonborrow=true

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;
 }
}

测试代码:

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>

目录结构:

详解java之redis篇(spring-data-redis整合)

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全部实现:

redisclienttemplate代码太多,附上下载地址:http://xiazai.jb51.net/201701/yuanma/redisclienttemplate_jb51.rar

 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。