這是最標準、維護性最好的方式,Spring 封裝了底層 Jedis 操作,開發者只需關注業務邏輯。
<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>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>0.9.24</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<beans ...>
<!-- 載入屬性檔 -->
<context:property-placeholder location="classpath:redis.properties" />
<!-- 掃描 DAO 包 -->
<context:component-scan base-package="com.x.redis.dao" />
<!-- Jedis 連線池配置 -->
<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" />
<!-- RedisTemplate:Spring 對 Redis 的核心封裝 -->
<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.host=127.0.0.1 redis.port=6379 redis.pass= redis.maxIdle=300 redis.maxActive=600 redis.maxWait=1000 redis.testOnBorrow=true
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;
}
});
}
}
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()); // 輸出: obama
}
不使用 Spring Data Redis 封裝,直接操作 Jedis,並自行建立連線池管理與模板封裝層。
<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>
@Repository("redisDataSource")
public class RedisDataSourceImpl implements RedisDataSource {
@Autowired private ShardedJedisPool shardedJedisPool;
public ShardedJedis getRedisClient() {
try { return shardedJedisPool.getResource(); }
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);
}
}
@Repository("redisClientTemplate")
public class RedisClientTemplate {
@Autowired private RedisDataSource redisDataSource;
public String set(String key, String value) {
ShardedJedis jedis = redisDataSource.getRedisClient();
if (jedis == null) return null;
boolean broken = false;
try { return jedis.set(key, value); }
catch (Exception e) { broken = true; throw e; }
finally { redisDataSource.returnResource(jedis, broken); }
}
// get() 等其他方法同理...
}
| 維度 | Spring Data Redis | 手動 Jedis 整合 |
|---|---|---|
| 開發效率 | 高(現成模板) | 中(需自行封裝) |
| 靈活度 | 中 | 高(可控制底層細節) |
| 分片支援 | 需額外配置 | 原生支援 ShardedJedisPool |
| 維護成本 | 低 | 較高 |
一般專案建議使用方案一;若需複雜分片、特殊連線控制或效能極致優化,可考慮方案二。