首页 > 编程 > Java > 正文

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

2019-11-26 13:17:30
字体:
来源:转载
供稿:网友

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=foobaredredis.host=127.0.0.1redis.port=6379redis.pass= redis.maxIdle=300redis.maxActive=600redis.maxWait=1000redis.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代码太多,附上下载地址:http://xiazai.VeVB.COm/201701/yuanma/RedisClientTemplate_jb51.rar

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表