# spring-redis
**Repository Path**: ultrajava/spring-redis
## Basic Information
- **Project Name**: spring-redis
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2017-01-10
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# spring整合redis实现无侵入式的缓存管理
> 使用spring缓存相关的注解, 并且结合redis, 达到无侵入式的缓存管理, 下面我将用一个demo演示怎样去实现...
## 项目整体结构

大家先看一下项目的整体结构, 暂时不要去纠结具体内容, 在需要的时候我会把内容贴出来
## 添加依赖
要想使用`spring`、`redis`,首先一定是要添加相关依赖, 为了测试方便我又添加了`junit`,为了代码简明我还添加了`lombok`
`pom.xml`完整内容:
```
4.0.0
com.kangyonggan
spring-redis
1.0-SNAPSHOT
4.9
4.2.5.RELEASE
1.3.2.RELEASE
2.4.2
1.16.8
junit
junit
${junit.version}
org.springframework
spring-core
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-context-support
${spring.version}
org.springframework
spring-aop
${spring.version}
org.springframework
spring-test
${spring.version}
org.springframework.data
spring-data-redis
${spring-data-redis.version}
redis.clients
jedis
${jedis.version}
org.projectlombok
lombok
${lombok.version}
provided
```
## reids相关配置
为了演示方便,我就不用`properties`或者`autoconfig`之类的了
`spring-redis.xml`完整内容:
```
```
## 自定义缓存配置
`RedisCacheConfig`完整内容:
```
package com.kangyonggan.redis.cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
/**
* @author kangyonggan
* @since 2016/10/16
*/
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
private JedisConnectionFactory jedisConnectionFactory;
private RedisTemplate redisTemplate;
private RedisCacheManager redisCacheManager;
public RedisCacheConfig(JedisConnectionFactory jedisConnectionFactory, RedisTemplate redisTemplate, RedisCacheManager redisCacheManager) {
this.jedisConnectionFactory = jedisConnectionFactory;
this.redisTemplate = redisTemplate;
this.redisCacheManager = redisCacheManager;
}
}
```
有需要的话, 可以重新定义`key`的生成策略, 覆写`keyGenerator`方法即可。
## 使用注解, 让代码无侵入
为了演示方便, 这里就不面向接口了
`UserService`完整内容:
```
package com.kangyonggan.redis.service;
import com.kangyonggan.redis.model.User;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
/**
* @author kangyonggan
* @since 16/10/16
*/
@Service
public class UserService {
/**
* 根据用户ID查找用户信息
*
* @param id
* @return
*/
@Cacheable(value = "user", key = "'user_id_' + #id")
public User findUserById(Long id) {
System.out.println("findUserById:" + id);
return new User();
}
/**
* 更新用户
*
* @param user
*/
@CacheEvict(value = "user", key = "'user_id_'+#user.getId()")
public void updateUser(User user) {
System.out.println("updateUser:" + user);
}
/**
* 删除用户
*
* @param id
*/
@CacheEvict(value = "user", key = "'user_id_'+#id")
public void deleteUser(Long id) {
System.out.println("deleteUser:" + id);
}
/**
* 清空用户相关缓存
*/
@CacheEvict(value = "user", allEntries = true)
public void clearUserCache() {
System.out.println("clearUserCache");
}
}
```
关于`@Cacheable`和`@CacheEvict`请自行百度,这里只是整合!
其中用到了`User`, 其完整代码:
```
package com.kangyonggan.redis.model;
import lombok.Data;
import java.io.Serializable;
/**
* @author kangyonggan
* @since 16/10/16
*/
@Data
public class User implements Serializable {
private Long id;
}
```
> 注意:User类要实现序列化
其中`@Data`用来在字节码中生成getter、setter、toString、hashCode等, 我用的是IntelliJ IDEA编译器,需要安装lombok插件, lombok相关知识请自行百度。
其中`@Service`用的是spring的ioc, 所以需要添加spring相关配置, `applicationContext.xml`完整内容:
```
```
## 测试
`UserServiceTest`完整内容:
```
package com.kangyonggan.redis;
import com.kangyonggan.redis.model.User;
import com.kangyonggan.redis.service.UserService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @author kangyonggan
* @since 2016/10/16
*/
public class UserServiceTest extends BaseTestCase {
@Autowired
private UserService userService;
@Test
public void testClearCache() {
log("==========testClearCache==========");
userService.clearUserCache();
log("==========testClearCache==========");
}
/**
* 测试查找用户
*/
@Test
public void testFindUserById() {
log("==========testFindUserById==========");
userService.findUserById(317L);
userService.findUserById(318L);
log("==========testFindUserById==========");
}
/**
* 测试删除用户
*/
@Test
public void testDeleteUser() {
log("==========testDeleteUser==========");
userService.deleteUser(317L);
log("==========testDeleteUser==========");
}
/**
* 测试更新用户
*/
@Test
public void testUpdateUser() {
log("==========testUpdateUser==========");
User user = new User();
user.setId(317L);
userService.updateUser(user);
log("==========testUpdateUser==========");
}
/**
* 输出日志
*
* @param object
*/
private void log(Object object) {
System.out.println(object);
}
}
```
其中`BaseTestCase`的完整内容:
```
package com.kangyonggan.redis;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author kangyonggan
* @since 2016/10/16
*/
@ContextConfiguration(locations = {"classpath:app-core.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class BaseTestCase extends AbstractJUnit4SpringContextTests {
}
```
其中`app-core.xml`的完整内容:
```
```
## 说明
如果用户经常有改动, 那么在分页查询用户信息时就不要加入缓存, 因为一旦添加了新用户就要去清空缓存, 这样可能会得不偿失, 因此我这里分页查询用户就没加缓存(所以代码也没贴)。当然,也有一些不经常改动的, 比如菜单, 我会在下面的例子中贴出如何管理此类缓存。
`MenuService`完整内容:
```
package com.kangyonggan.redis.service;
import com.kangyonggan.redis.model.Menu;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author kangyonggan
* @since 16/10/16
*/
@Service
public class MenuService {
/**
* 添加菜单
*
* @param menu
*/
@CacheEvict(value = "menu", allEntries = true)
public void saveMenu(Menu menu) {
System.out.println("saveMenu:" + menu);
}
/**
* 根据菜单ID查找菜单信息
*
* @param id
* @return
*/
@Cacheable(value = "menu", key = "'menu_id_' + #id")
public Menu findMenuById(Long id) {
System.out.println("findMenuById:" + id);
return new Menu();
}
/**
* 根据菜单ID查找菜单信息
*
* @param pageNum
* @return
*/
@Cacheable(value = "menu", key = "'menus_p_' + #pageNum")
public List