一:SpringBoot簡介
當前網際網路後端開發中,JavaEE佔據了主導地位。對JavaEE開發,首選框架是Spring框架。在傳統的Spring開發中,需要使用大量的與業務無關的XML配置才能使Spring框架執行起來,這點備受許多開發者詬病。隨著Spring4.x釋出,Spring已經完全脫離XML,只使用註解就可以執行專案。為了進一步簡化Spring應用的開發,SpringBoot誕生了。它是由Pivotal團隊提供的全新框架,其設計目的是簡化Spring應用的搭建及開發過程,並迎合時下流行的分散式微服務設計思想,越來越多企業在使用SpringBoot
1:設計初衷
SpringBoot為我們開發者提供了一種更快速、體驗更好的開發方式,我們可以開箱即用,無需像寫Spring那樣配置各種XML檔案,雖然Spring3.0時引入了基於java的配置,但是編寫這些配置無疑是在浪費大量時間,其實SpringBoot還內建Tomcat
2:核心功能
一:獨立的執行Spring SpringBoot 可以以jar包形式獨立執行,執行一個SpringBoot專案只需要通過java -jar xx.jar來執行 二:內建Servlet容器 Spring Boot可以選擇內嵌Tomcat、jetty或者Undertow,這樣我們無須以war包形式部署專案 三:簡化Maven配置 SpringBoot提供了一系列的start pom來簡化Maven的依賴載入,例如,當你使用了spring-boot-starter-web 四:自動裝配 SpringBoot會根據在類路徑中的jar包,類、為jar包裡面的類自動配置Bean,這樣會極大地減少我們要使用的配置。
當然,SpringBoot只考慮大多數的開發場景,並不是所有的場景,若在實際開發中我們需要配置Bean,而SpringBoot
沒有提供支援,則可以自定義自動配置 五:準生產的應用監控 SpringBoot提供基於http ssh telnet對執行時的專案進行監控 六:無程式碼生產和xml配置 SpringBoot不是藉助與程式碼生成來實現的,而是通過條件註解來實現的,這是Spring4.x提供的新特性
Spring Boot只是Spring本身的擴充套件,使開發,測試和部署更加方便
3:本文開發環境需求
SpringBoot 2.4.1正式發行版,要求Java8並且相容Java15;對應的Spring版本是5.3.2;而且要求Maven 3.3+ 但是最好使用3.5.4穩定版本,而Servlet容器的版本為Tomcat9.0(Servlet Version 4.0)、Jetty 9.4(Servlet Version 3.1)、Undertow 2.0(Servlet Version 4.0)
二:SpringBoot入門搭建
1:手動搭建案例
我們以一個簡單的SpringBoot案例來突顯出Spring的繁瑣,我接下來將使用SpringBoot來實現一個簡單的帶Controller的案例
第一步:使用IDEA構建一個普通的Maven專案
第二步:在構建好的maven工程中對pom檔案修改
第三步:編寫啟動引導類
第四步:編寫Controller
第五步:訪問(預設8080埠) 以本案例http://localhost:8080/index/test
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- 在編寫SpringBoot的專案時我們得繼承SpringBoot的父POM檔案, 這一點和我們以前使用Spring匯入的座標不太一樣,細心的會檢視 繼承的父POM檔案後發現SpringBoot為我們提前匯入了大量的座標, 這就解決了我們平常匯入座標版本衝突問題 --> <parent> <artifactId>spring-boot-starter-parent</artifactId> <groupId>org.springframework.boot</groupId> <version>2.4.1</version> </parent> <groupId>org.example</groupId> <artifactId>demo0023</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- 要編寫SpringMVC相關程式碼我們還得匯入web的starter依賴 SpringBoot為了我們匯入的方便,把一系列的關於SpringMVC的座標打包結合到了 這個我下面匯入的座標裡面 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
package cn.xw; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * 啟動引導類 */ //加上此註解代表當前類就是SpringBoot啟動類,否則就是普通類 @SpringBootApplication public class SpringBoot5Application { //SpringBoot程式入口 public static void main(String[] args) { //main函式裡面的args引數是一個String陣列,所以在main函式執行的 //同時可以接收引數,接收過來的引數交給了SpringBoot,用於後期執行配置,後面介紹 //第一個引數通過反射是告訴SpringBoot哪個是啟動引導類 //還有這個方法有個返回值,返回IOC容器 SpringApplication.run(SpringBoot5Application.class, args); } /** * 注意:此類只會掃描載入當前包及其子包裡面的全部類,然會把它們載入IOC容器中 */ }
package cn.xw.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController //結合@ResponseBody 和 @Controller 兩註解 @RequestMapping("/index") public class IndexController { @RequestMapping("/test") public String testMethod() { System.out.println("訪問到此方法"); return "Hello !!"; } }
2:使用Spring Initializr快速搭建
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!--SpringBoot父POM座標--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.1</version> <relativePath/> </parent> <groupId>cn.xw</groupId> <artifactId>springboot_test</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springboot_test</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!--WEB開發Starter--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--SpringBoot的開發者工具--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!--SpringBoot測試Starter--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <!--SpringBoot的Maven外掛--> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
三:SpringBoot基本分析
1:座標中starters分析及依賴管理
starter是依賴關係的整理和封裝。是一套依賴座標的整合,可以讓匯入應用開發的依賴座標更方便。利用依賴傳遞的特性幫我們把一些列指定功能的座標打包成了一個starter,我們只需要匯入starter即可,無需匯入大量座標;每個Starter包含了當前功能下的許多必備依賴座標這些依賴座標是專案開發,上線和執行必須的。同時這些依賴也支援依賴傳遞。如下Starter:
<!--匯入WEB開發Starter--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.4.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> <version>2.4.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <version>2.4.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.3.2</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.2</version> <scope>compile</scope> </dependency> </dependencies>
封裝成各個Starter的好處就是讓我們更加專注於業務開發,無需關心依賴匯入,依賴衝突,及依賴的版本
問:為什麼匯入的一些Starter不需要寫版本呢?
不指定版本是因為maven有依賴傳遞的特性,可推測starter在父級定義了並鎖定了版本;spring-boot-dependencies.xml 檔案可以給大家一個答案;繼承關係為 spring-boot-starter-parent.xml ==> spring-boot-dependencies.xml 這裡面鎖定了我們常用的座標及Stater
編寫SpringBoot專案繼承spring-boot-starter-parent的好處和特點
①:預設編譯Java 1.8
②:預設編碼UTF-8
③:通過spring-boot-denpendencies的pom管理所有公共Starter依賴的版本
④:spring-boot-denpendencies通過Maven的依賴傳遞和版本鎖定特性來實現版本管理
⑤:隨用隨取,不用繼承父類所有的starter依賴。
POM檔案中的Maven外掛功能
<build> <plugins> <!-- 作用:將一個SpringBoot的工程打包成為可執行的jar包 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
2:自動配置(AutoConfiguration)分析
所有我們要配置的專案Pivotal團隊的開發人員,幫我們寫好了,怎麼實現的,主要是通過@Configuration實現 SpringBoot採用約定大於配置設計思想,將所有可能遇到的配置資訊提前配置好,寫在自動配置的jar包中。每個Starter基本都會有對應的自動配置。SpringBoot幫我們將配置資訊寫好,存放在一個jar包中:spring-boot-autoconfigure-2.4.1.jar;jar包裡,存放的都是配置類,讓配置類生效的"規則類"
接下來我來介紹一個我們常見的配置類 一:找到專案的External Libraries 二:查詢Maven:org.springframework.boot:spring-autoconfigue:2.4.1 三:內部有個spring-boot-autoconfigue-2.4.1.jar 四:點選org ==> web ==> servlet ==> ServletWebServerFactoryAutoConfiguration類 @Configuration(proxyBeanMethods = false) //代表是個配置類 SpringBoot為我們提供的每個配置類都有此註解 @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 { ... } 補充:我們回到之前點選META-INF ==> spring.factories 這裡面配置的是SpringBoot的全部配置類
補充:我們回到之前點選META-INF ==> spring-configuration-metadata.json 這裡面配置著各種配置類的資訊引數
問:SpringBoot提供這麼多配置類,難道是程式執行後就全部匯入嗎?
不會全部匯入,只會根據當前專案的需求選擇性的裝配所需的配置類,這也是SpringBoot的自動裝配一大特性;我們也可以設想一下,一次性裝配全部配置類,那該多慢呀;
問:SpringBoot怎麼知道程式執行後就自動裝配呢?
我們找到SpringBoot入口函式,點開 @SpringBootApplication 註解會發現裡面有個 @EnableAutoConfiguration 這個註解就是開啟自動配置的
問:開啟自動裝配後,它咋知道要載入指定配置呢?那麼多配置類呢
我們繼續看上面的 ServletWebServerFactoryAutoConfiguration 配置類
@Configuration(proxyBeanMethods = false) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) //配置類能否被自動裝配主要看 @ConditionalOnClass註解 //此註解是否可以載入到一個叫 ServletRequest.class檔案,一旦存在則自動裝配 @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 { ... }
有了自動配置後,那麼基本全部採用預設配置(這也就是為啥說約定大於配置的思想);那麼要修改預設配置也是可以的,我們只需在配置檔案配置指定的引數即可 官方全部可配置屬性 如下常見配置:
# 埠配置 server.port=8888 # 配置context-path專案訪問根路徑 server.servlet.context-path=/demo # 開啟debug模式,詳細日誌輸出,用於開發的一種設定 預設是false debug=true # 配置日誌 logging.level.{指定包下的日誌}=debug logging.level.cn.xw=debug
四:SpringBoot的配置檔案
SpringBoot是約定大於配置的,配置都有預設值。如果想修改預設配置,可以使用application.properties或application.yml或application.yaml自定義配置。SpringBoot預設從Resource目錄載入自定義配置檔案。application.properties是鍵值對型別;application.yml是SpringBoot中一種新的配置檔案方式,在使用自定義配置時名稱一定要為application,因為是提前約定好的,而且三個字尾名的檔案都寫上是有個先後順序,後面可覆蓋前面
<includes> <include>**/application*.yml</include> <include>**/application*.yaml</include> <include>**/application*.properties</include> </includes>
# properties型別配置檔案 application.properties server.port=8080 server.address=127.0.0.1 <!--xml型別配置檔案 application.xml--> <server> <port>8080</port> <address>127.0.0.1</address> </server> # yml/yaml型別配置檔案 application.yml/ymal server: port: 8080 address: 127.0.0.1
1:yml/yaml配置檔案語法及使用
YML檔案格式是YAML(YAML Aint Markup Language)編寫的檔案格式。可以直觀被電腦識別的格式。容易閱讀,容易與指令碼語言互動。可以支援各種程式語言(C/C++、Ruby、Python、Java、Perl、C#、PHP)。以資料為核心,比XML更簡潔。副檔名為.yml或.yaml 官方網站 線上properties轉yml
1:大小寫敏感
2:資料值前邊必須有空格,作為分隔符
3:使用縮排表示層級關係
4:縮排不允許使用tab,只允許空格
5:縮排的空格數不重要,只要相同層級的元素左對齊即可
6:"#"表示註釋,從這個字元一直到行尾,都會被解析器忽略。
7:陣列和集合使用 "-" 表示陣列每個元素
# 單個值指定 name: 小周 # 單引號忽略轉義字元 message1: 'hello \n world' # 雙引號識別轉義字元 列印時會換行 message2: "hello \n world" # 物件方式指定 普通寫法 student: name: 張三 age: 25 address: 安徽六安 # 物件方式指定 行內寫法 teacher: { name: 李老師, age: 50, address: 上海 } # 陣列方式 普通寫法 hobby: - baseball - basketball - volleyball # 陣列方式 行內寫法 likes: [ baseball, basketball, volleyball ] # 集合方式 map等格式 peoples: key1: zhangsan key2: anhui key3: xiezi # 集合方式 map等格式 行內寫法 peoples1: { key1 : zhangsan, key2 : anhui , key3 : shanghai} # 這上面的key~ 是具體的key名稱 ######## 其它方式擴充套件 # 配置引用 bookName: 零基礎學Java person: name: xiaowu likeBookName: ${bookName} # 配置隨機數 其中有int 和 long兩種根據情況選擇 # 隨機字串 StringA: ${random.value} # 隨機數 numberB: ${random.int} # 隨機產出小於10的數 numberC: ${random.int(10)} # 隨機產出10~100之間的數 大於10小於100 numberD: ${random.int(10,100)} # 隨機產出一個uuid字串 uuid: ${random.uuid}
2:配置檔案與配置類屬性對映
(1):java配置獲取基本的配置檔案資訊.properties型別
三:配置類 jdbcConfig.java //宣告此類為配置類 @Configuration //匯入外部配置檔案 因為這個配置類是自定義的,不受SpringBoot幫我們管理 @PropertySource(value="classpath:application.properties") public class JdbcConfig { @Value(value = "${jdbc.datasource.driver-class-name}") private String driver; @Value("${jdbc.datasource.url}") private String url; @Value("${jdbc.datasource.username}") private String username; @Value("${jdbc.datasource.password}") private String password; @Bean(value = "dataSource") public DataSource getDataSource() { System.out.println(driver); //建立連線池 並加入容器 DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } } 四:Controller 通過訪問執行程式 這裡就先不寫測試類 @RestController //結合@ResponseBody 和 @Controller 兩註解 @RequestMapping("/index") public class IndexController { @Autowired private DataSource dataSource; @RequestMapping("/test") public String testMethod() { System.out.println("訪問到此方法"+dataSource); return "Hello !!"; } } //列印 訪問到此方法{ CreateTime:"2021-01-09 15:22:49", ActiveCount:0, PoolingCount:0, CreateCount:0, DestroyCount:0, CloseCount:0, ConnectCount:0, Connections:[ ] }
(2):java配置獲取基本的配置檔案資訊並注入.yml/.yaml型別
1、使用註解@Value對映 @value註解將配置檔案的值對映到Spring管理的Bean屬性值,只能對映基本資料型別 2、使用註解@ConfigurationProperties對映 通過註解@ConfigurationProperties(prefix=''配置檔案中的key的字首")可以將配置檔案中的配置自動與實體進行對映。
使用@ConfigurationProperties方式必須提供Setter方法,使用@Value註解不需要Setter方法
注:使用@ConfigurationProperties要在主函式上開啟@EnableConfigurationProperties
/** * @author: xiaofeng * @date: Create in $DATE * @description: 學生物件 * @version: v1.0.0 */ @Component //一定要保證被對映注入的是個元件 @ConfigurationProperties(prefix = "student") //可以之間對映物件 public class Student { private Integer id; //id private String name; //姓名 private String address; //住宅 private List<String> hobbys; //愛好 private Map<String, List<Integer>> score;//各科得分 private Map<String,Teacher> teachers; //各科老師 //...省略get/set 這個一定要寫 我為了程式碼少沒複製 } /** * @author: xiaofeng * @date: Create in $DATE * @description: 老師物件 * @version: v1.0.0 */ public class Teacher { private String name; private String message; } //注:在新增完@ConfigurationProperties後如果沒有spring-boot-configuration-processor編譯器會彈出提示 //提示資訊:Spring Boot Configuration Annotation Processor..... //pom.xml新增這個配置註解處理器 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> //然後去主函式類上面新增@EnableConfigurationProperties 開啟配置註解處理器
student: id: 1001 name: 張三 address: 安徽六安 hobbys: - baseball - basketball - volleyball score: yuwen: - 66 - 88 shuxue: - 85 - 99 #簡寫 score: { "yuwen" : [58,99], "shuxue" : [88,96] } # 這裡通過外界傳入值 注意引號別忘了 teachers: yuwenTeacher: { name: "${teacherNameA}", message: "${teacherMessageA}" } shuxueTecher: { name: "${teacherNameB}", message: "${teacherMessageB}" } teacherNameA: 張老師 teacherMessageA: 教語文 teacherNameB: 李老師 teacherMessageB: 教數學
//通過web的方式載入程式執行
@RestController //結合@ResponseBody 和 @Controller 兩註解 @RequestMapping("/index") public class IndexController { //注入 @Autowired private Student student; @RequestMapping("/test") public String testMethod() { System.out.println(student.toString()); //Student{ // id=1001, // name='張三', // address='安徽六安', // hobbys=[baseball, basketball, volleyball], // score={yuwen=[66, 88], shuxue=[85, 99]}, // teachers={yuwenTeacher=Teacher{name='張老師', message='教語文'}, // shuxueTecher=Teacher{name='李老師', message='教數學'}}} return "Hello !!"; } }
五:SpringBoot與其它技術整合
1:SpringBoot整合MyBatis 建表語句
整合Mybatis完成查詢全部
(1):使用註解方式完成整合
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cn.xw</groupId> <artifactId>demomybatiss</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demomybatiss</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!--web啟動器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--spring-boot啟動器--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency> <!--工具--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!--mysql驅動--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!--測試 這裡沒用到--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/demo_school?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC username: root password: 123 # 加上 ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 是為了防止SpringBoot報時區錯誤 # com.mysql.jdbc.Driver 這種的已經過時了,但是不代表就剔除了 可以用
///////////POJO /** * @author: xiaofeng * @date: Create in $DATE * @description: 學生實體類 * @version: v1.0.0 */ public class Student implements Serializable { private int id; //id private String name; //姓名 private String sex; //性別 private int age; //年齡 private double credit; //成績/學分 private double money; //零花錢 private String address; //住址 private String enrol; //入學時間 //private int fid; //外來鍵 家庭 //private int tid; //外來鍵 老師 //構造器(無參構造器必須有)/set/get/toString 你們補充一下 } /////////// Mapper //此註解org.apache.ibatis.annotations.Mapper 是mybatis提供的加入容器 //Mapper 可以說等於 @Component、@Repository、@Server、@Controller @Mapper public interface StudentMapper { //查詢全部 @Select("select * from student") @Results(id = "studentMapper", value = { @Result(id = true, column = "sid", property = "id"), @Result(column = "sname", property = "name"), @Result(column = "ssex", property = "sex"), @Result(column = "sage", property = "age"), @Result(column = "scredit", property = "credit"), @Result(column = "smoney", property = "money"), @Result(column = "saddress", property = "address"), @Result(column = "senrol", property = "enrol") }) List<Student> findAll(); } ///////////Service /** * @author: xiaofeng * @date: Create in $DATE * @description: 學生業務介面 * @version: v1.0.0 */ public interface StudentService { //查詢全部 List<Student> findAll(); } /** * @author: xiaofeng * @date: Create in $DATE * @description: 學生業務實現 * @version: v1.0.0 */ @Service //注入到容器 public class StudentServiceImpl implements StudentService { //注入物件 如果是IDEA編譯器這邊會有個紅線錯誤,不影響 @Autowired private StudentMapper studentMapper; //查詢全部 @Override public List<Student> findAll() { return studentMapper.findAll(); } } //////////Controller @RestController @RequestMapping("/student") public class StudentController { @Autowired private StudentService studentService; @RequestMapping("/findAll") public List<Student> findAll() { System.out.println("訪問成功"); //這裡通過json把物件寫到瀏覽器,要序列化物件 return studentService.findAll(); } }
注:使用http://localhost:8080/student/findAll訪問,還有就是Mapper資料夾裡面的程式碼一定要寫在主函式類當前包及其子包下,如果不在則需要在入口類新增@MapperScan或者@MapperScans註解掃描一下,這個是mybatis提供的
(2):使用Mapper.xml對映完成整合
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/demo_school?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC username: root password: 123 # spring繼承mybatis環境 # type-aliases-package:pojo別名掃描包 # mapper-locations:載入mybatis對映檔案 mybatis: type-aliases-package: cn.xw.pojo mapper-locations: classpath:mapper/*Mapper.xml # 加上 ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 是為了防止SpringBoot報時區錯誤 # com.mysql.jdbc.Driver 這種的已經過時了,但是不代表就剔除了 可以用
<?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="cn.xw.mapper.StudentMapper"> <!--名稱欄位不一樣可以使用這個對映名稱對應--> <resultMap id="studentMapper" type="student"> <id column="sid" property="id"/> <result column="sname" property="name"/> <result column="ssex" property="sex"/> <result column="sage" property="age"/> <result column="sscore" property="credit"/> <result column="smoney" property="money"/> <result column="saddress" property="address"/> <result column="senrol" property="enrol"/> </resultMap> <!--查詢全部學生 要使用上面的resultMap才可以--> <select id="findAll" resultMap="studentMapper"> select * from student; </select> </mapper>
刪除之前在Mapper使用註解的SQL語句刪除,只留方法
2:Spring Boot 整合 Redis
springBoot整合Redis後,以上個案例的基礎上做個查詢學生快取,如果第一次查詢則快取到redis伺服器裡,然後從redis讀取資料返回到客戶端
<!--匯入redis啟動器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
@RestController @RequestMapping("/student") public class StudentController { @Autowired private StudentService studentService; //注入redis模板物件 @Autowired private RedisTemplate redisTemplate; @RequestMapping("/findAll") public List<Student> findAll() { System.out.println("訪問成功"); //獲取類名 String className = studentService.getClass().getName(); //以類名+方法名的方式作為key來查詢redis快取資料 List<Student> studentList = (List<Student>) redisTemplate.boundValueOps(className + "findAll").get(); //redis沒有資料 查詢資料庫放入到redis if (studentList == null) { System.out.println("從資料庫查詢資料放入到redis"); //查詢資料庫 studentList = studentService.findAll(); //把查詢到的資料放入redis中 key為類名加findAll redisTemplate.boundValueOps(className + "findAll").set(studentList); } else { System.out.println("從redis讀取資料快取"); } //這裡通過json把物件寫到瀏覽器,要序列化物件 return studentList; } }
3:Spring Boot 整合定時器
使用SpringBoot完成一個簡易的定時器,每5秒輸出一下當前的時間到控制檯;
首先在入口函式類上面加@EnableScheduling註解,代表開啟定時器
@Component public class TimerUtil { /** * @Scheduled 設定方法執行規則 就是定時任務設定 * cron: 設定一個String型別的cron表示式 這個屬性和下面6個不要混用 * fixedDelay 以一個固定的延遲時間,上個任務完成後多久執行下一個任務 * fixedDelayString 和上面一樣字串形式傳值 * fixedRate 以一個固定的頻率執行,不管上一個任務執行時間 * fixedRateString 和上面一樣字串形式傳值 * initialDelay 當專案初始化後多久觸發事務的執行 * initialDelayString 和上面一樣字串形式傳值 */ //使用cron表示式 @Scheduled(initialDelay=10000,fixedDelay = 5000) public void myTask(){ System.out.println("當前時間:"+new Date()); } } //注:寫在入口函式類可掃描的範圍包下
4:Spring Boot 整合Test單元測試
<!--測試啟動start--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
//@RunWith(SpringRunner.class) 在老版的SpringBoot專案需要這個
//2.2.0.RELEASE以後,springboot測試類不再需要@Runwith的註解
@SpringBootTest //註明為SpringBoot測試類 class DemomybatissApplicationTests { //注入StudentService物件 @Autowired private StudentService studentService; @Test void contextLoads() { System.out.println(studentService.findAll()); } }
5:Spring Boot 傳送HTTP請求
要在SpringBoot內部傳送HTTP請求就得用到RestTemplate模板,它是Rest的HTTP客戶端模板工具類;對基於HTTP客戶端進行了封裝;還實現了物件與JSON的序列化與反序列化;不限定客戶端型別,目前常用的3種客戶端都支援:HttpClient、OKHttp、JDK原生URLConnection(預設方式)
@SpringBootApplication @EnableScheduling //開啟定時器註解 public class DemomybatissApplication { public static void main(String[] args) { SpringApplication.run(DemomybatissApplication.class, args); } //註冊RestTemplate物件放入IOC容器 @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } }
//@RunWith(SpringRunner.class) 在老版的SpringBoot專案需要這個 @SpringBootTest //註明為SpringBoot測試類 class DemomybatissApplicationTests { //注入RestTemplate物件 @Autowired private RestTemplate restTemplate; @Test void contextLoads() { //String.class代表以字串形式接收結果 String forObject = restTemplate.getForObject("http://baidu.com", String.class); System.out.println(forObject); //列印 //<html> //<meta http-equiv="refresh" content="0;url=http://www.baidu.com/"> //</html> } }
6:擴充套件
SpringBoot除了上面幾個整合外還整合 MongoDB、ElasticSearch、Memcached、郵件服務:普通郵件、模板郵件、驗證碼、帶Html的郵件、RabbitMQ訊息中介軟體、Freemarker或者Thymeleaf等等
六:SpringBoot打包部署
啟動方式有兩種,一種是打成jar直接執行,另一種是打包成war包放到Tomcat服務下,啟動Tomcat
1:打成Jar包部署執行
注:pom檔案裡的<packaging>jar</packaging>必須為jar,預設就是jar
/** * 第一步:使用IDEA工具把寫的程式碼通過maven的package打包 * 第二步:找到打包後的target資料夾裡面,把xxx.jar包扔給測試 * 第三步:自己測試的話使用cmd執行下面命令,前提得檢查自己的pom.xml檔案中是否有springboot的maven外掛 * java -jar xxxx.jar * 補充:在執行的時候傳遞引數 通過main函式的args接收 * java -jar xxxx.jar --server.port=8888 * 補充:在執行的時候配置jvm引數,使佔用更少的記憶體 * java -Xmx80m -Xms20m -jar xxxx.jar */
2:打成War包部署執行
注:pom檔案裡的<packaging>war</packaging>必須為jar,預設就是war
建立一個類如:ServletInitializer.java,繼承 SpringBootServletInitializer ,覆蓋 configure(), 把啟動類 Application 註冊進去。外部 Web 應用伺服器構建 Web Application Context 的時候, 會把啟動類新增進去。 //如下程式碼建立的類 除了類名和註冊的啟動類不一樣,其它是固定寫法 //WEB-INF/web.xml public class ServletInitializer extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { //DemoApplication是自己當前專案的主函式 return builder.sources(DemoApplication.class); } }
七:SpringBoot熱部署
我們在之前每次寫完程式碼之後都要重新部署執行,這樣特別浪費時間,其實SpringBoot是支援熱部署的,但是我們得有相對應的引數配置,匯入座標
檢查當前的pom.xml必須有此配置才可以,然後正常啟動執行即可
<!--工具 用於設定熱部署,optional必須為true--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency>
當我們的程式碼寫文執行後,後期更改了程式碼無需重寫部署,只需要按CTRL+F9(Build Project),這是快速構建專案,或點選有上角的錘子;
如果還覺得麻煩,那就設定,一旦更改程式碼,IDEA失去焦點就自動構建程式碼,我們要設定一下IDEA配置
八:SpringBoot配置檔案深入
1:多環境配置檔案
我們在開發Spring Boot應用時,通常同一套程式會被安裝到不同環境,比如:開發dev、測試test、生產pro等。其中資料庫地址、伺服器埠等等配置都不同,如果每次打包時,都要修改配置檔案,那麼非常麻煩。profile功能就是來進行動態配置切換的。
(1):單檔案的多環境配置
# 在只有application.yml一個檔案下配置多個配置環境就需要使用 " --- " 分隔界限 # 為了規範 Dev為開發 Test為測試 Pro為生產 # 配置完以後在這裡選擇要使用的配置環境 spring: profiles: # 開啟哪個環境下的配置檔案 active: oo # 引用包含哪個配置檔案 include: global # 開發環境配置 Dev --- server.port: 8881 # 設定當前的配置界限為 dev開發環境 spring.profiles: dev # 測試環境配置 Test --- server.port: 8882 spring.profiles: test # 生產上線環境配置 Pro --- server.port: 80 spring.profiles: pro # 全域性的配置供include包含使用 --- server.servlet.context-path: /littleBird spring.profiles: global
(2):多檔案的多環境配置
⭐:application.yml 主配置檔案(必須有) # 為了規範 Dev為開發 Test為測試 Pro為生產 # 配置完以後在這裡選擇要使用的配置環境 spring: profiles: # 開啟哪個環境下的配置檔案 active: dev # 引入包含共有配置 include: common ⭐:application-dev.yml/properties 開發環境配置 # 開發環境 server.port: 8881 ⭐:application-test.yml/properties 測試環境配置 # 測試環境 server.port: 8882 ⭐:application-pro.yml/properties 生產環境配置 # 上線環境 server.port: 80 ⭐:application-common.yml/properties 公共環境配置 # 公共配置 供其包含匯入 server.servlet.context-path: /littleBird
(3):profile啟用方式
在上面我介紹了使用配置檔案來指定配置環境:spring.profiles.active=xx;可是這個是有侷限性的,除了這種方式啟用還要另外2種
配置檔案: 再配置檔案中配置:spring.profiles.active=dev 虛擬機器引數:在VM options 指定:-Dspring.profiles.active=dev 命令列引數:java –jar xxx.jar --spring.profiles.active=dev
優先順序:命令列引數 > 虛擬機器引數 > 配置檔案
2:鬆散繫結
不論配置檔案中的屬性值是短橫線、駝峰式還是下換線分隔配置方式,在注入配置時都可以通過短橫線方式取出值;使用範圍:properties檔案、YAML檔案、系統屬性
⭐命名各種方式的名稱 application.yml檔案下定義方式 # 短橫線分隔 parameter1: spring-boot: student-name: zhangsan # 駝峰式 parameter2: springBoot: studentName: lisi # 下劃線分隔 parameter3: spring_boot: student_name: wangwu ⭐命名各種方式的名稱 application.properties檔案下定義方式 # 短橫線分隔 parameter1.spring-boot.student-name=zhangsan # 駝峰式 parameter2.springBoot.studentName=lisi # 下劃線分隔 parameter3.spring_boot.student_name: wangwu ⭐取出方式:使用短橫線分隔可以取出上面的任意一直格式 注:在@Value獲取上面的3種方式命名的配置只能使用短橫線分隔通配 否則配置檔案寫啥名,獲取就寫啥名,一一對應 @Value(value="${parameter1.spring-boot.student-name}") @Value(value="${parameter2.spring-boot.student-name}") @Value(value="${parameter3.spring-boot.student-name}")
3:配置路徑及其載入順序
4:外部配置載入順序 官方文件
外部載入順序就是說在程式執行時載入外部的配置資訊的順序,如我們常用的命令列下指定額外資訊 java -jar xxx.jar --server.port=8888
# 這個是2.1.11版本的springboot之前的資訊,中文的看的清楚,以具體版本為準 1:開啟 DevTools 時, ~/.spring-boot-devtools.properties 2:測試類上的 @TestPropertySource 註解 3:@SpringBootTest#properties 屬性 4:==命令?引數(--server.port=9000 )== 5:SPRING_APPLICATION_JSON 中的屬性 6:ServletConfig 初始化引數 7:ServletContext 初始化引數 8:java:comp/env 中的 JNDI 屬性 9:System.getProperties() 10:作業系統環境變數 11:random.* 涉及到的 RandomValuePropertySource 12:jar 包外部的 application-{profile}.properties 或 .yml 13:jar 包內部的 application-{profile}.properties 或 .yml 14:jar 包外部的 application.properties 或 .yml 15:jar 包內部的 application.properties 或 .yml 16:@Configuration 類上的 @PropertySource 17:SpringApplication.setDefaultProperties() 設定的預設屬性
5:修改配置檔案位置及預設名稱
我們知道配置檔案只能以application.yml/properties來定義,但是名稱不一樣是可以指定具體檔名,也可以把配置檔案放入其它位置並指定都是可以的;指定的方式我以cmd下指定引數 java -jar xxx.jar --xxx -xxx 方式指定,或在IDEA裡面指定-xxx引數
# 自定義配置檔名稱 --spring.config.name=myApplication # 指定配置檔案儲存位置 或 指定配置檔案儲存位置及配置檔名稱
--spring.config.location=classpath:/myconfig/myApplication.yml
注:多個配置引數以空格隔開 --xxx -xxx
九:SpringBoot監聽器
我們知道JavaEE包括13門規範,其中Servlet規範包括三個技術點:Servlet、Listener、Filter;而本章介紹的是監聽器,監聽器就是監聽某個物件的狀態變化;SpringBoot中的監聽器有很多種:如下
①:CommandLineRunner 應用程式啟動完成後
②:ApplicationRunner 應用程式啟動完成後
③:ApplicationContextInitializer 程式執行初始化前
④:SpringApplicationRunListener 多功能監聽器
1:對開發者有益的監聽器
@Component //實現CommandLineRunner介面的監聽器必須要加入IOC容器 public class MyCommandLineRunner implements CommandLineRunner { //注 引數args是主函式入口的args傳來的 @Override public void run(String... args) throws Exception { System.out.println("應用程式啟動完成後 列印:CommandLineRunner"); } }
@Component //實現ApplicationRunner介面的監聽器必須要加入IOC容器 public class MyApplicationRunner implements ApplicationRunner { //注 引數args是主函式入口的args傳來的 @Override public void run(ApplicationArguments args) throws Exception { System.out.println("應用程式啟動完成後 列印:ApplicationRunner"); } }
2:對框架開發者有意義的監聽器 功能多
public class MyApplicationContextInitializer implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext applicationContext) { System.out.println("程式執行初始化前 列印:ApplicationContextInitializer"); } }
public class MySpringApplicationRunListener implements SpringApplicationRunListener { //注意:此構造方法必須要寫 不寫就給你報個錯誤 public MySpringApplicationRunListener(SpringApplication application, String[] args) {} @Override public void starting(ConfigurableBootstrapContext bootstrapContext) { System.out.println("應用程式開始啟動==>starting"); } @Override public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) { System.out.println("環境準備完成==>environmentPrepared"); } @Override public void contextPrepared(ConfigurableApplicationContext context) { System.out.println("Spring容器準備完成==>contextPrepared"); } @Override public void contextLoaded(ConfigurableApplicationContext context) { System.out.println("Spring容器載入完成==>contextLoaded"); } @Override public void started(ConfigurableApplicationContext context) { System.out.println("應用程式啟動完成==>started"); } //注:running成功與failed異常只會存在一個 @Override public void running(ConfigurableApplicationContext context) { System.out.println("應用程式開始執行==>running"); } @Override public void failed(ConfigurableApplicationContext context, Throwable exception) { System.out.println("應用程式執行時丟擲異常==>failed"); } }
# 說明 在resources目錄下建立META-INF資料夾 並在裡面建立一個spring.factories # 主要目的是解耦:將監聽器的配置權交給第三方廠商、外掛開發者 # 框架提供介面,實現類由你自己來寫,釋放原生API能力,增加可定製性 # META-INF/spring.factories檔案中配置介面的實現類名稱 # 配置ApplicationContextInitializer監聽器的配置 # 左邊監聽器的全路徑名稱=右邊實現此監聽器的全路徑名 org.springframework.context.ApplicationContextInitializer=cn.xw.lintener.MyApplicationContextInitializer # 配置SpringApplicationRunListener監聽器的配置 # 左邊監聽器的全路徑名稱=右邊實現此監聽器的全路徑名 org.springframework.boot.SpringApplicationRunListener=cn.xw.lintener.MySpringApplicationRunListener
十:自動配置實現分析
我們在匯入spring-boot-starter-web啟動器無需其它配置就可以之間用,還有我們匯入spring-boot-starter-data-redis啟動器後可以直接使用@Autowired直接注入RedisTemplate物件,很奇怪吧,這就是SpringBoot自動配置特性,在下幾節我慢慢引入
1:@Import註解進階
當我們需要匯入某個類到spring容器中去,但spring恰好無法掃描到這個類,而我們又無法修改這個類(jar包形式)。我們就可以通過@import(xxx.class)是將這個類匯入到spring容器中
(1):直接匯入
//配置類 springConfig @Configuration @Import(value={DateConfig.class}) //直接匯入 public class SpringConfig { } //普通類,裡面有個@Bean注入方法 DateConfig //被任何一個配置類引用,當前自己類也變為子配置類 public class DateConfig { //建立時間物件放入容器 @Bean public Date createDate() { return new Date(); } }
(2):通過配置類匯入
@Configuration public class SpringConfig { //建立時間物件放入容器 @Bean public Date createDate() { return new Date(); } } @SpringBootApplication @Import(value={SpringConfig.class}) //匯入配置類 public class LintenerDemoApplication { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(LintenerDemoApplication.class, args); //列印時間物件 System.out.println(run.getBean(Date.class)); } }
(3):通過ImportSelector介面實現類匯入 高階方式
//普通類 裡面有個@Bean注入物件 public class DateConfig { //建立時間物件放入容器 @Bean public Date createDate() { return new Date(); } } //建立一個類實現ImportSelector public class MyImportSelector implements ImportSelector { //這個方法是返回配置類的全類名,匯入多少都行,最後通過@Import匯入 @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { //返回一個陣列 return new String[]{"cn.xw.config.DateConfig"}; } } @SpringBootApplication @Import(value={MyImportSelector.class}) //匯入配置類 public class LintenerDemoApplication { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(LintenerDemoApplication.class, args); //列印時間物件 System.out.println(run.getBean(Date.class)); } }
2:@Configuration註解進階
相對這個註解大家肯定不陌生,只要是Spring註解配置類都有這玩意;其實只要新增@Configuration註解的類裡面可以衍生出各種條件註解供我們使用,前提只能在註解類下使用,它就是@Conditional條件註解,這個條件註解又衍生出各種詳細的條件註解
注:@EnableAutoConfiguration 其本質是 @Import 和 @Configuration的組合
一:class類條件 @ConditionalOnClass == 存在指定類條件 @ConditionalOnMissingClass == 不存在指定類條件 二:屬性條件 @ConditionalOnProperty == 屬性條件,還可以為屬性設定預設值 三:Bean條件 @ConditionalOnBean == 存在Bean條件 @ConditionalOnMissingBean == 不存在Bean條件 @ConditionalOnSingleCondidate == 只有一個Bean條件 四:資源條件 @ConditionalResource == 資源條件 五:Web應用條件 @ConditionalOnWebApplication == web應用程式條件 @ConditionalOnNotWebApplication == 不是web應用程式條件 六:其他條件 @ConditionalOneExpression == EL表示式條件 @ConditionalOnJava == 在特定的Java版本條件
@Configuration還有一些載入順序的方式
1:@AutoConfigureBefore==在那些自動配置之前執行 2:@AutoConfigureAfter==在那些自動配置之後執行 3:@AutoConfigureOrder==自動配置順序
(1):@ConditionalOnClass 與 @ConditionalOnProperty 介紹
@ConditionalOnClass註解屬性介紹 Class<?>[] value():以類的class形式的陣列 String[] name():以類的全路徑名的字串陣列 @ConditionalOnProperty註解屬性介紹 value 和 name:陣列,獲取對應property名稱的值,它們只能存在其中一個 prefix:配置屬性名稱的字首,比如spring.http.encoding havingValue:可與name組合使用,比較獲取到的屬性值與havingValue給定的值是否相同,相同才載入配置 matchIfMissing:缺少該配置屬性時是否可以載入。如果為true,沒有該配置屬性時也會正常載入;反之則不會生效
//學生類 public class Student { private String name; private String identity; //省略了get/set, } //老師類 public class Teacher { private String name; private String identity; //省略了get/set, } //需求,當建立Teacher加入容器時得判斷當前是否存在Student這個類 @Configuration @ConditionalOnClass(name = "cn.xw.pojo.Student") public class SpringConfig { //可以通過spring.myconfig.enable=true開啟 或者false 關閉容器註冊 @Bean(value = "teacher") @ConditionalOnProperty(prefix = "spring.myconfig", name = "enable", havingValue ="true", matchIfMissing = true) public Teacher createTeacher() { Teacher teacher = new Teacher(); teacher.setName("張老師"); teacher.setIdentity("老師"); return teacher; } } @SpringBootApplication //匯入配置類 @Import(value={SpringConfig.class}) public class LintenerDemoApplication { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(LintenerDemoApplication.class, args); //列印時間物件 System.out.println(run.getBean(Teacher.class).getName()); } } //application.properties # 關閉容器註冊 spring.myconfig.enable=false
//註解類 @Configuration(proxyBeanMethods = false) //條件註解 確儲存在RedisOperations類 @ConditionalOnClass(RedisOperations.class) //@Import 和 @ConfigurationProperties結合 RedisProperties類就是我們配置額外變數的spring.redis @EnableConfigurationProperties(RedisProperties.class) //匯入配置類 @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) public class RedisAutoConfiguration { @Bean //判斷不存在redisTemplate的Bean條件 @ConditionalOnMissingBean(name = "redisTemplate") //判斷只有一個RedisConnectionFactory的Bean條件 @ConditionalOnSingleCandidate(RedisConnectionFactory.class) public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); return template; } //下面差不多 @Bean @ConditionalOnMissingBean @ConditionalOnSingleCandidate(RedisConnectionFactory.class) public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } }
十一:自定義auto-Configuration及starter
我們平常匯入是第三方mybatis-spring-boot-starter啟動器都是由第三方提供給,特點就是以mybatis開頭,那下面我們自定義starter也得是自定義名稱開頭,我們要自定義auto-Configuraction並使用必備的四個角色:功能主體框架、自動配置模組、starter模組、開發者引用
1:定製自動配置必要內容 autoconfiguration模組,包含自動配置程式碼。自定義 *-spring-boot-autoconfigure。 starter模組。自定義 *-spring-boot-starter 2:自動配置命名方式 官方的Starters spring-boot-starter-* 如:spring-boot-starter-web 非官方的starters *-spring-boot-starter 如:mybatis-spring-boot-starter 3:SpringBoot起步依賴,Starter Dependencies
接下來我要建立一個第三方模組,功能主體模組是一個圖形列印模組,根據配置檔案的不同列印出不同的圖案,還要就是一個自動配置模組和starter模組咯,最後由我來在普通的springboot應用中呼叫這個自定義的自動配置
(1):功能主體模組
⭐主體功能模組maven座標 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.tx</groupId> <artifactId>graphic-printing</artifactId> <version>1.0-SNAPSHOT</version> <!--設定maven使用什麼版本的jdk解析編譯--> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> </project> ⭐主體功能模組具體類方法 //圖形列印物件 public class GraphicPrintingUtil { private Integer width = 4; private Integer height = 3; //別忘了新增get/set方法,後面會引數注入 //列印圖形 方法 public void graphicPrinting() { System.out.println(">圖形開始列印<"); for (int i = 1; i <= height; i++) { for (int j = 1; j <= width; j++) { System.out.print(" * "); } System.out.println(); } } }
(2):自動配置模組
⭐自動配置模組maven座標 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!--匯入Springboot父座標--> <parent> <artifactId>spring-boot-starter-parent</artifactId> <groupId>org.springframework.boot</groupId> <version>2.4.1</version> </parent> <!--當前本專案的一些資訊--> <groupId>cn.tx</groupId> <artifactId>graphic-spring-boot-autoconfigure</artifactId> <version>1.0-SNAPSHOT</version> <!--座標--> <dependencies> <!--匯入SpringBoot的自動配置座標 因為程式碼中要寫配置註解--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <!--匯入我們之前建立的主體模組graphic-printing--> <dependency> <groupId>cn.tx</groupId> <artifactId>graphic-printing</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </project> ⭐自動配置模組具體類方法 ## GraphicConfiguration類 @Configuration //註解類 @Import(value = {GraphicProperties.class}) //匯入配置類 @ConditionalOnClass(GraphicPrintingUtil.class)//判斷當前專案是否存在GraphicPrintingUtil類 public class GraphicConfiguration { @Bean @ConditionalOnProperty(prefix = "graphic.printing", name = "enable", havingValue = "true", matchIfMissing = true) //@ConfigurationProperties(prefix = "graphic.config") 可以使用此註解直接注入 注入時值可有可無 public GraphicPrintingUtil createGraphicPrintingUtil(GraphicProperties g) { //建立圖形列印物件,主體模組上的物件 GraphicPrintingUtil printingUtil = new GraphicPrintingUtil(); //設定寬高 printingUtil.setHeight(g.getHeight()); printingUtil.setWidth(g.getWidth()); return printingUtil; } } ## GraphicProperties 配置類 //這裡報紅不管他,後面使用者匯入<artifactId>spring-boot-configuration-processor</artifactId> @ConfigurationProperties(prefix = "graphic.config") public class GraphicProperties { private Integer width; private Integer height; //別忘了寫get/set }
# 註冊自定義自動配置
# 前面是固定的,後面是自定義配置類
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.tx.config.GraphicConfiguration
(3):stater模組
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!--自己專案座標--> <groupId>cn.tx</groupId> <artifactId>graphic-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!--主體功能模組--> <dependency> <groupId>cn.tx</groupId> <artifactId>graphic-printing</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--自動配置類autoconfigure--> <dependency> <groupId>cn.tx</groupId> <artifactId>graphic-spring-boot-autoconfigure</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </project>
注:此模組啥都不用,只要pom.xml檔案即可
(3):開發者引用
注:此模組和正常SpringBoot一樣,可以使用腳手架構建 ⭐使用者maven座標 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!--springboot父座標--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.1</version> <relativePath/> </parent> <!--本專案的座標資訊--> <groupId>cn.xw</groupId> <artifactId>test001</artifactId> <version>0.0.1-SNAPSHOT</version> <name>test001</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--匯入我們自定義的stater啟動器--> <dependency> <groupId>cn.tx</groupId> <artifactId>graphic-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--一定要匯入,是為了注入配置檔案裡面的數值--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> </dependencies> <!--maven外掛--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> ⭐使用者具體類方法 @SpringBootApplication public class Test001Application { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(Test001Application.class, args); //ConfigurableApplicationContext是ClassPathXmlApplicationContext子類 run.getBean(GraphicPrintingUtil.class).graphicPrinting(); } } ⭐配置檔案application.properties graphic.printing.enable=true graphic.config.width=10 graphic.config.height=15
十二:切換內建web應用伺服器
SpringBoot的web環境中預設使用tomcat作為內建伺服器,其實還提供了另外2種內建伺服器供我們選擇,我們可以很方便的進行切換。
1:Tomcat:這個是使用最廣泛但效能不太好的web應用伺服器 預設
2:Jetty:Jetty 是一個開源的servlet容器,它為基於Java的web容器,例如JSP和servlet提供執行環境。
3:Undertow: 是紅帽公司開發的一款基於 NIO 的高效能 Web 嵌入式伺服器
Tomcat方式:Tomcat started on port(s): 8080 (http) with context path ''
Jetty方式:Jetty started on port(s) 8080 (http/1.1) with context path '/'
Undertow方式:Undertow started on port(s) 8080 (http)
<!--匯入web的starter啟動器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!--一定要排除tomcat的starter 因為預設就是tomcat--> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <!--匯入jetty容器依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency>
<!--匯入web的starter啟動器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!--一定要排除tomcat的starter 因為預設就是tomcat--> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <!--匯入undertow容器依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency>
十三:SpringBoot生產級監控
SpringBoot自帶監控功能Actuator,可以幫助實現對程式內部執行情況監控,比如監控狀況、Bean載入情況、配置屬性、日誌資訊等
1:專案整合Actuator監控服務
其實匯入健康服務特別簡單,任何一個SpringBoot只需要加入一個監控啟動器則可開啟監控服務,然後專案正常執行即可
<!--監控服務Actuator啟動器-->
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
儲存SpringBoot匯入監控座標後啟動程式,在程式執行的情況下訪問 http://localhost:8080/actuator 則可監控程式
補充:預設只可以監控這幾項,其實可以監測很多模組
路徑 描述 預設開啟
/beans 顯示容器的全部的Bean,以及它們的關係 N
/env 獲取全部環境屬性 N
/env/{name} 根據名稱獲取特定的環境屬性值 N
/health 顯示健康檢查資訊 Y
/info 顯示設定好的應用資訊 Y
/mappings 顯示所有的@RequestMapping資訊 N
/metrics 顯示應用的度量資訊 N
/scheduledtasks 顯示任務排程資訊 N
/httptrace 顯示Http Trace資訊 N
/caches 顯示應用中的快取 N
/conditions 顯示配置條件的匹配情況 N
/configprops 顯示@ConfigurationProperties的資訊 N
/loggers 顯示並更新日誌配置 N
/shutdown 關閉應用程式 N
/threaddump 執行ThreadDump N
/headdump 返回HeadDump檔案,格式為HPROF N
/prometheus 返回可供Prometheus抓取的資訊 N
常用application.properties配置
# 暴露所有的監控點
management.endpoints.web.exposure.include=*
# 定義Actuator訪問路徑
management.endpoints.web.base-path=/act
# 開啟endpoint 關閉服務功能 訪問關閉路徑只能傳送post請求才可關閉
management.endpoint.shutdown.enabled=true