1. 程式人生 > >springboot2整合redis,並自定義@Cache

springboot2整合redis,並自定義@Cache

1.maven依賴

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.5.0</version>
</dependency>

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

<!-- springboot2.x預設使用lettuce 不是jedis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.0</version>
</dependency>

2.application.properties配置

#資料庫索引 預設值0
spring.redis.database=0
spring.redis.host=182.92.234.232
spring.redis.port=6379
spring.redis.password=

#連線池最大連線數 負值表示無限制
spring.redis.jedis.pool.max-active=8
#連線池最大阻塞等待時間 負值表示無限制
spring.redis.jedis.pool.max-wait=-1
#連線池最大空閒連線
spring.redis.jedis.pool.max-idle=8
#連線池最小空閒連線
spring.redis.jedis.pool.min-idle=0
#連線超時時間(單位為毫秒)
spring.redis.timeout=2000

3.自定義RedisConfig

 @Configuration
 @EnableCaching
 public class RedisConfig extends CachingConfigurerSupport {
 
     @Bean
     public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
         RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
         redisTemplate.setConnectionFactory(redisConnectionFactory);
 
         ObjectMapper objectMapper = new ObjectMapper();
         objectMapper.setVisibility(PropertyAccessor.ALL, Visibility.ANY);
         objectMapper.enableDefaultTyping(DefaultTyping.NON_FINAL);
 
         Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
         jsonRedisSerializer.setObjectMapper(objectMapper);
         redisTemplate.setDefaultSerializer(jsonRedisSerializer);
 
         redisTemplate.setKeySerializer(new StringRedisSerializer());
         redisTemplate.afterPropertiesSet();
         return redisTemplate;
     }
 }

4.自定義快取Service (key:string value:object)

public interface IRedisCacheService {

    /**
     * @param expire TimeUnit.SECONDS
     */
    void setCache(String key, Object value, int expire);

    Object getCache(String key);

    void clearCache(String key);
}

@Service
public class RedisCacheServiceImpl implements IRedisCacheService {
    private static final Logger logger = LoggerFactory.getLogger(RedisCacheServiceImpl.class);

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void setCache(String key, Object value, int expire) {
        redisTemplate.opsForValue().set(key, value);
        redisTemplate.expire(key, expire, TimeUnit.SECONDS);
    }

    @Override
    public Object getCache(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    @Override
    public void clearCache(String key) {
        redisTemplate.delete(key);
    }
}

5.測試Service

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

   @Autowired
   private IRedisCacheService redisCacheServiceImpl;
   @Autowired
   private IUserService userServiceImpl;

   @Test
   public void add() {
       User user = new User("tom", "123456");
       redisCacheServiceImpl.setCache("redisKey", user, 200);
   }

   @Test
   public void get() {
       User user = (User) redisCacheServiceImpl.getCache("redisKey");
       System.out.println(user);
   }

   @Test
   public void delete() {
       redisCacheServiceImpl.clearCache("redisKey");
   }
}

6.自定義註解Cache

@Inherited
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Cache {

    /**
     * 字首 後面會拼引數
     */
    String prefix() default "";

    /**
     * 快取失效時間5分鐘
     */
    int expiredTime() default 60 * 5;
}

7.對@Cache的切面

@Aspect
@Service
public class CacheAspect {
	private static final Logger logger = LoggerFactory.getLogger(CacheAspect.class);

    private static final String el = "@annotation(com.boomsecret.annotation.Cache)";

    private static final String SYMBOL = ".";

    @Autowired
    private IRedisCacheService redisCacheServiceImpl;

	@Around(el)
	public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = methodSignature.getMethod();
        Cache cache = method.getAnnotation(Cache.class);

        StringBuilder sb = new StringBuilder();
        sb.append(methodSignature.getReturnType().getName()).append(SYMBOL)
                .append(method.getName()).append(SYMBOL)
                .append(cache.prefix()).append(SYMBOL);

		Object[] args = proceedingJoinPoint.getArgs();
		if(args.length > 0){
			for(Object arg : args){
				if(arg != null){
                    sb.append(arg.toString()).append(SYMBOL);
				}
			}
		}

		String redisKey = sb.substring(0, sb.length() - 1);

		Object redisCacheResult = null;
		try {
            redisCacheResult = redisCacheServiceImpl.getCache(redisKey);
		} catch (Exception e) {
			logger.warn("obtain value from redis error. key : " + redisKey);
		}

		if(redisCacheResult != null){
			return redisCacheResult;
		}

        redisCacheResult = proceedingJoinPoint.proceed();

		if(redisCacheResult != null){
			try {
                redisCacheServiceImpl.setCache(redisKey, redisCacheResult, cache.expiredTime());
			} catch (Exception e) {
				logger.warn("set value to redis error. key: " + redisKey);
			}
		}
		return redisCacheResult;
	}
}

[email protected]使用

@Cache(prefix = "key", expiredTime = 200)
@Override
public User getUser() {
    return new User(UUID.randomUUID().toString(), "123456");
}

[email protected]測試

@Test
public void testCacheAnnotation() {
    // 2次取出相同
    User temp001 = userServiceImpl.getUser();
    User temp002 = userServiceImpl.getUser();
    System.out.println(temp001);
    System.out.println(temp002);
}

原始碼 https://gitee.com/jsjack_wang/springboot-demo dev-redis分支