1.认识两个工具类

Redis工具类使用说明书 - 图1

2.开发中使用场景以及注意事项

2.1业务逻辑编写中的使用

2.1.1使用Demo

  1. 同事A要写一个用户查询接口,入参是用户的id,出参是一个用户信息
  2. 同事A编写完成,Controller->Service->DAO(Mapper)

①Controller层

  1. @RestController
  2. public class TestRedisController {
  3. @Autowired
  4. private SysUserService sysUserService;
  5. @RequestMapping("getSysUser")
  6. public SysUser getSysUser(long id){
  7. return sysUserService.getSysUserById(id);
  8. }
  9. }

②Service层

  1. @Service
  2. public class SysUserService {
  3. @Autowired
  4. private SysUserMapper sysUserMapper;
  5. public SysUser getSysUserById(long id){
  6. return sysUserMapper.getUserById(id);
  7. }
  8. }

③Dao层

  1. @Repository
  2. public interface SysUserMapper {
  3. SysUser getUserById(long id);
  4. }
  1. 同事A编写完成后,老大要求对此接口引入缓存来加快二次查询的效率,同事A求助同事B,同事B用了2秒种完成了老大的需求,改动如下:

    1. @Repository
    2. public interface SysUserMapper {
    3. @Cacheable(value="user",key = "#id")
    4. SysUser getUserById(long id);
    5. }

    4.同事A成功的完成的任务,但是他不明白@Cacheable注解的含义,于是同事B告诉他:

    1. @Cacheable注解标注到方法上
    2. 首次执行被@Cacheable标注的注解,该方法的返回值(这里SysUser对象)会被缓存进入Redis
    3. 注解中的value指明是最终key值的前缀,注解中的key值指明拼接在前缀后面的值,#id就是参数id值,注解中key值的指明规则可以查看 https://blog.csdn.net/newbie_907486852/article/details/81478046
    4. 对于c的解释可能有点模糊,直接举例:我查询一个 id=1的用户信息,那么redis中会为我记录如下的信息: key为 user:1 ,value 为 id=1的用户信息。

5.开发中可能还会删除redis缓存,因此可以查看 其他的缓存注解 ,相关博客同上

2.1.2关于key过期时间的配置

  1. 场景:对于查询对象的key-value对,可能要求的过期时间是不一样的
  2. 配置方式

    1. yurun:
    2. cache-manager:
    3. configs:
    4. - key: menu
    5. second: 300
    6. - key: user
    7. second: 1800
    8. - keyxxxx
    9. second: xxx
  3. 上述配置中我们查看第二个key=user second=1800

①含义解释:通过注解的方式设置缓存的,前缀为 user的 所有key -value对的 过期时间是1800s
②结合2.1.1来说,就是我的sysUser只保存1800s

2.2分布式锁的使用

分布式锁的封装方法在RedissonDistributedLock 类中,注入使用即可,这里的方法是对redission客户端提供的分布式锁方法的二次封装

2.2.1方法概览

  1. 方法罗列

    1. /**
    2. * 获取锁,如果获取不成功则一直等待直到lock被获取
    3. * @param key 锁的key
    4. * @param leaseTime 加锁的时间,超过这个时间后锁便自动解锁;
    5. * 如果leaseTime为-1,则保持锁定直到显式解锁
    6. * @param unit {@code leaseTime} 参数的时间单位
    7. * @param isFair 是否公平锁
    8. * @return 锁对象
    9. */
    10. Object lock(String key, long leaseTime, TimeUnit unit, boolean isFair) throws Exception;
    11. Object lock(String key, long leaseTime, TimeUnit unit) throws Exception;
    12. Object lock(String key, boolean isFair) throws Exception;
    13. Object lock(String key) throws Exception;
    14. /**
    15. * 尝试获取锁,如果锁不可用则等待最多waitTime时间后放弃
    16. * @param key 锁的key
    17. * @param waitTime 获取锁的最大尝试时间(单位毫秒)
    18. * @param leaseTime 加锁的时间,超过这个时间后锁便自动解锁;
    19. * 如果leaseTime为-1,则保持锁定直到显式解锁
    20. * @param unit {@code waitTime} 和 {@code leaseTime} 参数的时间单位
    21. * @return 锁对象,如果获取锁失败则为null
    22. */
    23. Object tryLock(String key, long waitTime, long leaseTime, TimeUnit unit, boolean isFair) throws Exception;
    24. Object tryLock(String key, long waitTime, long leaseTime, TimeUnit unit) throws Exception;
    25. Object tryLock(String key, long waitTime, TimeUnit unit, boolean isFair) throws Exception;
    26. Object tryLock(String key, long waitTime, TimeUnit unit) throws Exception;
    27. /**
    28. * 释放锁
    29. * @param lock 锁对象
    30. */
    31. void unlock(Object lock) throws Exception;
  2. 方法解释

①unlock:释放锁
②lock:获取锁
③trylock:尝试获取锁
④这里对②、③的区别是不是很迷惑?简单解释一下:

  1. lock:直到获取锁后才向下执行
  2. trylock:是尝试获取锁,若获取不到,仍然会继续执行下面的代码

    2.2.2使用Demo

  1. 场景描述:这里我写两个线程,每个线程打印完自己的内容后,睡眠3s。

    1. @Test
    2. public void testLock() throws InterruptedException {
    3. CountDownLatch countDownLatch = new CountDownLatch(2);
    4. new Thread(new Runnable() {
    5. @Override
    6. public void run() {
    7. System.out.println("hello");
    8. try {
    9. Thread.sleep(3000);
    10. } catch (InterruptedException e) {
    11. e.printStackTrace();
    12. }
    13. countDownLatch.countDown();
    14. }
    15. }).start();
    16. new Thread(new Runnable() {
    17. @Override
    18. public void run() {
    19. System.out.println("hello2");
    20. try {
    21. Thread.sleep(3000);
    22. } catch (InterruptedException e) {
    23. e.printStackTrace();
    24. }
    25. countDownLatch.countDown();
    26. }
    27. }).start();
    28. countDownLatch.await();
    29. }
  2. 以上的结果一定是:hello和hello2几乎同时打印出来,但是我想让一个线程打印完后,等待3s再打印另一个。

    1. @Autowired
    2. RedissonDistributedLock redissonDistributedLock;
    3. final String LOCK_KEY="mylock";
    4. @Test
    5. public void testLock() throws InterruptedException {
    6. CountDownLatch countDownLatch = new CountDownLatch(2);
    7. new Thread(new Runnable() {
    8. @Override
    9. public void run() {
    10. RLock lock = redissonDistributedLock.lock(LOCK_KEY);
    11. System.out.println("hello");
    12. try {
    13. Thread.sleep(3000);
    14. } catch (InterruptedException e) {
    15. e.printStackTrace();
    16. }
    17. countDownLatch.countDown();
    18. redissonDistributedLock.unlock(lock);
    19. }
    20. }).start();
    21. new Thread(new Runnable() {
    22. @Override
    23. public void run() {
    24. RLock lock2 = redissonDistributedLock.lock(LOCK_KEY);
    25. System.out.println("hello2");
    26. try {
    27. Thread.sleep(3000);
    28. } catch (InterruptedException e) {
    29. e.printStackTrace();
    30. }
    31. countDownLatch.countDown();
    32. redissonDistributedLock.unlock(lock2);
    33. }
    34. }).start();
    35. countDownLatch.await();
    36. }
  3. 上面的代码执行结果,一定是其中一个先打印,3s后另一个才打印

    2.3数据库CRUD操作的工具使用

    2.3.1使用Demo

  4. 注入RedisRepository 工具类使用即可

  5. 简单的使用代码
    1. @Autowired
    2. private RedisRepository redisRepository;
    3. @Test
    4. public void testestRedisUtil(){
    5. redisRepository.set("name","yurun");
    6. redisRepository.get("name");
    7. redisRepository.putHashValue("person","age",1);
    8. redisRepository.getHashValues("person","age");
    9. redisRepository.leftPush("mylist","helloworld");
    10. redisRepository.leftPop("mylist");
    11. redisRepository.getList("mylist",0,-1);
    12. redisRepository.set("productNum",200);
    13. redisRepository.incr("productNum");
    14. }