2流高手速成記(之四):SpringBoot整合redis及mongodb

2022-10-23 06:02:00

最近很忙,好不容易才抽出了時間,咱們接上回

上次我們主要講了如何通過SpringBoot快速整合mybatis/mybatis-plus,以實現業務互動中的資料持久化,而這一切都是基於關係型資料庫(SQL)實現的

本節我們來把關注點轉向NoSQL

NoSQL的概念:

NoSQL,泛指非關係型的資料庫。隨著網際網路web2.0網站的興起,傳統的關聯式資料庫在處理web2.0網站,特別是超大規模和高並行的SNS型別的web2.0純動態網站已經顯得力不從心,出現了很多難以克服的問題,而非關係型的資料庫則由於其本身的特點得到了非常迅速的發展。NoSQL資料庫的產生就是為了解決大規模資料集合多重資料種類帶來的挑戰,特別是巨量資料應用難題。(——來自百度百科

得益於其直接基於記憶體的儲存方式,NoSQL的存取速度可以用「飛快」兩個字來形容

在生產環境中,NoSQL常常配合傳統關係型資料庫來使用,比如構建一層資料快取來極大的提升資料的讀取速度

NoSQL在日常業務的驅動之下,逐漸發展出幾個主要的類別:鍵值對資料庫、檔案型資料庫、列儲存資料庫以及圖形化資料庫

這4類NoSQL資料庫之中最具代表性的,當屬鍵值對資料庫類別下的Redis,以及檔案型資料庫的Mongodb,本節我們重點關注這兩個產品在SpringBoot下的整合及使用

照慣例先上專案結構:

 

 

一、先看Redis的使用:

1. 在pom.xml中新增Redis相關依賴項

        <!-- 引入redis依賴(基於lettuce) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

2. 在application.properties中新增Redis的相關設定

# redis相關設定
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
# redis預設基於lettuce核心
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.min-idle=0

這裡關於lettuce核心有必要給大家解釋一下:

在SpringBoot2.x版本之前,其整合的預設Redis庫是Jedis,而在2.x版本之後才改為預設基於Lettuce

Jedis預設和Redis直連,為非執行緒安全模型,並行環境下需要池化使用

而Lettuce則是執行緒安全的,並行環境下可以通過一個範例搞定

當然,你也可以在SpringBoot2.x環境下依然使用Jedis,只需要把 spring.redis.lettuce 相關設定替換為 spring.redis.jedis 即可

更多內容大家感興趣可以從網上查閱相關資料,這裡推薦一篇:https://blog.csdn.net/kenkao/article/details/127085687

3. 新建 service/RedisService 介面及其實現類 service/impl/RedisServiceImpl

package com.example.hellospringboot.service;

public interface RedisService {
    void set(String key, String val);
    String get(String key);
}
package com.example.hellospringboot.service.impl;

import com.example.hellospringboot.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

@Service
public class RedisServiceImpl implements RedisService {

    @Autowired
    StringRedisTemplate redis;

    public void set(String key, String val){
        ValueOperations<String,String> ops = redis.opsForValue();
        ops.set(key, val);
    }

    public String get(String key){
        ValueOperations<String,String> ops = redis.opsForValue();
        return ops.get(key);
    }
}

我們在Service中自動裝載一個StringRedisTemplate範例,而後通過其建立Operation物件,進行可以進行各種Redis讀寫操作

4. 新建 controller/RedisController 

package com.example.hellospringboot.controller;

import com.example.hellospringboot.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;

@RestController
@RequestMapping("/redis")
public class RedisController {

    @Autowired
    RedisService service;

    @PostMapping("/set")
    public void set(String key, String val){
        service.set(key, val);
    }

    @GetMapping("/get")
    public String get(String key){
        return service.get(key);
    }

}

5. 通過Postman進行結果驗證

 

 

 通過RDM檢視寫入redis的資料:

 

 

 之後是讀操作:

 

 

 至此我們便完成了SpringBoot中整合Redis的操作

二、MongoDB的使用

1. 首先還是先新增MongoDB相關依賴項

        <!-- 引入mongodb依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

2. 然後是新增MongoDB相關設定

# mongodb相關設定
spring.data.mongodb.authentication-database=admin
spring.data.mongodb.database=local
spring.data.mongodb.host=127.0.0.1
spring.data.mongodb.port=27017
#spring.data.mongodb.username=admin
#spring.data.mongodb.password=admin

各註釋項內容依次是:身份驗證庫、目標資料庫、主機地址、埠以及使用者名稱和口令

由於我沒有設定使用者名稱和口令,所以直接註釋掉這兩項

3. 新建 repository/PersonRepository

package com.example.hellospringboot.repository;

import com.example.hellospringboot.model.Person;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface PersonRepository extends MongoRepository<Person, Integer> {
    Person findByNameIs(String name);
    Person findByIdIs(int id);
    Person findByIdAndName(int id, String name);
    Person findByIdOrName(int id, String name);
}

這裡出現了非常神奇的一幕:

我們僅需要提供一個介面,而不用提供具體實現!

僅憑方法的命名規範,spring.data.mongodb就能自行分析開發者的意圖,進行補全內部的業務邏輯!

而同樣具備這種智慧化能力的還有spring.jpa,後者也是一種非常便捷高效資料庫驅動,與mybatis屬於同類產品

順便也給大家提供一份方法命名規範清單,請各位在方法命名時務必遵循以下規則:

關鍵字 方法命名 sql where字句
And findByNameAndPwd where name= ? and pwd =?
Or findByNameOrSex where name= ? or sex=?
Is,Equals findById,findByIdEquals where id= ?
Between findByIdBetween where id between ? and ?
LessThan findByIdLessThan where id < ?
LessThanEqual findByIdLessThanEqual where id <= ?
GreaterThan findByIdGreaterThan where id > ?
GreaterThanEqual findByIdGreaterThanEqual where id > = ?
After findByIdAfter where id > ?
Before findByIdBefore where id < ?
IsNull findByNameIsNull where name is null
isNotNull,NotNull findByNameNotNull where name is not null
Like findByNameLike where name like ?
NotLike findByNameNotLike where name not like ?

StartingWith

findByNameStartingWith where name like '?%'
EndingWith findByNameEndingWith where name like '%?'
Containing findByNameContaining where name like '%?%'
OrderBy findByIdOrderByXDesc where id=? order by x desc
Not findByNameNot where name <> ?
In findByIdIn(Collection<?> c) where id in (?)
NotIn findByIdNotIn(Collection<?> c) where id not in (?)
True

findByAaaTue

where aaa = true
False findByAaaFalse where aaa = false
IgnoreCase findByNameIgnoreCase where UPPER(name)=UPPER(?)

 

4. Service介面定義及實現

package com.example.hellospringboot.service;

import com.example.hellospringboot.model.Person;

public interface MongoService {
    public void insert(Person person);
    public Person findByName(String name);
    public Person findById(int id);
    public Person findByIdAndName(int id, String name);
    public Person findByIdOrName(int id, String name);
}
package com.example.hellospringboot.service.impl;

import com.example.hellospringboot.model.Person;
import com.example.hellospringboot.repository.PersonRepository;
import com.example.hellospringboot.service.MongoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MongoServiceImpl implements MongoService {

    @Autowired
    PersonRepository repository;

    public void insert(Person person){
        repository.insert(person);
    }

    public Person findByName(String name){
        return repository.findByNameIs(name);
    }

    public Person findById(int id){
        return repository.findByIdIs(id);
    }

    public Person findByIdAndName(int id, String name){
        return repository.findByIdAndName(id, name);
    }

    public Person findByIdOrName(int id, String name){
        return repository.findByIdOrName(id, name);
    }
}

5. Controller實現

package com.example.hellospringboot.controller;

import com.example.hellospringboot.model.Person;
import com.example.hellospringboot.service.MongoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/mongo")
public class MongoController {

    @Autowired
    MongoService service;

    @PostMapping("/insert")
    public void insert(Person person){
        service.insert(person);
    }

    @GetMapping("/findByName")
    public Person findByName(String name){
        return service.findByName(name);
    }

    @GetMapping("/findById")
    public Person findById(int id){
        return service.findById(id);
    }

    @GetMapping("/findByIdAndName")
    public Person findByIdAndName(int id, String name){
        return service.findByIdAndName(id, name);
    }

    @GetMapping("/findByIdOrName")
    public Person findByIdOrName(int id, String name) {
        return service.findByIdOrName(id, name);
    }
}

Service及Controller的實現不再做過多贅述,還是老一套

6. Postman驗證結果

向mongodb中寫入一條資料

 

 

 

 之後是幾種讀取操作:

 

 

 

 

 

 不論是與或操作,我們都可以得到正確的結果

 到這裡,mongodb的整合就完成了

三、基於Redis實現Session設定共用

這部分純屬附送內容 ^ ^

前邊我們已經完成了對Redis的整合操作,而基於Redis我們可以非常便捷的實現伺服器端Session設定的跨節點共用

伺服器端Session預設儲存在本地,而當我們需要多臺伺服器共用一套Session設定時,在地化Session便不再滿足我們的要求

而基於SpringSession,我們可以完全透明化的替換掉預設的Session容器,直接改為基於Redis儲存

1. 新增相關依賴

        <!-- 引入spring session無縫替換原有的session系統 -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

2. 新增兩個RedisController方法

    @PostMapping("/setSession")
    public void setSession(String key, String val, HttpSession session){
        session.setAttribute(key, val);
    }

    @GetMapping("/getSession")
    public Object getSession(String key, HttpSession session){
        return session.getAttribute(key);
    }

就完事兒了?對!就完事兒了 ^ ^,超級簡單是吧?

到此,我們就完成了SpringBoot對於Redis以及MongoDB的整合和使用

非常感慨於SpringBoot框架設計的智慧化及人性化,就像身邊有一哥們說的:這年頭,框架都能直接聽懂人話了!哈哈

下一節我們討論一個生產環境下常常面臨的實際問題——安全管理

Shiro框架要來咯!敬請期待——