Redis缓存
1.CentOS7的安装
傻瓜式安装
启动后输入账户和密码就OK啦。
关闭当前机器的哔哔提示音:
vim /etc/inputrc
找到set bell-style none 将前面的#去掉,重启系统
即可解决操作命令行时tab键和backspace键的声音问题。但是在用vim时,还是会有哔哔声。
也可以将此机器保存为一个母机,日后的机器从此克隆就行。
2.获取虚拟机ip
1.查看当前虚拟机的ip地址
ip addr
可以看到当前虚拟机没有ip地址
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ocSp0n34-1574302699791)(C:\Users\zhangkuan\AppData\Roaming\Typora\typora-user-images\1557301448897.png)]
2.获取ip地址
vi /etc/sysconfig/network-scripts/ifcfg-ens33
修改:ONBOOT=yes
保存退出(:wq)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FrBNZqDN-1574302699792)(C:\Users\zhangkuan\AppData\Roaming\Typora\typora-user-images\1557301579331.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V71p0EQC-1574302699792)(C:\Users\zhangkuan\AppData\Roaming\Typora\typora-user-images\1557301662568.png)]
3.重启虚拟机
reboot
4.查看虚拟机ip地址
ip addr
此时即可看到该虚拟机的ip地址了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vwxr4CYh-1574302699793)(C:\Users\zhangkuan\AppData\Roaming\Typora\typora-user-images\1557301976903.png)]
3.安装并启动Redis服务
1.将Redis的安装包上传到虚拟机
Alt+p键 将Redis的安装包拉倒SecureCRT
2.解压Redis的安装包
tar -zxvf redis-4.0.9.tar.gz
3.安装gcc
yum install gcc
4.进入到Redis的目录下进行编译
cd redis-4.0.9/
make
5.安装Redis到/usr/redis目录下
make install PREFIX=/usr/redis
6.开启redis的服务
cd /usr/redis/bin/
./redis-server
看到如图页面即表示redis服务启动成功
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aNsf0XHw-1574302699793)(C:\Users\zhangkuan\AppData\Roaming\Typora\typora-user-images\1557303007094.png)]
注意:
为了使java代码能够操作redis
需要修改redis的配置文件
vi redis-4.0.9/redis.conf
将第69行的127.0.0.1修改成0.0.0.0(set nu 可展示行)
再次启动redis服务的时候需要加载配置文件启动
cd /usr/redis/bin/
./redis-server /root/redis-4.0.9/redis.conf
4.SpringBoot继承Redis做缓存
4.1使用Jedis开发
1.导入jar
<!--SpringBoot的aop编程-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--加入jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
2.开发SpringBoot项目
3.将Jedis交由Spring工厂管理
@Configuration
public class CommonFactory {
@Bean("jedis")
public Jedis getJedis(){
return new Jedis("192.168.181.133",6379);//redis服务的机器ip,端口号
}
}
4.开发自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisCache {
}
5.开发一个切面
1.第一种key方案(String)
(1)Redis中key的设定
key:全类名.方法名实参 例:com.baizhi.service.UserServiceImpl.selectAllUser
com.baizhi.service.UserServiceImpl.selectUserById123
value: 查询出来的结果
(2) 开发一个通知类
@Configuration
@Aspect
public class RedisCache {
@Autowired
private Jedis jedis;
/**
* 将业务层的查询方法添加到缓存中
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("execution(* com.baizhi.service.*.selectAll*(..))")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// 判断当前注解是否存在
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
Method method = methodSignature.getMethod();
boolean b = method.isAnnotationPresent(com.baizhi.annotation.RedisCache.class);
System.out.println("b:"+b);
Object result = null;
if(b){
// 存在注解
StringBuilder sb = new StringBuilder();
// 获取类的名称
String className = proceedingJoinPoint.getTarget().getClass().getName();
// 获取方法的名称
String methodName = proceedingJoinPoint.getSignature().getName();
// 获取参数实参
Object[] args = proceedingJoinPoint.getArgs();
sb.append(className).append(".").append(methodName);
for (Object arg : args) {
sb.append(arg);
}
String key = sb.toString();
System.out.println("key:"+key);
// 判断redis中是否含有这个key
if ( jedis.exists(key) ){
// 缓存中存在该key
String json = jedis.get(key);
result = JSONObject.parse(json);
}else{
// 缓存中不含有该key,放行方法
result = proceedingJoinPoint.proceed();
// 将查询的结果放入到redis中缓存起来
jedis.set(key, JSONObject.toJSONString(result));
}
jedis.close();
return result;
}else {
// 不存在注解
result = proceedingJoinPoint.proceed();
}
jedis.close();
return result;
}
/**
* 执行增删改方法之后清除当前业务层的查询缓存
* @param joinPoint
*/
@After("execution(* com.baizhi.service.*.*(..)) && !execution(* com.baizhi.service.*.select*(..))")
public void after(JoinPoint joinPoint){
// 获取当前执行目标对象的全名
String className = joinPoint.getTarget().getClass().getName();
System.out.println("className:"+className);
// 获取redis缓存中的所有key
Set<String> keys = jedis.keys("*");
for (String key : keys) {
//当前遍历的key 包含当前执行的目标方法的全类名(以当前执行目标方法的全类名开头)
if (key.startsWith(className)){
//删除缓存中的这个key
jedis.del(key);
}
}
// 关闭jedis的连接
jedis.close();
}
}
2.第二种key方案(Hash)
(1)Redis中key的设定
key:全类名 例:com.baizhi.service.UserServiceImpl
value: key:方法名 value:查询出来的结果
例:key:selectAllUser:1,2 selectUserById:123
(2) 第二种key方案的好处:
第一种方案每次添加修改删除的时候都需要拿到Redis中所有的缓存,并进行遍历,删除和用户相关的所有缓存
第二种方案则不需要拿到Redis中所有的缓存进行遍历,直接删除key为用户这个类的所有缓存即可
(3) 开发一个通知类
@Configuration
@Aspect
public class RedisCacheNew {
@Autowired
private Jedis jedis;
/**
* 将业务层的查询方法添加到缓存中
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("execution(* com.baizhi.service.*.selectAll*(..))")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// 判断当前注解是否存在
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
Method method = methodSignature.getMethod();
boolean b = method.isAnnotationPresent(com.baizhi.annotation.RedisCache.class);
Object result = null;
if(b){
// 存在注解
StringBuilder sb = new StringBuilder();
// 获取类的名称
String className = proceedingJoinPoint.getTarget().getClass().getName();
// 获取方法的名称
String methodName = proceedingJoinPoint.getSignature().getName();
// 获取参数实参
Object[] args = proceedingJoinPoint.getArgs();
// sb.append(className).append(".").append(methodName);
sb.append(methodName);
for (Object arg : args) {
sb.append(arg);
}
String key = sb.toString();
System.out.println("key:"+key);
// 判断redis中是否含有这个key
if ( jedis.hexists(className, key) ){
// 缓存中存在该key
String json = jedis.hget(className, key);
result = JSONObject.parse(json);
}else{
// 缓存中不含有该key,放行方法
result = proceedingJoinPoint.proceed();
// 将查询的结果放入到redis中缓存起来
jedis.hset(className, key, JSONObject.toJSONString(result));
}
jedis.close();
return result;
}else {
// 不存在注解
result = proceedingJoinPoint.proceed();
}
jedis.close();
return result;
}
/**
* 执行增删改方法之后清除当前业务层的查询缓存
* @param joinPoint
*/
// @After("execution(* com.baizhi.service.*.*(..)) && !execution(* com.baizhi.service.*.select*(..))")
@AfterReturning("execution(* com.baizhi.service.*.*(..)) && !execution(* com.baizhi.service.*.select*(..))")
public void after(JoinPoint joinPoint){
// 获取当前执行目标对象的全名
String className = joinPoint.getTarget().getClass().getName();
System.out.println("className:"+className);
jedis.del(className);
// 关闭jedis的连接
jedis.close();
}
}
3.@After和@AfterReturning区别
@After:无论目标方法是否有异常,都将执行切面中的代码(删除缓存)
@AfterReturning:目标方法一旦有异常,则不会执行切面中的代码(删除缓存)
4.2使用RestTemplate开发
1.导入jar
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.声明相关配置
spring:
redis:
host: 192.168.181.133
port: 6379
3.测试案例
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test2 {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testString(){
ValueOperations valueOperations = redisTemplate.opsForValue();
valueOperations.set("name", "zhangsan");
valueOperations.set("user", new User("uuu","小黑","男",new Date()));
Object name = valueOperations.get("name");
System.out.println(name);
User user = (User) valueOperations.get("user");
System.out.println(user.getId());
System.out.println(user.getName());
System.out.println(user.getSex());
System.out.println(user.getBir());
}
@Test
public void testList(){
ListOperations listOperations = redisTemplate.opsForList();
listOperations.leftPush("aa", "123");
listOperations.leftPush("aa", new User("uuu","小黑","男",new Date()));
List list = listOperations.range("aa", 0, -1);
for (Object o : list) {
System.out.println(o);
}
}
//可以做键绑定,使用起来更简单一些
@Test
public void testList2(){
BoundListOperations ops = redisTemplate.boundListOps("aa");
ops.leftPush("123");
ops.leftPush(new User("uuu","小黑","男",new Date()));
List list = ops.range(0, -1);
for (Object o : list) {
System.out.println(o);
}
}
}
ct o : list) {
System.out.println(o);
}
}
//可以做键绑定,使用起来更简单一些
@Test
public void testList2(){
BoundListOperations ops = redisTemplate.boundListOps("aa");
ops.leftPush("123");
ops.leftPush(new User("uuu","小黑","男",new Date()));
List list = ops.range(0, -1);
for (Object o : list) {
System.out.println(o);
}
}
}