[前端學(xué)java05-SpringBoot實(shí)戰(zhàn)] 常用注解 + redis實(shí)現(xiàn)統(tǒng)計(jì)功能

導(dǎo)航

[react] Hooks

[React 從零實(shí)踐01-后臺(tái)] 代碼分割
[React 從零實(shí)踐02-后臺(tái)] 權(quán)限控制
[React 從零實(shí)踐03-后臺(tái)] 自定義hooks
[React 從零實(shí)踐04-后臺(tái)] docker-compose 部署react+egg+nginx+mysql
[React 從零實(shí)踐05-后臺(tái)] Gitlab-CI使用Docker自動(dòng)化部署

[源碼-webpack01-前置知識(shí)] AST抽象語(yǔ)法樹(shù)
[源碼-webpack02-前置知識(shí)] Tapable
[源碼-webpack03] 手寫(xiě)webpack - compiler簡(jiǎn)單編譯流程
[源碼] Redux React-Redux01
[源碼] axios
[源碼] vuex
[源碼-vue01] data響應(yīng)式 和 初始化渲染
[源碼-vue02] computed 響應(yīng)式 - 初始化,訪問(wèn),更新過(guò)程
[源碼-vue03] watch 偵聽(tīng)屬性 - 初始化和更新
[源碼-vue04] Vue.set 和 vm.$set
[源碼-vue05] Vue.extend

[源碼-vue06] Vue.nextTick 和 vm.$nextTick
[部署01] Nginx
[部署02] Docker 部署vue項(xiàng)目
[部署03] gitlab-CI

[數(shù)據(jù)結(jié)構(gòu)和算法01] 二分查找和排序

[深入01] 執(zhí)行上下文
[深入02] 原型鏈
[深入03] 繼承
[深入04] 事件循環(huán)
[深入05] 柯里化 偏函數(shù) 函數(shù)記憶
[深入06] 隱式轉(zhuǎn)換 和 運(yùn)算符
[深入07] 瀏覽器緩存機(jī)制(http緩存機(jī)制)
[深入08] 前端安全
[深入09] 深淺拷貝
[深入10] Debounce Throttle
[深入11] 前端路由
[深入12] 前端模塊化
[深入13] 觀察者模式 發(fā)布訂閱模式 雙向數(shù)據(jù)綁定
[深入14] canvas
[深入15] webSocket
[深入16] webpack
[深入17] http 和 https
[深入18] CSS-interview
[深入19] 手寫(xiě)Promise
[深入20] 手寫(xiě)函數(shù)
[深入21] 數(shù)據(jù)結(jié)構(gòu)和算法 - 二分查找和排序
[深入22] js和v8垃圾回收機(jī)制
[深入23] JS設(shè)計(jì)模式 - 代理,策略,單例

[前端學(xué)java01-SpringBoot實(shí)戰(zhàn)] 環(huán)境配置和HelloWorld服務(wù)
[前端學(xué)java02-SpringBoot實(shí)戰(zhàn)] mybatis + mysql 實(shí)現(xiàn)歌曲增刪改查
[前端學(xué)java03-SpringBoot實(shí)戰(zhàn)] lombok,日志,部署
[前端學(xué)java04-SpringBoot實(shí)戰(zhàn)] 靜態(tài)資源 + 攔截器 + 前后端文件上傳
[前端學(xué)java05-SpringBoot實(shí)戰(zhàn)] 常用注解 + redis實(shí)現(xiàn)統(tǒng)計(jì)功能

(一) 前置知識(shí)

(1) 一些單詞

security 安全 保護(hù)
core 核心
archetype 原型 // create from archetype 從原型創(chuàng)建
conditional 條件的
final 最終 決賽 // 在java中是常量的關(guān)鍵字
framework 框架 架構(gòu) // spring framework => spring框架
external 外部的 // external libraries 擴(kuò)展類(lèi)庫(kù)

(2) SpringBoot的默認(rèn)錯(cuò)誤解析

  • src/main/resources/templates/error/4xx.html或5xx.html會(huì)被自動(dòng)解析
    • 1.可以在resources/templates文件下
    • 2.也可以在靜態(tài)資源文件夾下resources/static|public|resources|META-INF.resources 等
  • 當(dāng)訪問(wèn)不存在的頁(yè)面時(shí),會(huì)返回templates/error/4xx|5xx頁(yè)面


    image

(3) java基本數(shù)據(jù)類(lèi)型

  • java提供了8中基本類(lèi)型 四個(gè)整數(shù)型 兩個(gè)浮點(diǎn)型 字符型 布爾型
  • 四個(gè)整數(shù)型
    • byte 8位
    • short 16位
    • int 32位 => 4個(gè)Byte
    • long 64位 => 8個(gè)Byte
  • 兩個(gè)浮點(diǎn)型
    • float
    • double
  • 字符型
    • char
  • 布爾型
    • boolean
  • 屬性:SIZE TYPE MIN_VALUE MAX_VALUE

(4) java的引用類(lèi)型

  • 所有引用類(lèi)型的默認(rèn)值都是 null
  • 一個(gè)引用變量可以用來(lái)引用任何與之兼容的類(lèi)型

(5) 常量 final

  • 常量通常大寫(xiě)
final double PI = 3.1415927;

(6) 自動(dòng)類(lèi)型轉(zhuǎn)換

int i = 128;   
byte b = (byte)i;

(7) List 和 ArrayList 的區(qū)別

List<SomeObject> myList = new ArrayList<SomeObject>();
ArrayList<SomeObject> myList = new ArrayList<SomeObject>();

區(qū)別:
(1) List是一個(gè)接口,它沒(méi)有實(shí)現(xiàn)任何屬性和方法,在List上如果調(diào)用方法,實(shí)際上是調(diào)用的 ArrayList 的方法
(2) List是一個(gè)接口,需要使用實(shí)現(xiàn)類(lèi),比如ArrayList
(3) 使用方式不同:Array數(shù)組使用下標(biāo)獲取元素,List是get
(4) 初始化:Array數(shù)組必須指定大小,不靈活。List 可以自己擴(kuò)充大小,方便

(8) IOC AOP

  • IOC 控制反轉(zhuǎn)/依賴注入 => Bean對(duì)象的實(shí)例化 Bean對(duì)象的創(chuàng)建
  • AOP 面向切面編程 => 動(dòng)態(tài)代理
  • Spring JDBC + 事務(wù)
    image

    image

(二) SpringBoot常用注解

(1) @RestController

  • @RestController = @Controller + @ResponseBody
  • 特點(diǎn)
    • 添加該注解后,Controller類(lèi)中的方法 無(wú)法返回頁(yè)面
    • 相當(dāng)于在方法上自動(dòng)加了 @ResponseBody 注解,所以 沒(méi)辦法跳轉(zhuǎn)并傳入數(shù)據(jù)到另一個(gè)頁(yè)面
    • 返會(huì)的內(nèi)容就是 return 的內(nèi)容

(2) @GetMapping @PostMapping @PutMappiing @DeleteMapping

(3) @PathVariable @CookieValue @RequestHeader @ReqeustAttribute @RequestParam @RequestBody @MatrixVariable

  • @PathVariable 在 RESTful 風(fēng)格下url中獲取路徑變量
// 測(cè)試 request
// 測(cè)試 @PathVariable
// 測(cè)試 @CookieValue
// 測(cè)試 @RequestHeader => 對(duì)比 @RequestParam @RequestBody @RequestPart
// 測(cè)試 @RequestAttribute
// 測(cè)試 @RequestParam
// 測(cè)試 @RequestBody
// 測(cè)試URL:http://localhost:7777/car/1/owner/woow_wu7?age=20&city=chongqing
@GetMapping("/car/{id}/owner/{username}")
public Void getPath(
        HttpServletRequest request,
        @PathVariable("id") int id,
        @PathVariable("username") String username,
        @PathVariable Map<String, String> pathVariable,
        // @CookieValue("name") String name,
        @RequestHeader("User-Agent") String userAgent,
        @RequestHeader Map<String, String> headers,
        @RequestParam("age") int age,
        @RequestParam Map<String, String> params
        // @RequestBody String body
        // @RequestAttribute("message") String message
) {
    log.info("@PathVariable('id') => id:{}, username: {}", id, username);
    log.info("@PathVariable Map<String, String> => 可以用一個(gè)map對(duì)象,接收所有的path變量 => pv: {}", pathVariable);
    String tempId = pathVariable.get("id"); // Map實(shí)例有 ( map.get ) ( map.put ) 等方法
    System.out.println(tempId);

    log.info("@RequestHeader('User-Agent') => User-Agent: {}", userAgent);
    log.info("@RequestHeader Map<String, String> => headers: {}", headers);

    log.info("@RequestParam Map<String, String> => params: {}", params);
    // log.info("@CookieValue('name') => name: {}", name);
    // log.info("@RequestBody String body => 可以獲取post請(qǐng)求的body,也可以是一個(gè)Map實(shí)例,比如 @RequestBody Map<String, Object> body ====> body{}", body);

    request.setAttribute("message", "success");
    log.info("request: {}", request.getAttribute("message"));
    return null;
}

(4) @Configuration配置類(lèi)的注解 + @Bean向容器中注冊(cè)組件

  • @Configuration => 可以理解為xml中的 beans 標(biāo)簽
    • 作用:是告訴springboot標(biāo)注的類(lèi)是一個(gè) 配置類(lèi)
    • 注意點(diǎn):@Configuration 標(biāo)注的 配置類(lèi)本身也是組件
    • 參數(shù):@Configuration(proxyBeanMethods = true)
  • @Bean => 可以理解為xml中的 bean 標(biāo)簽
    • 作用:向容器中添加組件,并且添加的組件是 ( 單實(shí)例 )
    • 組件ID:是方法名
    • 返回類(lèi)型:就是組件的類(lèi)型
    • 返回值:就是組件在容器中的實(shí)例
    • @Bean(組件名) => @Bean()的參數(shù)可以重命名組件名,而不是用方法名
(1) 
/src/main/java/com.example.demo/config/PetConfig.java
-------

// 1. 對(duì)比參考 UserConfig 類(lèi)
// 2. @Configuration 標(biāo)注的類(lèi)是配置類(lèi),配置類(lèi)本身也是組件
// 3. 外界無(wú)論對(duì)配置類(lèi)中的這個(gè)注冊(cè)方法調(diào)用多少次獲取的都是之前容器中的單實(shí)例,前提是 @Configuration(proxyBeanMethods = true
// 4. 如果 @Configuration(proxyBeanMethods = false) 外界調(diào)用拿到的就不是 ( 代理對(duì)象 ),就 ( 不是單實(shí)例 ) 的了
@Configuration // 配置類(lèi) => 相當(dāng)于以前的xml配置文件,xml中有 beans bean 標(biāo)簽
public class PetConfig {
    @Bean // 向容器中注冊(cè)組件 => @Bean(pet02)這樣寫(xiě)可以把注冊(cè)到容器中的組件重新命名為pet02,而不是用方法名pet01
    public PetBean pet01() {
        return new PetBean("dog", "white");
    }
}
(2) 
問(wèn)題:如何驗(yàn)證組件已經(jīng)注冊(cè)到容器中呢?
回答:在主類(lèi)中可以查看,因?yàn)橹黝?lèi)中通過(guò) IOC 可以通過(guò) run.getBeanDefinitionNames() 獲取到組件名數(shù)組

問(wèn)題:如果獲取到容器中的組件呢?
回答:run.getBean 來(lái)獲取


具體代碼:
// 主程序類(lèi),主配置類(lèi)
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        // 1. 返回 IOC 容器
        // 2. IOC的作用是:控制反轉(zhuǎn) 和 依賴注入
        ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);

        // 3. 查看容器里的組件
        String[] beanDefinitionNames = run.getBeanDefinitionNames();
        for (String name : beanDefinitionNames) {
              System.out.println(name);
        }

        // 3. 從容器中獲取組件 userX
        UserBean userX1 = run.getBean("userX", UserBean.class);
        UserBean userX2 = run.getBean("userX", UserBean.class);
        System.out.println("組件:" + (userX1 == userX2));
        System.out.println("上面是true,因?yàn)樽?cè)的組件默認(rèn)就是單實(shí)例的,因?yàn)锧Bean給容器注冊(cè)的組件是單實(shí)例的");

        // 3. 從容器中獲取組件 pet01
        PetBean pet01 = run.getBean("pet01", PetBean.class);
        System.out.println(pet01.getName()); // 獲取pet01對(duì)象中的name屬性
    }
}

(5) @ConditionalOnBean 條件裝配注解

  • @ConditionalOnBean(name) 表示IOC容器中存在 ( name組件 ) 時(shí),才向容器中添加 ( @ConditionalOnBean ) 組件,不存在name就不添加
  • @ConditionalOnBean(name) 如果標(biāo)注在類(lèi)上,則表示類(lèi)里面所有@Bean生效的前提是:容器中有name組件
  • 一般都場(chǎng)景啟動(dòng)器中就有非常多的各種條件注解,條件判斷
  • 在IOC中
    • 1.優(yōu)先解析 @Component,@Service,@Controller,@Mapper等注解類(lèi)
    • 2.再解析配置類(lèi),即@Configuration標(biāo)注的類(lèi)
    • 3.最后解析配置類(lèi)中定義的 @Bean
@Configuration
// @ConditionalOnBean(name = "com.example.demo.bean.ImportBean") 如果標(biāo)注在類(lèi)上,則表示里面所有@Bean生效的前提是容器中有com.example.demo.bean.ImportBean組件
public class TestConditionalOnBeanConfig {

    // @ConditionalOnBean(name) 表示IOC容器中存在 ( name組件 ) 時(shí),才向容器中添加 ( @ConditionalOnBean ) 組件,不存在name就不添加
    // @ConditionalOnBean(name) 如果標(biāo)注在類(lèi)上,則表示類(lèi)里面所有@Bean生效的前提是:容器中有name組件
    // - 在IOC中
      // - 1.優(yōu)先解析 `@Component,@Service,@Controller,@Mapper`等注解類(lèi)
      // - 2.再解析配置類(lèi),即`@Configuration`標(biāo)注的類(lèi)
      // - 3.最后解析配置類(lèi)中定義的 `@Bean`
    @ConditionalOnBean(name = "com.example.demo.bean.ImportBean")
    @Bean("@ConditionalOnBean")
    public TestConditionalOnBeanBean registerConditionalOnBean() {
        return new TestConditionalOnBeanBean("@ConditionalOnBean");
    }
}

(5) @Import 向容器中添加組件

  • @Import 和 @Bean 的作用類(lèi)似,都是向容器中添加組
  • 語(yǔ)法:@Import({ 類(lèi)名.class, 類(lèi)名.class... })
  • 組件名:@Import導(dǎo)入容器中的組件名默認(rèn)是 ( 全類(lèi)名 )
  • 注意點(diǎn):
    • @Import()必須用在組件類(lèi)上,組件肯定是在springboot IOC容器中的
    • @Import() 比如用在@Config @Controller @Service 等組件上都可以
    • @Import()可以導(dǎo)入第三方包
src/main/java/com.example.demo/config/PetConfig.java
-------

// @Import
// 1. @Import 和 @Bean 的作用類(lèi)似,都是向容器中添加組
// 2. @Import導(dǎo)入容器中的組件名默認(rèn)是 ( `全類(lèi)名` )
@Import({UserBean.class, PetBean.class})
@Configuration(proxyBeanMethods = true) // 配置類(lèi) => 相當(dāng)于以前的xml配置文件,xml中有 beans bean 標(biāo)簽
public class PetConfig {
    @Bean // 向容器中注冊(cè)組件 => @Bean(pet02)這樣寫(xiě)可以把注冊(cè)到容器中的組件重新命名為pet02,而不是用方法名pet01
    public PetBean pet01() {
        return new PetBean("dog", "white");
    }
}

// 以上打印的話
// @Import向容器添加的組件名是:com.example.demo.bean.PetBean
// @Bean向容器添加的組件名是:pet01

(6) @ImportResource 把傳統(tǒng)的xml文件配置的組件添加到容器中

  • @ImportResource("classpath:beans/beans.xml")
    • 參數(shù):classpath:beans/beans.xml 表示的是 配置組件beans.xml的文件路徑
    • 具體:beans.xml 被放在了 src/main/resources/beans/beans.xml
(1)
src/main/java/com.example.demo/config/PetConig.java
-------

// @ImportResource
// 1. @ImportResource("classpath:beans/beans.xml")
// 2. 參數(shù):`classpath:beans/beans.xml` 表示的是 `配置組件beans.xml的文件路徑`
// 3. 具體:`beans.xml` 被放在了 `src/main/resources/beans/beans.xml` 中
@Import({UserBean.class, PetBean.class})
@Configuration(proxyBeanMethods = true) // 配置類(lèi) => 相當(dāng)于以前的xml配置文件,xml中有 beans bean 標(biāo)簽
@ImportResource("classpath:beans/beans.xml")
public class PetConfig {

    @Bean // 向容器中注冊(cè)組件 => @Bean(pet02)這樣寫(xiě)可以把注冊(cè)到容器中的組件重新命名為pet02,而不是用方法名pet01
    public PetBean pet01() {
        return new PetBean("dog", "white");
    }
}
(2)
src/main/resources/beans/beans.xml
-------

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
        
    <!--UserBean-->
    <bean id="haha" class="com.example.demo.bean.UserBean">
        <property name="name" value="zhangsan"></property>
        <property name="age" value="20"></property>
    </bean>
    <!--PetBean-->
    <bean id="hehe" class="com.example.demo.bean.PetBean">
        <property name="name" value="dog"></property>
        <property name="color" value="red"></property>
    </bean>
</beans>

(7) @ConfigurationProperties + @Component 實(shí)現(xiàn)配置綁定

  • @ConfigurationProperties(prefix = "myapp")
  • @Compoennt的作用是將類(lèi)組件添加到容器中
(1)
src/main/java/com.example.demo/bean/AppMessageBean.java
-------

// 1. 只有在容器中的組件才能獲取 SpringBoot 的強(qiáng)大功能,也就是說(shuō)要使用@ConfigurationProperties()必須用@Component將對(duì)象標(biāo)記成容器組件
// 2. 該 bean 對(duì)象主要是測(cè)試 @ConfigurationProperties 和 @Component 兩個(gè)注解
// 3. 如果類(lèi)中的屬性多于application.yml文件中的myapp的話,多的屬性返回的是null
@Data
@Component
@ConfigurationProperties(prefix = "myapp") // prefix="myapp" 這個(gè)前綴的值是在 application.yml 文件中配置的
public class AppMessageBean {
    private String name;
    private String email;
    private String author;
    private String other;
}
(2)
src/main/resources/application.yml
-------

myapp:
  # 自定義的配置參數(shù),這里主要用來(lái)驗(yàn)證 @ConfigurationProperties 注解的使用
  author: woow_wu7
  name: react-admin-java
  email: woow.wu7@gmail.com
(3)
src/main/java/com.example.demo/controller/TestController.java
-------
    @Autowired
    AppMessageBean appMessageBean;

    // (1)
    // 測(cè)試: @ConfigurationProperties 和 @Component 兩個(gè)注解
    // 教程: https://www.cnblogs.com/jimoer/p/11374229.html
    @GetMapping("/@ConfigurationProperties")
    public AppMessageBean getAuthorName() {
        System.out.println(appMessageBean);
        String author = appMessageBean.getAuthor();
        System.out.println(author);
        return appMessageBean;
    }

(8) @SpringBootTest + @Test 單元測(cè)試

  • 1.引入maven場(chǎng)景啟動(dòng)器 spring-boot-starter-test
<!-- spring-boot-starter-test -->
<!-- 單元測(cè)試場(chǎng)景啟動(dòng)器 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
  • 2.編譯一個(gè)測(cè)試類(lèi)
src/test/java/com.example.demo/ApplicationTests.java
-------
@SpringBootTest
class ApplicationTests {
    @Test
    void contextLoads() { dosomething...}
}

(三) 修改maven依賴包的版本號(hào)的兩種方法

以mysql為例

(1) 在 pom.xml 中通過(guò) version 標(biāo)簽來(lái)指定 ( 原理是maven的就近依賴原則 )

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.21</version>
    <scope>runtime</scope>
</dependency>

(2) 在 pom.xml 中通過(guò) properties 標(biāo)簽來(lái)修改 ( 原理是maven屬性的就近優(yōu)先原則 )

<properties>
    <java.version>1.8</java.version>
    <!-- 除了修改version還可以在properties中來(lái)修改依賴的版本號(hào) -->
    <!-- <mysql.version>8.0.21</mysql.version>  -->
</properties>

(四) 數(shù)據(jù)訪問(wèn)

(1) mysql驅(qū)動(dòng) + JDBC數(shù)據(jù)庫(kù)連接池 = springboot最基礎(chǔ)的操作mysql的方式

  • 在這基礎(chǔ)上還可以添加 mybatis 來(lái)操作數(shù)據(jù)庫(kù)
  • 1.安裝:mysql驅(qū)動(dòng) => mysql-connector-java
  • 2.安裝:jdbc數(shù)據(jù)庫(kù)連接池 => spring-boot-starter-data-jdbc ( 區(qū)分:spring-boot-starter-jdbc )
  • 3.配置項(xiàng):spring.datasource...
  • 4.數(shù)據(jù)源:HikariDataSource
spring:
  datasource:
    # 1. 只要裝了 ( mysql驅(qū)動(dòng) ) 和 ( jdbc數(shù)據(jù)庫(kù)連接池 ),并且在這里配置好 ( 數(shù)據(jù)庫(kù)連接池相關(guān)的配置項(xiàng) ) 就能連接數(shù)據(jù)庫(kù)
    # 2. mysql驅(qū)動(dòng) => mysql-connector-java
    # 3. jdbc連接池 => spring-boot-starter-jdbc 
    # 4. 更進(jìn)一步:還可以使用 ( Druid數(shù)據(jù)源 + MyBatis )
    url: jdbc:mysql://localhost:3306/7-react-admin-java?serverTimezone=GMT%2B8&useSSL=false
    username: root
    password: root
    dirver-class-name: com.mysql.cj.jdbc.Driver
  jdbc:
    template:
      query-timeout: 10 # 10s沒(méi)查出來(lái)就超時(shí)
  • 4.通過(guò)springBoot容器中的 JdbcTemplate 就行操作數(shù)據(jù)庫(kù) ( 單元測(cè)試 )
src/test/com.example.demo/ApplicationTests.java
-------

@SpringBootTest
@Slf4j
class ApplicationTests {
    @Autowired
    JdbcTemplate jdbcTemplate; // 自動(dòng)注入容器中的 JdbcTemplate
    @Test
    void contextLoads() {
        Long aLong = jdbcTemplate.queryForObject("select count(*) from music", Long.class); // 操作數(shù)據(jù)庫(kù)
        log.info("music總數(shù)據(jù)量:{}", aLong);
    }
}

(2) HikariDataSource 和 Druid數(shù)據(jù)源 => 濾過(guò)Druid數(shù)據(jù)源

(五) Redis

Redis是一個(gè)開(kāi)源的,( 內(nèi)存中 ) 的 ( 數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng) ),它可以用作 ( 數(shù)據(jù)庫(kù) ) ( 緩存 ) ( 消息中間件 )

(1) 導(dǎo)入maven的依賴包,即redis的場(chǎng)景啟動(dòng)器

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

(2) 查看springboot的autoconfigure中的redis的 ( 自動(dòng)配置類(lèi) )

  • 目錄:External Libraries/spring-boot-autoconfigure:2.4.2/data/redis/RedisAutoConfiguration.java
  • external 外部的意思
  • external libraries 擴(kuò)展類(lèi)庫(kù)的意思
  • RedisAutoConfiguration.java (1)
    • redis自動(dòng)配置:
      • @EnableConfigurationProperties(RedisProperties.class) (2)
      • spring.redis.xxx (3)
      • RedisAutoConfiguration.java => @EnableConfigurationProperties(RedisProperties.class) => spring.redis.xxx是對(duì)redis的配置,也就是說(shuō)可以在application.yml中去做redis相關(guān)的配置,比如 spring.redis.xxx
    • 連接工廠是準(zhǔn)備好的 ( 兩種 )
      • Lettuce => LettuceConnectionConfiguration
      • Jedis => JedisConnectionConfiguration
    • 操作redis
      • 自動(dòng)注入了下面兩個(gè)組件類(lèi)
      • RedisTemplate<Object, Object>
        • key: value
        • 對(duì)比 JdbcTemplate
      • StringRedisTemplate
        • key 和 value 都是 String

(3) 申請(qǐng)一個(gè)阿里云的 redis 服務(wù)器,并申請(qǐng)redis公網(wǎng)連接地址,和設(shè)置白名單,用戶權(quán)限(讀寫(xiě))等

image

image

image

image

(4) 下載安裝 redis 和 redis客戶端

  • 下載連接
  • redis下載安裝教程
  • windows系統(tǒng)redis客戶端下載連接
  • redis常用命令
  • redis的使用
    • 1.在windows系統(tǒng)上安裝完成后,在解壓的目錄下雙擊 redis-cli.exe 運(yùn)行
    • 2.除了雙擊運(yùn)行,也可以在該文件夾下打開(kāi)cmd,輸入 ./redis-cli.exe命令
  • redis常用命令
    • 獲取讀寫(xiě)權(quán)限
      • auth username:password
      • auth password
    • 是否禁用redis
      • config set disable [yes|no]
    • 查詢默認(rèn)密碼 ( 登陸后才可以操作 )
      • config get requirepass
    • 修改密碼 ( 登陸后才可以操作 )
      • config set requirepass 123456
    • 登陸redis
      • ./redis-cli -p 6379 -a 123456
    • 啟動(dòng)服務(wù)
      • ./redis-server --service-start
    • 停止服務(wù)
      • ./redis-server --service-stop
    • string
      • set key value 設(shè)置鍵值
      • get key 獲取鍵值
      • del key 刪除鍵值
      • mget key1 key2 同時(shí)獲取
      • exists key 檢查key是否存在
    • list => 是鏈表
      • lpush key value1 value2 在key所關(guān)聯(lián)的list的頭部 ( 插入 ) 所有value值
      • rpush key value1 value2 在key所關(guān)聯(lián)的list的頭部 ( 插入 ) 所有value值
      • lrange key start end 獲取key鏈表中從start到end的元素的值,start、end可 為負(fù)數(shù),若為-1則表示鏈表尾部的元素
      • lpushx key value 當(dāng)key存在時(shí)才leftpush,如果不加x不存在時(shí)會(huì)新建
      • lpop key 返回并彈出指定的key關(guān)聯(lián)的鏈表中的第一個(gè)元素,即頭部元素
    • set => 是數(shù)組加鏈表
      • sadd key value1 value2 向set中添加數(shù)據(jù),如果該key的值已有則不會(huì) 重復(fù)添加 l`
      • smembers key 獲取set中所有的成員
      • scard key 獲取set中成員的數(shù)量
      • srem key member1、member2 刪除set中指定的成員
    • zset
      • zset中的每一個(gè)成員都會(huì)有一個(gè)分 數(shù)(score)與之關(guān)聯(lián),Redis正是通過(guò)分?jǐn)?shù)來(lái)為集合中的成員進(jìn)行從小到大的排序
      • zadd key score member score2 member2 將所有成員以及該成員的 分?jǐn)?shù)存放到sorted-set中
    • hash
      • Redis中的Hashes類(lèi)型可以看成具有String Key和String Value的map容器,所以適合存儲(chǔ)值是對(duì)象的信息,比如 username
      • hset key fild value 為指定的key設(shè)定field/value對(duì)(鍵值對(duì))
      • hgetall key 獲取key中的所有filed-vaule
        image

(5) 在application.properties 或 applicatioin.yml中配置 redis

spring:
  redis:
    # 可以通過(guò) (external libraries)/spring-boot-autoconfigure:2.4.2/data/redis/RedisAutoConfiguration/RedisProperties/url 來(lái)查看
    # url = redis://user:password@example.com:6379
    host: r-bp1z4zrytbuyv7mkuzpd.redis.rds.aliyuncs.com
    port: 6379
    password: woow_wu7:ALy123456789

(6) 在springboot的測(cè)試類(lèi)中測(cè)試 讀寫(xiě)redis

src/test/java/com.example.demo/ApplicationTests.java
-------

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    RedisTemplate redisTemplate;
    
    @Test
    void testRedis() {
        ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
        stringStringValueOperations.set("redis", "ok"); // string set
        String redis = stringStringValueOperations.get("redis"); // string get
        log.info("redis: {}", redis);
    }
image

(7) 從 Lettuce 切換到 Jedis

  • springboot中默認(rèn)使用的是 Lettuce,如何切換成 Jedis
(1) 導(dǎo)入依賴
        <!-- jedis -->
        <!-- SpringBoot默認(rèn)使用的是Lettuce,要切換成jedis就必須安裝該依賴 -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
   
(2) 修改配置
  redis:
    # 可以通過(guò) (external libraries)/spring-boot-autoconfigure:2.4.2/data/redis/RedisAutoConfiguration/RedisProperties/url 來(lái)查看
    # url = redis://user:password@example.com:6379
    host: r-bp1z4zrytbuyv7mkuzpd.redis.rds.aliyuncs.com
    port: 6379
    password: woow_wu7:ALy123456789
    client-type: jedis #兩種,默認(rèn)是 Lettuce

(3) 測(cè)試
    @Autowired
    RedisConnectionFactory redisConnectionFactory;

    @Test
    void testRedis() {
        ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
        stringStringValueOperations.set("redis", "ok");
        String redis = stringStringValueOperations.get("redis");
        log.info("redis: {}", redis);

        // 打印 redis 的連接工廠是用的 Lettuce 還是 jedis
        log.info(String.valueOf(redisConnectionFactory.getClass()));
    }

(8) 實(shí)現(xiàn)一個(gè)小功能 => 統(tǒng)計(jì)每個(gè)url訪問(wèn)的次數(shù)

  • 在springboot連接好redis后
  • 原理
    • 1.通過(guò) Interceptor 攔截除去登陸,靜態(tài)資源外的所有請(qǐng)求
    • 2.在攔截器中實(shí)現(xiàn) HandlerInterceptor 接口的前置鉤子 preHandle 方法
    • 3.在 preHandle 方法中通過(guò)獲取自動(dòng)注入的 StringRedisTemplateopsForValue()increment() 方法實(shí)現(xiàn)統(tǒng)計(jì)
    • 4.redis => 中的 increment(url)方法,key=url, value=計(jì)數(shù)
    • 5.攔截器通過(guò) @Component 添加到容器中,在配置類(lèi)中實(shí)現(xiàn) WebMvcConfigurer 接口的 addInterceptors 方法實(shí)現(xiàn)攔截
  • 詳細(xì)步驟
(1)
src/mian/java/com.example.demo/interceptor/RedisUrlCountInteceptor.java
-------

/**
 * Interceptor 和 Filter 都具有相同的功能
 * 區(qū)別:
 *  1. Filter: 是Servlet定義的原生組件,好處是脫離spring也能使用
 *  2. Interceptor: 是spring定義的接口,只能在spring中使用,可以使用Spring的 ( 自動(dòng)裝配 ) 等功能
 */
@Component // 將攔截器放到容器中
public class RedisUrlCountInterceptor implements HandlerInterceptor {

    @Autowired
    StringRedisTemplate stringRedisTemplate; // 自動(dòng)注入操作redis的容器中的組件類(lèi)

    // preHandle 前置鉤子
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        // stringRedisTemplate.opsForValue().increment(url) => 該方法每次訪問(wèn)該地址,url計(jì)數(shù)都會(huì)+1
        stringRedisTemplate.opsForValue().increment(requestURI);
        return true;
    }
}
(2)
src/main/java/com.example.demo/config/AdminWebConfig.java
-------

/**
 * 攔截器
 * 1. 編寫(xiě)一個(gè)攔截器,實(shí)現(xiàn) HandlerInterceptor 接口
 * 2. 把攔截器注冊(cè)到容器中 ( 實(shí)現(xiàn) WebMvcConfigurer 接口的  addInterceptors 方法)
 * 3. 指定攔截規(guī)則 【如果攔截所有,靜態(tài)資源也會(huì)被攔截,可以用 excludePathPatterns 方法放行】
 */
// @Configuration 用于定義 ( 配置類(lèi) )
@Configuration
@EnableConfigurationProperties
public class AdminWebConfig implements WebMvcConfigurer {

    // 這里之所以可以自動(dòng)注入,是因?yàn)镽edisUrlCountInterceptor類(lèi)通過(guò)@Compoent注冊(cè)到容器中了,非配置類(lèi)
    @Autowired
    RedisUrlCountInterceptor redisUrlCountInterceptor;

    // @Override表示被標(biāo)注的方法是一個(gè)重寫(xiě)方法
    // override 覆蓋
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(redisUrlCountInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/", "/login", "css/**", "/fonts/**", "/images/**", "/js/**");
    }
}
image

項(xiàng)目源碼

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容