Redis缓存

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);
    }
}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-七秒钟记忆

微薄打赏,小编的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值