ishowcode.eth

ishowcode.eth

区块链小白

純手寫爆肝史上最詳細講解SpringBoot

SpringBoot 基礎#

一、SpringBoot 簡介#

1.1. 什麼是 Spring Boot#

Spring Boot 是 Spring 項目中的一個子工程,與我們所熟知的 Spring-framework 同屬於 spring 的產品:

在這裡插入圖片描述

一般把 Spring Boot 稱為搭建程序的腳手架或者說是便捷搭建基於 Spring 的工程腳手架。其最主要作用就是幫助開發人員快速的構建龐大的 spring 項目,並且盡可能的減少一切 xml 配置,做到開箱即用,迅速上手,讓開發人員關注業務而非配置。

1.2. 為什麼要學習 Spring Boot#

java 一直被人詬病的一點就是臃腫、麻煩。究其原因注意是兩點:

複雜的配置

項目各種配置其實是開發時的損耗,因為在思考 Spring 特性配置和解決業務問題之間需要進行思維切換,所以寫配置擠佔了寫應用程序邏輯的時間。

混亂的依賴管理

項目的依賴管理也是件吃力不討好的事情。決定項目裡要用哪些庫就已經夠讓人頭痛的了,你還要知道這些庫的哪個版本和其他庫不會有衝突,這難題實在太棘手。並且,依賴管理也是一種損耗,添加依賴不是寫應用程序代碼。一旦選錯了依賴的版本,隨之而來的不兼容問題毫無疑問會是生產力殺手。

而 Spring Boot 讓這一切成為過去!

Spring Boot簡化了基於Spring的應用開發,只需要“run”就能創建一個獨立的、生成級別的Spring應用。Spring Boot為Spring平台及第三方庫提供開箱即用的設置(提供默認設置,存放默認配置的包就是啟動器starter),這樣我們就可以簡單的開始。多數Spring Boot應用只需要很少的Spring配置。

我們可以使用 Spring Boot 創建 java 應用,並使用 java –jar 啟動它,就能得到一個生成級別的 web 工程。

1.3. Spring Boot 的特點#

1.3.1 SpringBoot 的特點#

  • 為基於 Spring 的開發提供更快的入門體驗
  • 開箱即用,沒有代碼生成,也無需 XML 配置。同時也可以修改默認值來滿足特定的需求
  • 提供了一些大型項目中常見的非功能性特性,如嵌入式伺服器、安全、指標,健康檢測、外部配置等
    SpringBoot 不是對 Spring 功能上的增強,而是提供了一種快速使用 Spring 的方式

二、SpringBoot 快速入門#

接下來,我們就來利用 Spring Boot 搭建一個 web 工程,體會一下 Spring Boot 的魅力所在!

2.1 創建 Maven 工程#

使用 idea 工具創建一個 maven 工程,該工程為普通的 java 工程即可

在這裡插入圖片描述

2.2 添加 SpringBoot 的起步依賴#

看到這裡很多同學會有疑惑,前面說傳統開發的問題之一就是依賴管理混亂,怎麼這裡我們還需要管理依賴呢?難道 Spring Boot 不幫我們管理嗎?別著急,現在我們的項目與 Spring Boot 還沒有什麼關聯。Spring Boot 提供了一個名為 spring-boot-starter-parent 的工程,裡面已經對各種常用依賴(並非全部)的版本進行了管理,我們的項目需要以這個項目為父工程,這樣我們就不用操心依賴的版本問題了,需要什麼依賴,直接引入坐標即可。

2.2.1. 添加父工程坐標#

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐parent</artifactId>
<version>2.1.5.RELEASE</version>
</parent>

2.2.2. 添加 web 啟動器#

為了讓 Spring Boot 幫我們完成各種自動配置,我們必須引入 Spring Boot 提供的自動配置依賴,我們稱為啟動器。因為我們是 web 項目,這裡我們引入 web 啟動器,在 pom.xml 文件中加入如下依賴:

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐web</artifactId>
</dependency>
</dependencies>

需要注意的是,我們並沒有在這裡指定版本信息。因為 Spring Boot 的父工程已經對版本進行了管理了。這個時候,我們會發現項目中多出了大量的依賴。那些依賴都是 Spring Boot 根據 spring-boot-starter-web 這個依賴自動引入的,而且所有的版本都已經管理好,不會出現衝突。

2.3 編寫 SpringBoot 引導類和 Controller#

要通過 SpringBoot 提供的引導類起步 SpringBoot 才可以進行訪問

package com.summer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MySpringBootApplication {
    public static void main(String[] args) {
SpringApplication.run(MySpringBootApplication.class);
}
}

在引導類 MySpringBootApplication 同級包或者子級包中創建 QuickStartController

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class QuickController {
@RequestMapping("/quick")
@ResponseBody
public String quick(){
return "springboot訪問成功!";
}
}
@ResponseBody註解作用其實是將java對象轉為json格式的數據響應給客戶端,如果返回值是字符串,那麼直接將字符串寫到客戶端

2.4 啟動測試#

執行 SpringBoot 起步類的主方法,控制台打印日誌如下:

在這裡插入圖片描述

在這裡插入圖片描述

通過日誌發現,Tomcat started on port (s): 8080 (http) with context path '' tomcat 已經起步,端口監聽 8080,web 應用的虛擬工程名稱為空 打開瀏覽器訪問 url 地址為:http://localhost:8080/quick

2.5 SpringBoot 工程熱部署#

我們在開發中反復修改類、頁面等資源,每次修改後都是需要重新啟動才生效,這樣每次啟動都很麻煩,浪費了大量的時間,我們可以在修改代碼後不重啟就能生效,在 pom.xml 中添加如下配置就可以實現這樣的功能,我們稱之為熱部署。

<!‐‐熱部署配置‐‐>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐devtools</artifactId>
</dependency>

注意:IDEA 進行 SpringBoot 熱部署失敗原因 出現這種情況,並不是熱部署配置問題,其根本原因是因為 Intellij IDEA 默認情況下不會自動編譯,需要對 IDEA 進行自動編譯的設置,如下:

在這裡插入圖片描述

然後 Shift+Ctrl+Alt+/,選擇 Registry

在這裡插入圖片描述

2.6 使用 idea 快速創建 SpringBoot 項目#

通過 idea 快速創建的 SpringBoot 項目的 pom.xml 中已經導入了我們選擇的 web 的起步依賴的坐標

在這裡插入圖片描述

可以使用快速入門的方式創建 Controller 進行訪問,此處不再贅述

三、 java 配置應用#

在入門案例中,我們沒有任何的配置,就可以實現一個 SpringMVC 的項目了,快速、高效!但是有同學會有疑問,如果沒有任何的 xml,那麼我們如果要配置一個 Bean 該怎麼辦?比如我們要配置一個數據庫連接池,以前會這麼配置:

<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

3.1. Spring 配置歷史#

事實上,在 Spring3.0 開始,Spring 官方就已經開始推薦使用 java 配置來代替傳統的 xml 配置了,我們不妨來回顧一下 Spring 的歷史:

  • Spring1.0 時代 在此時因為 jdk1.5 剛剛出來,註解開發並未盛行,因此一切 Spring 配置都是 xml 格式,想象一下所有的 bean 都用 xml 配置,細思極恐啊,心疼那個時候的程序員 2 秒

  • Spring2.0 時代 Spring 引入了註解開發,但是因為並不完善,因此並未完全替代 xml,此時的程序員往往是把 xml 與註解進行結合,貌似我們之前都是這種方式

  • Spring3.0 及以後 3.0 以後 Spring 的註解已經非常完善了,因此 Spring 推薦大家使用完全的 java 配置來代替以前的 xml,不過似乎在國內並未推廣盛行。然後當 Spring Boot 來臨,人們才慢慢認識到 java 配置的優雅。

  • 有句古話說的好:擁抱變化,擁抱未來。所以我們也應該順應時代潮流,做時尚的弄潮兒,一起來學習下 java 配置的玩法。

3.2. 嘗試 java 配置#

java 配置主要靠 java 類和一些註解,比較常用的註解有:

  • @Configuration:聲明一個類作為配置類,代替 xml 文件
  • @Bean:聲明在方法上,將方法的返回值加入 Bean 容器,代替標籤
  • @Value:屬性注入
  • @PropertySource:加載外部屬性文件

我們接下來用 java 配置來嘗試實現連接池配置:

  1. 在 pom.xml 文件中添加 Druid 連接池依賴如下
<!‐‐ Druid連接池 ‐‐>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>

2.jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root
  1. 配置類
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
@Value("${jdbc.url}")
String url;
@Value("${jdbc.driverClassName}")
String driverClassName;
@Value("${jdbc.username}")
String username;
@Value("${jdbc.password}")
String password;
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
  • 解讀:
  • @Configuration:聲明我們 JdbcConfig 是一個配置類
  • @PropertySource:指定屬性文件的路徑是: classpath.properties
  • 通過 @Value 為屬性注入值
  • 通過 @Bean 將 dataSource () 方法聲明為一個註冊 Bean 的方法,Spring 會自動調用該方法,將方法的返回值加入 Spring 容器中。
    然後我們就可以在任意位置通過 @Autowired 注入 DataSource 了!
  1. 測試
@Controller
public class QuickController {
@Autowired
private DataSource dataSource;
@RequestMapping("/quick")
@ResponseBody
public String hello() {
System.out.println("dataSource = " + dataSource);
return "hello, spring boot!";
}
}

3.3. Spring Boot 的屬性注入#

在上面的案例中我們實驗了 java 配置方式。不過屬性注入使用的是 @Value 註解。這種方式雖然可行,但是不夠強大,因為它只能注入基本類型值。在 Spring Boot 中,提供了一種新的屬性注入方式,支持各種 java 基本數據類型及複雜類型的注入。屬性文件的名稱有變化,默認的文件名必須是:

application.propertiesapplication.yml

/
/將該類聲明為屬性讀取類
@ConfigurationProperties(prefix ="jdbc")
public class JdbcProperties {
private String driverClassName;
private String url;
private String username;
private String password;
// ... 略
// getters和setters
}
  • 在類上通過 @ConfigurationProperties 註解聲明當前類為屬性讀取類
  • prefix="jdbc" 讀取屬性文件中,前綴為 jdbc 的值。
  • 在類上定義各個屬性,名稱必須與屬性文件中 jdbc. 後面部分一致
  • 需要注意的是,這裡我們並沒有指定屬性文件的地址,所以我們需要把 jdbc.properties 名稱改為 application.properties,這是 Spring Boot 默認讀取的屬性文件名
    【注意】如果出現如下提示,項目也可以運行;

在這裡插入圖片描述

如果要去掉上述的提示,則可以在 pom.xml 文件中添加如下依賴:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐configuration‐processor</artifactId>
<!‐‐不傳遞依賴‐‐>
<optional>true</optional>
</dependency>

優雅的注入

@Configuration
@EnableConfigurationProperties(JdbcProperties.class)
public class JdbcConfig {
@Bean
public DataSource dataSource(JdbcProperties jdbc) {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(jdbc.getUrl());
dataSource.setDriverClassName(jdbc.getDriverClassName());
dataSource.setUsername(jdbc.getUsername());
dataSource.setPassword(jdbc.getPassword());
return dataSource;
}
}

更優雅的注入 事實上,如果一段屬性只有一個 Bean 需要使用,我們無需將其注入到一個類(JdbcProperties,將該類上的所有註解去掉)中。而是直接在需要的地方聲明即可;再次修改 JdbcConfig 類為如下代碼:

@Configuration
public class JdbcConfig {
@Bean
// 聲明要注入的屬性前綴,Spring Boot會自動把相關屬性通過set方法注入到DataSource中
@ConfigurationProperties(prefix = "jdbc")
public DataSource dataSource() {
return new DruidDataSource();
}
}

3.4 Yaml 配置文件#

配置文件除了可以使用 application.properties 類型,還可以使用後綴名為:.yml 或者.yaml 的類型,也就是:application.yml 或者 application.yaml yaml 與 properties 配置文件除了展示形式不相同以外,其它功能和作用都是一樣的;在項目中原路的讀取方式不需要改變。 yml 配置文件的特徵:

  1. 樹狀層級結構展示配置項;
  2. 配置項之間如果有關係的話需要分行空兩格;
  3. 配置項如果有值的話,那麼需要在:之後空一格再寫配置項值;

基本格式:

jdbc:
driverClassName : com.mysql.jdbc.Driver
url : jdbc:mysql://localhost:3306/kw
username : root
password : root

把 application.properties 修改為 application.yml 進行測試。

四、自動配置原理解析#

使用 Spring Boot 之後,一個整合了 SpringMVC 的 WEB 工程開發,變得無比簡單,那些繁雜的配置都消失不見了,這是如何做到的? 一切魔力的開始,都是從我們的 main 函數來的,所以我們再次來看下啟動類: 按住 Ctrl 點擊查看啟動類MySpringBootApplication上的註解 @SpringBootApplication

//創建springboot工程的起步引導類,工程的入口
//自動掃描當前類所在的包以其子包
@SpringBootApplication
public class MySpringBootApplication {
public static void main(String[] args) {
//運行springboot應用
SpringApplication.run(MySpringBootApplication.class,args);
}
}

註解 @SpringBootApplication 的源碼

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
/**
* Exclude specific auto‐configuration classes such that they will never be applied.
* @return the classes to exclude
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
    ... ... ...
}
  • 這裡重點的註解有 3 個:
  • @SpringBootConfiguration:等同與 @Configuration,即標註該類是 Spring 的一個配置類
  • @EnableAutoConfifiguration:SpringBoot 自動配置功能開啟
  • 按住 Ctrl 點擊查看註解 @EnableAutoConfig
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
... ... ...
}

其中,@EnableAutoConfifiguration 的作用就是從 META-INF/spring.factories 文件中讀取有關自動配置的配置信息

在這裡插入圖片描述

spring.factories 文件中有關自動配置的配置信息如下:

在這裡插入圖片描述

上面配置文件存在大量的以 AutoConfiguration 為結尾的類名稱,這些類就是存有自動配置信息的類,而 SpringApplication 在獲取這些類名後再加載 我們以 ServletWebServerFactoryAutoConfiguration 為例來分析源碼:

@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
... ... ...
}

其中, @EnableConfigurationProperties (ServerProperties.class) 代表加載 ServerProperties 伺服器配置屬性類,這種玩法我們玩過~~進入 ServerProperties.class 源碼如下:

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
/**
* Server HTTP port.
*/
private Integer port;
/**
* Network address to which the server should bind.
*/
private InetAddress address;
    ... ... ...
}

其中, prefix = "server" 表示 SpringBoot 配置文件中的前綴,SpringBoot 會將配置文件中以 server 開始的屬性映射到該類的字段中。映射關係如下:

在這裡插入圖片描述

  • @ComponentScan
配置組件掃描的指令。提供了類似與<context:component-scan>標籤的作用 通過basePackageClasses或者basePackages屬性來指定要掃描的包。如果沒有指定這些屬性,那麼將從聲明這個註解的類所在的包開始,掃描包及子包

而我們的 @SpringBootApplication 註解聲明的類就是 main 函數所在的啟動類,因此掃描的包是該類所在包及其子包。

因此,一般啟動類會放在一個比較前的包目錄中。

五、SpringBoot 與整合其他技術#

5.1 整合 SpringMVC#

雖然默認配置已經可以使用 SpringMVC 了,不過我們有時候需要進行自定義配置。

5.1.1. 修改端口#

查看 SpringBoot 的全局屬性可知,端口通過以下方式配置:

server:
port: 80

5.2.2. 訪問靜態資源#

現在,我們的項目是一個 jar 工程,那麼就沒有 webapp,我們的靜態資源該放哪裡呢?

回顧我們在上面看的源碼,有一個叫做 ResourceProperties 的類,裡面就定義了靜態資源的默認查找路徑

在這裡插入圖片描述

  • 默認的靜態資源路徑為:
  • classpath:/META-INF/resources/
  • classpath:/resources/
  • classpath:/static/
  • classpath:/public
注意:如果訪問圖片時候沒有顯示;可以先將項目先clean再啟動,或者創建public、resources文件夾,然後圖片放置到public或resources中。

5.2. 整合 jdbc 和事務#

spring 中的 jdbc 連接和事務是配置中的重要一環,在 SpringBoot 中該如何處理呢? 答案是不需要處理,我們只要找到 SpringBoot 提供的啟動器即可,在 pom.xml 文件中添加如下依賴:

<!‐‐整合jdbc和事務‐‐>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐jdbc</artifactId>
</dependency>

當然,不要忘了數據庫驅動,SpringBoot 並不知道我們用的是什麼數據庫,這裡我們選擇 MySQL;同樣的在 pom.xml 文件中添加如下依賴:

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql‐connector‐java</artifactId>
</dependency>

至於事務,SpringBoot 中通過註解來控制。就是我們熟知的 @Transactional 使用的時候設置在對應的類或方法上即可。

5.3 整合連接池#

其實,在剛才引入 jdbc 啟動器的時候,SpringBoot 已經自動幫我們引入了一個連接池:

在這裡插入圖片描述

HikariCP 應該是目前速度最快的連接池了,我們看看它與 c3p0 的對比:

在這裡插入圖片描述

因此,我們只需要指定連接池參數即可;打開 application.yml 添加修改配置如下:

spring:
datasource:
driver‐class‐name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF‐8&serverTimezone=UTC
username: root
password: root

5.4 SpringBoot 整合 Mybatis#

添加 Mybatis 的起步依賴 SpringBoot 官方並沒有提供 Mybatis 的啟動器,不過 Mybatis 官網自己實現了。在項目的 pom.xml 文件中加入如下依賴:

<!‐‐mybatis起步依賴‐‐>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis‐spring‐boot‐starter</artifactId>
<version>2.1.2</version>
</dependency>

添加數據庫驅動坐標

<!‐‐ MySQL連接驅動 ‐‐>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql‐connector‐java</artifactId>
</dependency>

配置 application.yml,常用配置如下:

#mybatis配置
mybatis:
type‐aliases‐package: com.bailiban.domain
mapper‐locations: classpath:com/bailiban/mapper/*Mapper.xml
configuration:
log‐impl: org.apache.ibatis.logging.stdout.StdOutImpl

配置 Mapper 掃描 需要注意,這裡沒有配置 mapper 接口掃描包,因此我們需要給每一個 Mapper 接口添加 @Mapper 註解,才能被識別。

@Mapper
public interface UserMapper {
}

或者,我們也可以不加註解,而是在啟動類上添加掃描包註解 (推薦):

@SpringBootApplication
@MapperScan("com.bailiban.mapper")
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(MySpringBootApplication.class);
}
}

5.4.1 創建 user 表#

在 test 數據庫中創建 user 表

DROP table if EXISTS user;
##用戶
CREATE TABLE `user` (
`uid` INT AUTO_INCREMENT ,
`username` VARCHAR(20) DEFAULT NULL,
`password` VARCHAR(20) DEFAULT NULL,
`realname` VARCHAR(20) DEFAULT NULL,
`email` VARCHAR(30) DEFAULT NULL,
`telephone` VARCHAR(20) DEFAULT NULL,
PRIMARY KEY (`uid`)
);
INSERT INTO `user` VALUES (NULL,'wc001','888888','旺財','[email protected]','15723689921'),
(NULL,'xq001','888888','小強','[email protected]','15723689922'),
(NULL,'xb001','888888','小寶','[email protected]','15723689923');

5.4.2 創建實體 Bean#

package com.bailiban.domain;
public class User {
private int uid;//用戶編號
private String username;//用戶名
private String password;//密碼
private String realname;//真實姓名
private String email;//郵箱
private String telephone;//電話
//省略setter getter方法
}

5.4.3 編寫 Mapper#

@Mapper
public interface UserMapper {
public List<User> queryUserList();
}

注意:@Mapper 標記該類是一個 mybatis 的 mapper 接口,可以被 spring boot 自動掃描到 spring 上下文中

5.4.4 配置 Mapper 映射文件#

在 src/main/resources/com/bailiban/mapper 路徑下加入 UserMapper.xml 配置文件 "

<
?xml version="1.0" encoding="utf‐8" ?>
<!DOCTYPE mapper PUBLIC "‐//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis‐3‐mapper.dtd" >
<mapper namespace="com.bailiban.mapper.UserMapper">
<select id="queryUserList" resultType="user">
select * from user
</select>
</mapper>

5.4.5 在 application.yml 中添加 mybatis 的信息#

#mybatis配置
mybatis:
type‐aliases‐package: com.bailiban.domain
mapper‐locations: classpath:com/bailiban/mapper/*Mapper.xml
configuration:
log‐impl: org.apache.ibatis.logging.stdout.StdOutImpl

5.4.6 編寫測試 Controller#

@Controller
public class MapperController {
@Autowired
private UserMapper userMapper;
@RequestMapping("/queryUser")
@ResponseBody
public List<User> queryUser(){
List<User> users = userMapper.queryUserList();
return users;
}
}

5.5 Junit 測試#

  1. 在 springboot 項目中如果要使用 Junit 進行單元測試,則需要添加如下的啟動器:

    <!‐‐單元測試啟動器‐‐>
    <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis‐spring‐starter‐test</artifactId>
    </dependency>
    
  2. 在測試包下編寫測試類 在測試類上面必須要添加 @SpringBootTest 註解。

import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void test1(){
List<User> users = userService.selectAll();
System.out.println(users);
}
}

5.6 整合 Redis#

概念:redis 是一款高性能的 NOSQL 系列的非關係型數據庫

5.6.1 什麼是 NOSQL#

NoSQL (NoSQL = Not Only SQL),意即 “不僅僅是 SQL”,是一項全新的數據庫理念,泛指非關係型的數據庫。 隨著互聯網 web2.0 網站的興起,傳統的關係數據庫在應付 web2.0 網站,特別是超大規模和高並發的 SNS 類型的 web2.0 純動態網站已經顯得力不從心,暴露了很多難以克服的問題,而非關係型的數據庫則由於其本身的特點得到了非常迅速的發展。NoSQL 數據庫的產生就是為了解決大規模數據集合多重數據種類帶來的挑戰,尤其是大數據應用難題

5.6.2 NOSQL 和關係型數據庫比較#

優點:

  1. 成本:nosql 數據庫簡單易部署,基本都是開源軟件,不需要像使用 oracle 那樣花費大量成本購買使用,相比關係型數據庫價格便宜。

  2. 查詢速度:nosql 數據庫將數據存儲於緩存之中,關係型數據庫將數據存儲在硬盤中,自然查詢速度遠不及 nosql 數據庫。

  3. 存儲數據的格式:nosql 的存儲格式是 key,value 形式、文檔形式、圖片形式等等,所以可以存儲基礎類型以及對象或者是集合等各種格式,而數據庫則只支持基礎類型。

  4. 擴展性:關係型數據庫有類似 join 這樣的多表查詢機制的限制導致擴展很艱難。
    缺點:

  5. 維護的工具和資料有限,因為 nosql 是屬於新的技術,不能和關係型數據庫 10 幾年的技術同日而語。

  6. 不提供對 sql 的支持,如果不支持 sql 這樣的工業標準,將產生一定用戶的學習和使用成本。

  7. 不提供關係型數據庫對事務的處理。

總結: 關係型數據庫與 NoSQL 數據庫並非對立而是互補的關係,即通常情況下使用關係型數據庫,在適合使用 NoSQL 的時候使用 NoSQL 數據庫,讓 NoSQL 數據庫對關係型數據庫的不足進行彌補。 一般會將數據存儲在關係型數據庫中,在 nosql 數據庫中備份存儲關係型數據庫的數據

5.6.3 主流的 NOSQL 產品#

相關產品:Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
典型應用:內容緩存,主要用於處理大量數據的高訪問負載。
數據模型:一系列鍵值對
優勢:快速查詢
劣勢:存儲的數據缺少結構化
文檔型數據庫
相關產品:CouchDB、MongoDB
典型應用:Web 應用(與 Key-Value 類似,Value 是結構化的)
數據模型:一系列鍵值對
優勢:數據結構要求不嚴格
劣勢:查詢性能不高,而且缺乏統一的查詢語法

5.6.4 什麼是 Redis#

Redis 是用 C 語言開發的一個開源的高性能鍵值對(key-value)數據庫,官方提供測試數據,50 個並發執行 100000 個請求,讀的速度是 110000 次 /s, 寫的速度是 81000 次 /s,且 Redis 通過提供多種鍵值數據類型來適應不同場景下的存儲需求,目前為止 Redis 支持的鍵值數據類型如下:
\1. 字符串類型 string
\2. 哈希類型 hash
\3. 列表類型 list
\4. 集合類型 set
\5. 有序集合類型 sortedset

5.6.5 redis 的應用場景#

  • 緩存(數據查詢、短連接、新聞內容、商品內容等等)
  • 聊天室的在線好友列表
  • 任務隊列。(秒殺、搶購、12306 等等)
  • 應用排行榜
  • 網站訪問統計
  • 數據過期處理(可以精確到毫秒)
  • 分佈式集群架構中的 session 分離

5.6.6 整合#

在 pom.xml 文件中添加如下依賴

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

配置 application.yml 文件

spring:
redis:
host: localhost
port: 6379

測試代碼

package com.summer.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.*;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void test1() {
//保存字符串最常用的
redisTemplate.opsForValue().set("hello", "哈哈");
//獲取
String hello = (String) redisTemplate.opsForValue().get("hello");
System.out.println(hello);
//保存和讀取set
redisTemplate.opsForSet().add("s_key", "a", "b", "c");
Set set = redisTemplate.opsForSet().members("s_key");
System.out.println("set集合"+set);
//保存和讀取List
List<String> list = Arrays.asList("a", "b", "c");
redisTemplate.opsForList().leftPush("l_key", list);
//獲取
List<String> list1 = (List<String>) redisTemplate.opsForList().leftPop("l_key");
System.out.println("list集合"+list1);
//保存和讀取map集合
Map<String, String> map = new HashMap<>();
map.put("name", "旺財");
map.put("age", "18");
redisTemplate.opsForHash().putAll("h_key", map);
//獲取map
Map<String, String> map1 = redisTemplate.opsForHash().entries("h_key");
//獲取key的集合
Set key_set = redisTemplate.opsForHash().keys("h_key");
//獲取value的集合
List value_list = redisTemplate.opsForHash().values("h_key");
System.out.println("key的集合:"+key_set);
System.out.println("value的集合:"+value_list);
System.out.println("map集合:"+map1);
//保存有序的set
redisTemplate.opsForZSet().add("z_key","a",10);
redisTemplate.opsForZSet().add("z_key","b",20);
redisTemplate.opsForZSet().add("z_key","c",30);
//獲取
Set z_set = redisTemplate.opsForZSet().range("z_key", 0, -1);
System.out.println("有序的set"+z_set);
}
}
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。