当前位置: 移动技术网 > IT编程>开发语言>Java > 详解java之redis篇(spring-data-redis整合)

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

2019年07月22日  | 移动技术网IT编程  | 我要评论

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了

项目文件目录结构:

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>

目录结构:

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代码太多,附上下载地址:

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网