首頁  >  文章  >  Java  >  java SpringBoot專案整合Redis的方法是什麼

java SpringBoot專案整合Redis的方法是什麼

王林
王林轉載
2023-05-12 13:52:131482瀏覽

Redis 是完全開源的,遵守BSD 協議,是一個高效能的key-value 資料庫.

Redis 與其他key - value 快取產品有以下三個特點:

  • Redis支援資料的持久化,可以將記憶體中的資料保存在磁碟中,重啟的時候可以再次載入進行使用。

  • Redis不僅支援簡單的key-value類型的數據,同時也提供list,set,zset,hash等資料結構的儲存。

  • Redis支援資料的備份,即master-slave模式的資料備份。

Redis 的優勢

  • 效能極高– Redis能讀的速度是110000次/s,寫的速度是81000次/ s

  • 豐富的資料型別– Redis支援二進位案例的 String, List, Hash, Set 及zset資料型別運算。

  • 原子 – Redis的所有操作都是原子性的,意思是要麼成功執行要麼失敗完全不執行。單一操作是原子性的。多個操作也支援事務,即原子性,透過MULTI和EXEC指令包起來。

  • 豐富的特性– Redis也支援 publish/subscribe, 通知, key 過期等等特性

  • Redis 是單執行緒的,6.0版本開始支援開啟多執行緒。

Redis 安裝

java SpringBoot项目整合Redis的方法是什么

解壓縮下載後的壓縮文件,解壓縮後文件清單如下:

java SpringBoot项目整合Redis的方法是什么

使用cmd視窗開啟Redis

redis-server.exe   redis.windows.conf   #加载配置文件启动

java SpringBoot项目整合Redis的方法是什么

#註:啟動之後,不要關閉窗口,關閉視窗服務停止!

安裝Redis資料庫客戶端

java SpringBoot项目整合Redis的方法是什么

#庫相關指令:

flushdb  清空当前库

flushall  清空所有库

select   1    切换库

key的相關指令

刪除一個或多個keydel keyname ##existsexists keynameexpireexpire keyname secondss查詢所有符合模式的key ?匹配一個字元*匹配0-n個字元[] 滿足其中的一個key * key h?llo##randomkeyrandomkey#renamerename key newkeytypetype keyname

Redis 資料型別

1.String(字串)

  • string 是redis 最基本的型別,你可以理解成與Memcached 一模一樣的型別,一個key 對應一個value。

  • string 類型是二進位安全的。意思是 redis 的 string 可以包含任何資料。例如jpg圖片或是序列化的物件。

  • string 類型是 Redis 最基本的資料類型,string 類型的值最大能儲存 512MB。

操作指令:

指令 #作用 語法
del
判斷一個或多個key是否存在,多個key時有一個存在則會回傳1
設定key的生存時間單位:秒
##key
move ##將key移到指定的庫中 move keyname db
#pexpire 設定key的生存時間單位:毫秒設定成功回傳1 否則回傳0 pexpire keyname milliseconds
##ttl##以秒為單位傳回key的剩餘生存時間,回傳-1表示永久存儲,-2表示key不存在 ttl keyname
從目前資料庫中隨機的回傳一個key
重命名key,成功回傳ok,否則返回錯誤訊息。
傳回key所儲存的值的型別
##SET設定指定key 的值GET##取得指定key 的值。 傳回key 中字串值的子字元將key所儲存的值加上給定的浮點增量值(increment)將key 中儲存的數字值減一。 key 所儲存的值減去給定的減量值(decrement)
命令 描述
GETRANGE
##GETSET 將給定key 的值設為value ,並傳回key 的舊值(old value)。
SETEX 將值 value 關聯到 key ,並將 key 的過期時間設為 seconds (以秒為單位)。
SETNX 只有在key 不存在時設定key 的值
STRLEN 傳回key 所儲存的字串值的長度。
MSET 同時設定一個或多個 key-value 對。
MSETNX 同時設定一個或多個key-value 對,當且僅當所有給定key 都不存在
INCR 將key 中儲存的數字值增加一個
INCRBY 將key 所儲存的值加上給定的增量值(increment)
#INCRBYFLOAT
#INCRBYFLOAT
#DECR
DECRBY

APPEND
  • 如果key 已經存在且是一個字串,APPEND 指令將指定的value 追加到該key 原來值(value)的結尾

  • #2.Hash(雜湊)

Redis hash 是鍵值(key=>value)對集合。 操作指令:命令描述##hset設定一個key/value對#hget 取得key對應的valuehgetall取得所有的key/value對#hdel刪除某個key/value對hexists判斷一個key是否存在#hkeys取得所有的keyhvals取得所有的valuehmset設定多個key/valuehmget取得多個key的valuehsetnx設定一個不存在的key的值hincrby
Redis hash 是一個 string 類型的 field 和 value 的映射表,hash 特別適合用於儲存物件。
###value的值加法運算############hincrbyfloat######為value的值加浮點類型值運算## ##########

3.List(列表)

  • Redis 列表是簡單的字串列表,依照插入順序排序。你可以加上一個元素到清單的頭部(左邊)或尾部(右邊)。

操作指令

#透過索引取得清單中的元素lindex lists 0在清單的元素前後插入元素#取得清單長度# 移出並取得清單的第一個元素LPUSHLPUSHX的清單頭取得清單指定範圍內的元素(0 -1)#移除清單重複元素透過索引設定清單元素的值,但索引必須存在,實質是根據索引修改值##LTRIMRPOPRPOPLPUSHRPUSH
#指令 描述
LINDEX
LINSERT key BEFORE|AFTER
LLEN
LPOP
將一個或多個值插入到清單頭
將一個值插入到已存在
#LRANGE
LREM
LSET
將一個清單修剪(trim),就是說,讓清單只保留指定區間內的元素,不在指定區間之內的元素都會被刪除
移除清單的最後一個元素,傳回值為移除的元素
移除清單的最後一個元素,並將該元素新增至另一個清單並傳回

在清單中新增一個或多個值
  • RPUSHX
  • #為已存在的清單新增值

4.Set(集合)Redis 的Set 是string 類型的無序集合。 集合是透過哈希表實現的,所以添加,刪除,查找的複雜度都是 O(1)。 操作指令:##saddsmembersscard#spopsmovesremsismembersrandmember
命令 描述
為集合新增元素
顯示集合中所有元素(無序)
傳回集合中元素的數量
隨機傳回一個元素,並將這個元素刪除
從一個集合向令一個集合轉移元素
從集合中刪除一個元素
判斷集合中是否包含這個元素
隨機傳回一個元素

  • sinter

    求交集sunion##求和集

  • 5.ZSet(sorted set:有序集合)

  • #Redis ZSet
  •  與 

    Set#同樣也是 String

     類型元素的集合,且不允許重複的成員。

不同的是每個元素都會關聯一個 double 類型的分數。 RedisZSet 的成員是唯一的,但分數(score)卻可以重複。 命令描述##zadd新增一個有序集合元素zcard傳回集合中元素的數量zrange升序zrevrange降序傳回一個範圍內的元素zrangebyscore依照分數找出一個範圍內的元素zrank回傳排名#zrevrankzscore
 正是透過分數為集合中的成員進行從小到大的排序。
操作指令:
##倒敘排名
顯示某個元素的分數############zrem######移除某個元素########## ###zincrby######給某個特定元素加分#############

SpringBoot 操作 Redis

  spring boot data redis中提供了RedisTemplate和StringRedisTemplate,其中StringRedisTemplate是Redistemplate的子类,两个方法基本一致,不同之处主要体现在操作的数据类型不同,RedisTemplate中的两个泛型都是Object,意味着存储的key和value都可以是一个对象,而StringRedisTemplate的两个泛型都是String,意味着StringRedisTemplate的key和value都只能是字符串。

引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

SpringBoot 配置 Redis

spring:
  redis:
    # Redis数据库索引(默认为0)
    database: 0
    # Redis服务器地址
    host: 127.0.0.1
    # Redis服务器连接端口
    port: 6379
    # Redis服务器连接密码(默认为空)
    password:
    # 连接池最大连接数(使用负值表示没有限制)
    jedis.pool.max-active: 20
    # 连接池最大阻塞等待时间(使用负值表示没有限制)
    jedis.pool.max-wait: -1
    # 连接池中的最大空闲连接
    jedis.pool.max-idle: 10
    # 连接池中的最小空闲连接
    jedis.pool.min-idle: 0
    # 连接超时时间(毫秒)
    timeout: 1000

RedisTemplate 及其相关方法

1.RedisTemplate 介绍

  Spring封装了RedisTemplate对象来进行对Redis的各种操作,它支持所有的Redis原生的api。RedisTemplate位于spring-data-redis包下。RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅。

2.Redis 5种数据结构操作

  • redisTemplate.opsForValue(); //操作字符串

  • redisTemplate.opsForHash(); //操作hash

  • redisTemplate.opsForList(); //操作list

  • redisTemplate.opsForSet(); //操作set

  • redisTemplate.opsForZSet(); //操作有序set

或者:

  • redistempalate.boundValueOps

  • redistempalate.boundSetOps

  • redistempalate.boundListOps

  • redistempalate.boundHashOps

  • redistempalate.boundZSetOps

 opsForXXX和boundXXXOps的区别:XXX为value的类型,前者获取一个operator,但是没有指定操作的对象(key),可以在一个连接(事务)内操作多个key以及对应的value;后者获取了一个指定操作对象(key)的operator,在一个连接(事务)内只能操作这个key对应的value。

 SpringBootTest 实现Redis数据库增删改查

/**
 * 使用RedisTemplate 操作Redis数据的不同数据类型
 */
@SpringBootTest
public class Springbootday03ApplicationTests {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * String 类型数据操作
     */
    @Test
    public void operateString() {

        //添加值
        redisTemplate.opsForValue().set("str", "strValue1");

        //添加值  判定是否存在 存在则不添加
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("str", "strAbsent");
        System.out.println("str设置成功:" + aBoolean);

        //获取值
        String str = redisTemplate.opsForValue().get("str");
        System.out.println("str = " + str);

        //更新值
        redisTemplate.opsForValue().set("str", "strValue2");
        str = redisTemplate.opsForValue().get("str");
        System.out.println("newStr = " + str);

        //删除值
        Boolean b = redisTemplate.delete("str");
        System.out.println("str删除成功:" + b);

    }

    /**
     * 操作string类型数据  设置过期时间
     */
    @Test
    public void operateString2() {
        redisTemplate.opsForValue().set("str", "strTimeout", 10, TimeUnit.SECONDS);
        //判定值是否存在 不存在则设置值 同时设置过期时间
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("str2", "strTimeoutAbsent", 20, TimeUnit.SECONDS);
        System.out.println("setIfAbsent:" + aBoolean);
    }

    /**
     * 操作hash类型数据
     */
    @Test
    public void operateHash() {
        //添加hash类型数据  key - value
        redisTemplate.opsForHash().put("hash", "username", "admin");
        //修改hash类型数据
        redisTemplate.opsForHash().put("hash", "username", "tom");
        redisTemplate.opsForHash().put("hash", "password", "123456");

        //添加hash类型数据  key - map
        HashMap<String, String> map = new HashMap<>();
        map.put("driverName", "com.mysql.jdbc.Driver");
        map.put("url", "jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC");
        redisTemplate.opsForHash().putAll("hash", map);

        //获取hash类型数据  entries
        Map<Object, Object> hash = redisTemplate.opsForHash().entries("hash");
        hash.forEach((key, value) -> {
            System.out.println(key + "::" + value);
        });

        //获取所有的key
        Set<Object> keys = redisTemplate.opsForHash().keys("hash");
        for (Object key : keys) {
            System.out.println("key:" + key);
        }
        //获取所有value
        List<Object> values = redisTemplate.opsForHash().values("hash");
        values.forEach(value -> System.out.println("value:" + value));

        //删除hash类型数据  删除一个  返回删除的个数
        Long delete = redisTemplate.opsForHash().delete("hash", "username");
        System.out.println("delete = " + delete);

        //删除hash类型数据  删除多个  返回删除的个数
        delete = redisTemplate.opsForHash().delete("hash", "username", "password", "driverName");
        System.out.println("delete = " + delete);

        //删除hash类型数据  删除所有
        Boolean delHash = redisTemplate.delete("hash");
        System.out.println("delHah:" + delHash);

    }

    /**
     * 操作List类型  有序 可重复
     */
    @Test
    public void operateList() {

        //左压栈
        // redisTemplate.opsForList().leftPush("list", "listValue1");
        // redisTemplate.opsForList().leftPush("list", "listValue1");
        // redisTemplate.opsForList().leftPush("list", "listValue2");
        // redisTemplate.opsForList().leftPush("list", "listValue3");

        //右压栈
        redisTemplate.opsForList().rightPush("list", "listValue0");
        redisTemplate.opsForList().rightPush("list", "listValue2");
        redisTemplate.opsForList().rightPush("list", "listValue0");

        //左出栈
        String list1 = redisTemplate.opsForList().leftPop("list");
        System.out.println("leftPop list1 = " + list1);
        //右出栈
        String list2 = redisTemplate.opsForList().rightPop("list");
        System.out.println("rightPop list2 = " + list2);

        //获取所有数据
        List<String> lists = redisTemplate.opsForList().range("list", 0, 		        redisTemplate.opsForList().size("list") - 1);
        lists.forEach(list -> System.out.println(list));


        //设置指定位置的数据
        redisTemplate.opsForList().set("list", 0, "listValue0");
        /**
         * 从存储在键中的列表中删除等于值的元素的第一个计数事件。
         * count> 0:删除等于从左到右移动的值的第一个元素;
         * count< 0:删除等于从右到左移动的值的第一个元素;
         * count = 0:删除等于value的所有元素。
         */
        Long remove = redisTemplate.opsForList().remove("list", -1, "listValue0");
        System.out.println("remove:" + remove);

        //删除指定key的list数据
        Boolean list = redisTemplate.delete("list");
        System.out.println("list集合删除成功:" + list);
    }

    /**
     * 操作Set类型  无序 不可重复
     */
    @Test
    public void operateSet() {

        //设置set值
        redisTemplate.opsForSet().add("set", "setValue0");
        redisTemplate.opsForSet().add("set", "setValue0");
        redisTemplate.opsForSet().add("set", "setValue1");

        //判定是否包含
        Boolean member = redisTemplate.opsForSet().isMember("set", "setValue0");
        System.out.println("isMember:" + member);

        //删除set中的值
        Long remove = redisTemplate.opsForSet().remove("set", "setValue0");
        System.out.println("remove = " + remove);

        //获取set类型值
        Set<String> set = redisTemplate.opsForSet().members("set");
        set.forEach(str -> {
            System.out.println("str = " + str);
        });
    }

    /**
     * 操作 ZSet  有序 不可重复
     */
    @Test
    public void operateZSet() {
        //存储值
        Boolean add = redisTemplate.opsForZSet().add("zset", "zsetValue0", 10);
        System.out.println("add = " + add);
        System.out.println("add = " + add);
        add = redisTemplate.opsForZSet().add("zset", "zsetValue2", 2);
        System.out.println("add = " + add);
        //获取值
        // Boolean zset = redisTemplate.delete("zset");
        // System.out.println("delete zset = " + zset);
    }
}

Redis工具类的封装

/**
 * Redis 工具类
 * @author mosin
 * date 2021/11/30
 * @version 1.0
 */
@Component
public final class RedisUtil {

    private RedisUtil(){};
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    //设置值
    public void  setValue(String key,String value){
        redisTemplate.opsForValue().set(key, value);
    }
    // 设置值 同时设置有效时间
    public void setValue(String key, String value, Long timeOut, TimeUnit timeUnit){
        redisTemplate.opsForValue().setIfAbsent(key, value, timeOut, timeUnit);
    }

    //设置值 没有则设置 有则不设置
    public void  setNx(String key,String value){
        redisTemplate.opsForValue().setIfAbsent(key, value);
    }

    //设置值 没有则设置 同时设置有效时间 有则不设置
    public void  setNx(String key,String value,long timeOut,TimeUnit timeUnit){
        redisTemplate.opsForValue().setIfAbsent(key, value,timeOut,timeUnit);
    }

    //删除值
    public boolean del(String key){
        return redisTemplate.delete(key);
    }
    
     //获取值
    public String getValue(String key){
        return  redisTemplate.opsForValue().get(key);
    }
}

Redis 业务实践

redis 存储 token,实现非法请求拦截

1.编写拦截器

@Component
public class AdminInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisUtil redisUtil;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器以拦截请求");
        //从请求头中获取token  验证用户是否登录
        String token = request.getHeader("token");
        System.out.println(token);
        String tokenValue = redisUtil.getValue(token);
        System.out.println("tokenValue = " + tokenValue);
        if(tokenValue!=null){ //用户已登录 放行请求
            return  true;
        }else{//重定向到登录页面
            response.sendRedirect(request.getContextPath()+"/login.jsp");
            return false;
        }
    }
}

2.配置拦截器

@Configuration
public class LoginConfig implements WebMvcConfigurer {
    @Autowired
    private AdminInterceptor adminInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration registration = registry.addInterceptor(adminInterceptor);
        registration.addPathPatterns("/**");
        registration.excludePathPatterns("/user/login","/user/register","/login.jsp");
    }
}

3.编写统一返回数据格式类

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class JsonResult<T> {
    private Integer code;
    private String msg;
    private Long count;
    private T data;
}

4.编写控制器

@Controller
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private RedisUtil redisUtil;
    @ResponseBody
    @RequestMapping("/login")
    public Object login(User user) throws JsonProcessingException {
        User usr = User.builder().id(1).name("admin").password("123456").build();
        //获取token  放入redis
        String token = UUID.randomUUID().toString().replace("-", "");
        //将user 转为json格式放入 redis
        ObjectMapper objectMapper = new ObjectMapper();
        String s1 = objectMapper.writeValueAsString(usr);
        //将 token 和用户信息存入 redis
        redisUtil.setValue(token, s1, 2L, TimeUnit.MINUTES);
        //将token 存入map集合返回
        HashMap<String, String> map = new HashMap<>();
        map.put("token", token);
        return map;
    }

    @ResponseBody
    @RequestMapping("/register")
    public Object register(User user){
        HashMap<String, String> map = new HashMap<>();
        map.put("msg", "ok");
        return map;
    }

    @ResponseBody
    @RequestMapping("/add")
    public Object add(User user){
        HashMap<String, String> map = new HashMap<>();
        map.put("msg", "ok");
        return map;
    }
}

5.编写业务类和Mapper接口

6.使用postman接口测试工具测试接口

以上是java SpringBoot專案整合Redis的方法是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除