思考:
java中执行某个service方法,先判断缓存中有没有该方法的返回值。
如果有的话,直接在redis缓存中取得数据并返回给controller。
如果没有的话,先执行改service,得到的结果放到redis中.第二次将直接在redis中取得数据
在springboot中就有@cacheable
相关注解实现类似的业务。在这里我们使用自定义注解的方式实现该业务流程
Springboot整合redis
步骤一:在pom.xml中导入相关依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
步骤二:写配置文件
server:
port: 8000
spring:
redis:
database: 2
host: 127.0.0.1
port: 6379
#连接超时时间(ms)
timeout: 5000
jedis:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: -1
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
步骤三:业务中使用RedisTemplate<Object,Object> redisTemplate
实现redis的操作
package com.shida.service.impl;
import com.shida.annotation.RedisAfterFind;
import com.shida.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
/**
* Description:
*
* @author mfei
* Date: 2022/3/22 14:47
**/
@Service
public class HelloServiceImpl implements HelloService {
@Autowired
private RedisTemplate<Object,Object> redisTemplate;
private String key = "getHello";
@Override
@RedisAfterFind(key = "hello")
public Object getHello() {
System.out.println("-----进入了此方法-----");
String user = "15+张三";
redisTemplate.opsForValue().set(key,user);
System.out.println("-------结束方法-----");
return user;
}
@Override
@RedisAfterFind(key = "hello1")
public Object getHello1() {
System.out.println("-----进入了此方法-----");
String user = "16+张三";
redisTemplate.opsForValue().set(key,user);
System.out.println("-------结束方法-----");
return user;
}
@Override
@RedisAfterFind(key = "hello2")
public Object getHello2() {
System.out.println("-----进入了此方法-----");
String user = "18+张三";
redisTemplate.opsForValue().set(key,user);
System.out.println("-------结束方法-----");
return user;
}
@Override
public String getRedis() {
String age = "年龄为" + redisTemplate.opsForValue().get("age");
return age;
}
}
发现问题:
redis存储格式为/dfafd/b63/fdfd疑似乱码(其实是编码的问题)
解决方案:重写RedisTemplate
package com.shida.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* Description:
*
* @author mfei
* Date: 2022/3/22 16:01
**/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
template.setValueSerializer(genericJackson2JsonRedisSerializer);
template.setHashValueSerializer(genericJackson2JsonRedisSerializer);
return template;
}
}
使用注解+AOP方法实现redi方法缓存
package com.shida.common;
import java.lang.annotation.*;
/**
* @author mfei
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisAopFind {
String key();
int seconds() default -1;
}
package com.shida.common;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* Description:
*
* @author mfei
* Date: 2022/3/19 16:45
**/
@Aspect
@Component
public class RedisAop {
@Autowired
private RedisTemplate<Object,Object> redisTemplate;
@Before(value = "@annotation(com.shida.common.RedisAopFind)")
public void doBefore(){
System.out.println("---------方法执行前---------");
}
@Around("@annotation(com.shida.common.RedisAopFind)")
public Object around(ProceedingJoinPoint point) throws Throwable {
Object result = null;
MethodSignature signature = (MethodSignature) point.getSignature();
RedisAopFind redisAopFind = signature.getMethod().getAnnotation(RedisAopFind.class);
String key = redisAopFind.key();
Method method = signature.getMethod();
// -------- 使用spel表达式,可忽视------
//创建解析器
SpelExpressionParser parser = new SpelExpressionParser();
//获取表达式
Expression expression = parser.parseExpression(key);
//设置解析上下文(有哪些占位符,以及每种占位符的值)
EvaluationContext context = new StandardEvaluationContext();
//获取参数值
Object[] args = point.getArgs();
//获取运行时参数的名称
DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
String[] parameterNames = discoverer.getParameterNames(method);
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i],args[i].toString());
}
//解析,获取替换后的结果
String result1 = expression.getValue(context).toString();
System.out.println(result1);
// ---------------------------------------
Boolean aBoolean = redisTemplate.hasKey(result1);
if (aBoolean) {
return redisTemplate.opsForValue().get(result1);
}
result = point.proceed();
redisTemplate.opsForValue().set(result1,result);
return result;
}
}
网友评论