溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發(fā)布時間:2023-03-31 11:54:27 來源:億速云 閱讀:164 作者:iii 欄目:開發(fā)技術

這篇文章主要介紹了java SpringBoot項目整合Redis的方法是什么的相關知識,內(nèi)容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇java SpringBoot項目整合Redis的方法是什么文章都會有所收獲,下面我們一起來看看吧。

Redis 是完全開源的,遵守 BSD 協(xié)議,是一個高性能的 key-value 數(shù)據(jù)庫.

Redis 與其他 key - value 緩存產(chǎn)品有以下三個特點:

  • Redis支持數(shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤中,重啟的時候可以再次加載進行使用。

  • Redis不僅僅支持簡單的key-value類型的數(shù)據(jù),同時還提供list,set,zset,hash等數(shù)據(jù)結(jié)構(gòu)的存儲。

  • Redis支持數(shù)據(jù)的備份,即master-slave模式的數(shù)據(jù)備份。

Redis 的優(yōu)勢

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

  • 豐富的數(shù)據(jù)類型 – Redis支持二進制案例的 String, List, Hash, Set 及 zset數(shù)據(jù)類型操作。

  • 原子 – Redis的所有操作都是原子性的,意思就是要么成功執(zhí)行要么失敗完全不執(zhí)行。單個操作是原子性的。多個操作也支持事務,即原子性,通過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數(shù)據(jù)庫客戶端

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

庫相關指令:

flushdb  清空當前庫

flushall  清空所有庫

select   1    切換庫

key的相關指令

指令作用語法
del刪除一個或多個keydel keyname
exists判斷一個或多個key是否存在,多個key時有一個存在則就會返回1exists keyname
expire設置key的生存時間 單位 :秒expire keyname seconds
keys查詢所有匹配模式的key ?匹配一個字符 *匹配0-n個字符 [] 滿足其中的一個key * key h?llo
move將key移動到指定的庫中move keyname db
pexpire設置key的生存時間 單位 :毫秒 設置成功返回1 否則返回0pexpire keyname milliseconds
ttl以秒為單位返回key的剩余生存時間,返回-1表示永久存儲,-2表示key不存在ttl keyname
randomkey從當前數(shù)據(jù)庫中隨機的返回一個keyrandomkey
rename重命名key,成功返回ok,否則返回錯誤信息。rename key newkey
type返回key所存儲的值的類型type keyname

Redis 數(shù)據(jù)類型

1.String(字符串)

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

  • string 類型是二進制安全的。意思是 redis 的 string 可以包含任何數(shù)據(jù)。比如jpg圖片或者序列化的對象。

  • string 類型是 Redis 最基本的數(shù)據(jù)類型,string 類型的值最大能存儲 512MB。

操作指令:

命令描述
SET設置指定 key 的值
GET獲取指定 key 的值。
GETRANGE返回 key 中字符串值的子字符
GETSET將給定 key 的值設為 value ,并返回 key 的舊值(old value)。
SETEX將值 value 關聯(lián)到 key ,并將 key 的過期時間設為 seconds (以秒為單位)。
SETNX只有在 key 不存在時設置 key 的值
STRLEN返回 key 所儲存的字符串值的長度。
MSET同時設置一個或多個 key-value 對。
MSETNX同時設置一個或多個 key-value 對,當且僅當所有給定 key 都不存在
INCR將 key 中儲存的數(shù)字值增一
INCRBY將 key 所儲存的值加上給定的增量值(increment)
INCRBYFLOAT將 key 所儲存的值加上給定的浮點增量值(increment)
DECR將 key 中儲存的數(shù)字值減一。
DECRBYkey 所儲存的值減去給定的減量值(decrement)
APPEND如果 key 已經(jīng)存在并且是一個字符串, APPEND 命令將指定的 value 追加到該 key 原來值(value)的末尾

2.Hash(哈希)

  • Redis hash 是一個鍵值(key=>value)對集合。

  • Redis hash 是一個 string 類型的 field 和 value 的映射表,hash 特別適合用于存儲對象。

操作指令:

命令描述
hset設置一個key/value對
hget獲取key對應的value
hgetall獲取所有的key/value對
hdel刪除某個key/value對
hexists判斷一個key是否存在
hkeys獲取所有的key
hvals獲取所有的value
hmset設置多個key/value
hmget獲取多個key的value
hsetnx設置一個不存在的key的值
hincrby為value的值進行加法運算
hincrbyfloat為value的值進行加浮點類型值運算

3.List(列表)

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

操作指令

命令描述
LINDEX通過索引獲取列表中的元素 lindex lists 0
LINSERT key BEFORE|AFTER在列表的元素前或者后插入元素
LLEN獲取列表長度
LPOP移出并獲取列表的第一個元素
LPUSH將一個或多個值插入到列表頭部
LPUSHX將一個值插入到已存在的列表頭部
LRANGE獲取列表指定范圍內(nèi)的元素 (0 -1)
LREM移除列表重復元素
LSET通過索引設置列表元素的值 ,但是索引必須存在,實質(zhì)是根據(jù)索引修改值
LTRIM對一個列表進行修剪(trim),就是說,讓列表只保留指定區(qū)間內(nèi)的元素,不在指定區(qū)間之內(nèi)的元素都將被刪除
RPOP移除列表的最后一個元素,返回值為移除的元素
RPOPLPUSH移除列表的最后一個元素,并將該元素添加到另一個列表并返回
RPUSH在列表中添加一個或多個值
RPUSHX為已存在的列表添加值

4.Set(集合)

  • Redis 的 Set 是 string 類型的無序集合。

  • 集合是通過哈希表實現(xiàn)的,所以添加,刪除,查找的復雜度都是 O(1)。

操作指令:

命令描述
sadd為集合添加元素
smembers顯示集合中所有元素 (無序)
scard返回集合中元素的個數(shù)
spop隨機返回一個元素,并將這個元素刪除
smove從一個集合向令一個集合中轉(zhuǎn)移元素
srem從集合中刪除一個元素
sismember判斷集合中是否包含這個元素
srandmember隨機返回一個元素
sinter求交集
sunion求和集

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

  • Redis ZSet 和 Set 一樣也是 String 類型元素的集合,且不允許重復的成員。

  • 不同的是每個元素都會關聯(lián)一個 double 類型的分數(shù)。Redis 正是通過分數(shù)來為集合中的成員進行從小到大的排序。

  • ZSet 的成員是唯一的,但分數(shù)(score)卻可以重復。

操作指令:

命令描述
zadd添加一個有序集合元素
zcard返回集合中元素的個數(shù)
zrange升序 zrevrange降序返回一個范圍內(nèi)的元素
zrangebyscore按照分數(shù)查找一個范圍內(nèi)的元素
zrank返回排名
zrevrank倒敘排名
zscore顯示某個元素的分數(shù)
zrem移除某個元素
zincrby給某個特定元素加分

SpringBoot 操作 Redis

  spring boot data redis中提供了RedisTemplate和StringRedisTemplate,其中StringRedisTemplate是Redistemplate的子類,兩個方法基本一致,不同之處主要體現(xiàn)在操作的數(shù)據(jù)類型不同,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數(shù)據(jù)庫索引(默認為0)
    database: 0
    # Redis服務器地址
    host: 127.0.0.1
    # Redis服務器連接端口
    port: 6379
    # Redis服務器連接密碼(默認為空)
    password:
    # 連接池最大連接數(shù)(使用負值表示沒有限制)
    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 介紹

&emsp;&emsp;Spring封裝了RedisTemplate對象來進行對Redis的各種操作,它支持所有的Redis原生的api。RedisTemplate位于spring-data-redis包下。RedisTemplate提供了redis各種操作、異常處理及序列化,支持發(fā)布訂閱。

2.Redis 5種數(shù)據(jù)結(jié)構(gòu)操作

  • 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的區(qū)別:XXX為value的類型,前者獲取一個operator,但是沒有指定操作的對象(key),可以在一個連接(事務)內(nèi)操作多個key以及對應的value;后者獲取了一個指定操作對象(key)的operator,在一個連接(事務)內(nèi)只能操作這個key對應的value。

 SpringBootTest 實現(xiàn)Redis數(shù)據(jù)庫增刪改查

/**
 * 使用RedisTemplate 操作Redis數(shù)據(jù)的不同數(shù)據(jù)類型
 */
@SpringBootTest
public class Springbootday03ApplicationTests {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * String 類型數(shù)據(jù)操作
     */
    @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類型數(shù)據(jù)  設置過期時間
     */
    @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類型數(shù)據(jù)
     */
    @Test
    public void operateHash() {
        //添加hash類型數(shù)據(jù)  key - value
        redisTemplate.opsForHash().put("hash", "username", "admin");
        //修改hash類型數(shù)據(jù)
        redisTemplate.opsForHash().put("hash", "username", "tom");
        redisTemplate.opsForHash().put("hash", "password", "123456");

        //添加hash類型數(shù)據(jù)  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類型數(shù)據(jù)  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類型數(shù)據(jù)  刪除一個  返回刪除的個數(shù)
        Long delete = redisTemplate.opsForHash().delete("hash", "username");
        System.out.println("delete = " + delete);

        //刪除hash類型數(shù)據(jù)  刪除多個  返回刪除的個數(shù)
        delete = redisTemplate.opsForHash().delete("hash", "username", "password", "driverName");
        System.out.println("delete = " + delete);

        //刪除hash類型數(shù)據(jù)  刪除所有
        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);

        //獲取所有數(shù)據(jù)
        List<String> lists = redisTemplate.opsForList().range("list", 0, 		        redisTemplate.opsForList().size("list") - 1);
        lists.forEach(list -> System.out.println(list));


        //設置指定位置的數(shù)據(jù)
        redisTemplate.opsForList().set("list", 0, "listValue0");
        /**
         * 從存儲在鍵中的列表中刪除等于值的元素的第一個計數(shù)事件。
         * count> 0:刪除等于從左到右移動的值的第一個元素;
         * count< 0:刪除等于從右到左移動的值的第一個元素;
         * count = 0:刪除等于value的所有元素。
         */
        Long remove = redisTemplate.opsForList().remove("list", -1, "listValue0");
        System.out.println("remove:" + remove);

        //刪除指定key的list數(shù)據(jù)
        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 業(yè)務實踐

redis 存儲 token,實現(xiàn)非法請求攔截

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.編寫統(tǒng)一返回數(shù)據(jù)格式類

@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 轉(zhuǎn)為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.編寫業(yè)務類和Mapper接口

6.使用postman接口測試工具測試接口

關于“java SpringBoot項目整合Redis的方法是什么”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“java SpringBoot項目整合Redis的方法是什么”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI