一、SpringBoot 概述
1.1 SpringBoot 概念
SpringBoot提供了一種快速使用Spring的方式,基於約定優於配置的思想,可以讓開發人員不必在配置與邏輯業務之間進行思維的切換,全身心的投入到邏輯業務的代碼編寫中,從而大大提高了開發的效率,一定程度上縮短了項目周期。
2014 年 4 月,Spring Boot 1.0.0 發布。Spring的頂級項目之一(https://spring.io)。
1.2 Spring 缺點
1) 配置繁瑣
雖然Spring的組件代碼是輕量級的,但它的配置卻是重量級的。
一開始,Spring用XML配置,而且是很多XML配置。
Spring 2.5 引入了基於注解的組件掃描,這消除了大量針對應用程序自身組件的顯式XML配置。
Spring 3.0 引入了基於Java的配置,這是一種類型安全的可重構配置方式,可以代替XML。
所有這些配置都代表了開發時的損耗。因為在思考Spring特性配置和解決業務問題之間需要進行思維切換,所以編寫配置擠占了編寫應用程序邏輯的時間。和所有框架一樣,Spring實用,但它要求的回報也不少。
2)依賴繁瑣
項目的依賴管理也是一件耗時耗力的事情。在環境搭建時,需要分析要導入哪些庫的坐標,而且還需要分析導入與之有依賴關系的其他庫的坐標,一旦選錯了依賴的版本,隨之而來的不兼容問題就會嚴重阻礙項目的開發進度。
1.3 SpringBoot 功能
1) 自動配置
Spring Boot的自動配置是一個運行時(更准確地說,是應用程序啟動時)的過程,考慮了眾多因素,才決定Spring配置應該用哪個,不該用哪個。該過程是SpringBoot自動完成的。
2) 起步依賴
起步依賴本質上是一個Maven項目對象模型(Project Object Model,POM),定義了對其他庫的傳遞依賴,這些東西加在一起即支持某項功能。簡單的說,起步依賴就是將具備某種功能的坐標打包到一起,並提供一些默認的功能。
3) 輔助功能
提供了一些大型項目中常見的非功能性特性,如嵌入式服務器、安全、指標,健康檢測、外部配置等。
Spring Boot 並不是對 Spring 功能上的增強,而是提供了一種快速使用 Spring 的方式。
1.4 小結
SpringBoot提供了一種快速開發Spring項目的方式,而不是對Spring功能上的增強。
Spring的缺點:
- 配置繁瑣
- 依賴繁瑣
SpringBoot功能:
- 自動配置
- 起步依賴:依賴傳遞
- 輔助功能
二、SpringBoot 快速入門
2.1、需求
搭建SpringBoot工程,定義HelloController.hello()方法,返回”Hello SpringBoot!”。
2.2、實現步驟
① 創建Maven項目
在porm.xml配置以下代碼,導入SpringBoot起步依賴
<!--springboot工程需要繼承的父工程-->
<parent>
<groupId>org.springframework.boot</groupId>
<version>2.3.0.RELEASE</version>
<artifactId>spring-boot-starter-parent</artifactId>
</parent>
<dependencies>
<!--web開發的起步依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
③ 定義Controller
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "hello spring boot!";
}
}
④ 編寫引導類
引導類作SpringBoot的項目入口
/**
* 引導類。SpringBoot項目的入口
*/
@SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class,args);
}
}
⑤ 啟動測試
2.3、Spring Initializr創建SpringBoot工程
(1)直接選中Spring Initializr
(2)我們這里創建web工程,選中web即可
(3) 創建完畢,SpringBoot會自動配置好需要的依賴和創建相關目錄
(4) 自己創建controller測試即可
2.4、SpringBoot起步依賴原理分析
- 在spring-boot-starter-parent中定義了各種技術的版本信息,組合了一套最優搭配的技術版本。
- 在各種starter中,定義了完成該功能需要的坐標合集,其中大部分版本信息來自於父工程。
- 我們的工程繼承parent,引入starter后,通過依賴傳遞,就可以簡單方便獲得需要的jar包,並且不會存在版本沖突等問題
2.5、總結
- SpringBoot在創建項目時,使用jar的打包方式。
- SpringBoot的引導類,是項目入口,運行main方法就可以啟動項目。
三、配置
3.1 配置文件分類
SpringBoot是基於約定的,所以很多配置都有默認值,但如果想使用自己的配置替換默認配置的話,就可以使用 application.properties或者application.yml(application.yaml)進行配置。
properties:
server.port=8080
yaml:
server:
port: 8080
總結:
- SpringBoot提供了2種配置文件類型:properteis和yml/yaml
- 默認配置文件名稱:application
- 在同一級目錄下優先級為:properties > yml > yaml
3.2 yaml
yaml:YAML全稱是 YAML Ain’t Markup Language 。YAML是一種直觀的能夠被電腦識別的的數據數據序列化格式,並且容易被人類閱讀,容易和腳本語言交互的,可以被支持YAML庫的不同的編程語言程序導入,比如: C/C++, Ruby, Python, Java, Perl, C#, PHP等。YML文件是以數據為核心的,比傳統的xml方式更加簡潔。 YAML文件的擴展名可以使用.yml或者.yaml。
對比:
properties:
server.port=8080
server.address=127.0.0.1
xml:
<server>
<port>8080</port>
<address>127.0.0.1</address>
</server>
yaml:
server:
port: 8080
address: 127.0.0.1
可以看出:對比其他兩種方式,yaml更簡潔,以數據為核心。
yaml基本語法
- 大小寫敏感
- 數據值前邊必須有空格,作為分隔符
- 使用縮進表示層級關系
- 縮進時不允許使用Tab鍵,只允許使用空格(各個系統 Tab對應的 空格數目可能不同,導致層次混亂)。
- 縮進的空格數目不重要,只要相同層級的元素左側對齊即可
- # 表示注釋,從這個字符一直到行尾,都會被解析器忽略。
server:
port: 8080
address: 127.0.0.1
name: abc
yaml數據格式
對象(map):鍵值對的集合
person:
name: zhangsan
# 行內寫法
person: {name: zhangsan}
數組:一組按次序排列的值
address:
- beijing
- shanghai
# 行內寫法
address: [beijing,shanghai]
純量:單個的,不可再分的值
msg1: 'hello \n world' # 單引忽略轉義字符
msg2: "hello \n world" # 雙引識別轉義字符
yaml參數引用
name: lisi
person:
name: ${name} # 引用上邊定義的name值
3.3 讀取配置文件內容
先預先准備好測試的ymal文件:
name: xpp
person:
name: ${name}
age: 23
address:
- benjing
- shanghai
address:
- benjing
- shanghai
msg1: 'hello \n springboot'
msg2: "hello \n springboot"
@Value
@Value("${name}")
private String name;
@Value("${person.name}")
private String name1;
@Value(("${address[0]}"))
private String address1;
@Value("${msg1}")
private String msg1;
@Value("${msg2}")
private String msg2;
@RequestMapping("/hello2")
public String hello2(){
System.out.println(name);
System.out.println(name1);
System.out.println(address1);
System.out.println(msg1);
System.out.println(msg2);
return "Hello SpringBoot !";
}
輸出結果:
xpp
xpp
benjing
hello \n springboot
hello
springboot
Environment
Environment讀取yaml配置文件
@Autowired
private Environment env;
@RequestMapping("/hello2")
public String hello2(){
System.out.println(env.getProperty("name"));
System.out.println(env.getProperty("person.age"));
System.out.println(env.getProperty("address[0]"));
return "Hello SpringBoot !";
}
輸出:
xpp
23
benjing
@ConfigurationProperties
我們使用 @Value
注解或着使用 Spring Environment
bean 訪問這些屬性,這種注入配置方式有時顯得很笨重。我們將使用更安全的方式(@ConfigurationProperties
)來獲取這些屬性
准備一個Person類:
@Component//表示這個類被spring識別了
@ConfigurationProperties(prefix = "person")//綁定前綴
//下面四個注解為LomBok提供的,簡化開發,自動幫我們寫好get,set,有參,無參和toString方法
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Person {
private String name;
private Integer age;
private String[] address;
}
測試:
@Autowired
private Person person;
@RequestMapping("/hello2")
public String hello2(){
System.out.println(person);
return "Hello SpringBoot !";
}
輸出結果:
Person(name=xpp, age=23, address=[benjing, shanghai])
3.4 profile
我們在開發Spring Boot應用時,通常同一套程序會被安裝到不同環境,比如:開發、測試、生產等。其中數據庫地址、服務器端口等等配置都不同,如果每次打包時,都要修改配置文件,那么非常麻煩。profile功能就是來進行動態配置切換的。
profile配置方式
(1)多profile文件方式
提供多個配置文件,每一個代表一種環境:
- application-dev.properties/yml 開發環境
- application-test.properties/yml 測試環境
- application-pro.properties/yml 生產環境
注意!:格式必須為application-xxx.properties/yml
在主配置文件application.properties選擇用哪種環境:
格式:spring.profiles.active=xxx
spring.profiles.active=dev
(2)yaml多文檔方式
---用來划分yaml文件區域
---
server:
port: 8081
spring:
config:
activate:
on-profile: dev
---
server:
port: 8082
spring:
config:
activate:
on-profile: test
---
server:
port: 8083
spring:
config:
activate:
on-profile: pro
---
spring:
profiles:
active: test
profile激活方式
(1)配置文件
即上面所講的:在配置文件中配置:spring.profiles.active=dev
(2)虛擬機
在VM options 指定:-Dspring.profiles.active=xxx
①直接在Program arguments
配置
②打包方式配置
進入target文件夾(快捷鍵Ctrl+Alt+F12
)
在當前目錄打開cmd
輸入java –jar xxx.jar
啟動SpringBoot項目
輸入java –jar xxx.jar --spring.profiles.active=xxx
即可更改環境
3.5 內置配置加載順序
Springboot程序啟動時,會從以下位置加載配置文件:
- file:./config/:當前項目下的/config目錄下
- file:./ :當前項目的根目錄
- classpath:/config/:classpath的/config目錄
- classpath:/ :classpath的根目錄(之前我們用的就是這種)
加載順序為上文的排列順序,高優先級配置的屬性會生效
3.6 外部配置加載順序
命令行參數
通過官網查看外部屬性加載順序:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
四、整合其他框架
4.1 整合Junit
-
搭建SpringBoot工程
-
引入starter-test起步依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
- 編寫測試類
@Service
public class UserService {
public void add(){
System.out.println("add...");
}
}
- 編寫測試方法
@SpringBootTest(classes = SpringbootTestApplication.class)
//這里加不加classes取決於當前測試類包所在的位置
//在引導類所在包的子包或同級則不需要加(會自動找引導類),否則要加
class SpringbootRedisApplicationTests {
@Autowired
UserService userService;
@Test
void contextLoads() {
userService.add();
}
}
4.2 整合Redis
-
搭建SpringBoot工程
-
引入redis起步依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置redis相關屬性
spring:
redis:
host: 127.0.0.1 #redis的主機ip
port: 6379
-
注入
RedisTemplate
模板 -
編寫測試方法,測試(記得打開本機的redis)
@SpringBootTest
class SpringbootRedisApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testSet(){
//存數劇
redisTemplate.boundValueOps("name").set("zhangsan");
}
@Test void testGet(){
//獲取數據
Object name = redisTemplate.boundValueOps("name").get();
System.out.println(name);
}
}
4.3 整合MyBatis
-
搭建SpringBoot工程
-
引入mybatis起步依賴,添加mysql驅動
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
- 編寫DataSource和MyBatis相關配置
DataSource配置信息:
spring:
datasource:
url: jdbc:mysql:///mzz
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
用注解開發可以不用寫MyBatis的配置xml開發MyBatis相關配置
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml #mapper映射文件路徑
type-aliases-package: com.itheima.springbootmybatis.domain #配置別名
#config-location: 指定mybatis的核心配置文件
- 定義表和實體類
表
USE `mzz`;
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`password` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
insert into `t_user`(`id`,`username`,`password`) values (1,'zhangsan','123'),(2,'lisi','234');
實體類
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
}
- 編寫dao和mapper文件/純注解開發
xml開發:
@Mapper
@Repository
public interface UserXmlMapper {
public List<User> findAll();
}
<?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.itheima.springbootmybatis.mapper.UserXmlMapper">
<select id="findAll" resultType="user">
select * from t_user
</select>
</mapper>
純注解開發:
@Mapper
@Repository//這里可加可不加,mybatis提供@Mapper可以代替
public interface UserMapper {
@Select("select * from t_user")
public List<User> findAll();
}
- 測試
@SpringBootTest
class SpringbootMybatisApplicationTests {
@Autowired
private UserMapper userMapper;
@Autowired
private UserXmlMapper userXmlMapper;
@Test
void testFindAll() {
List<User> res = userMapper.findAll();
for (User user : res) {
System.out.println(user);
}
}
@Test
void testFindAll1() {
List<User> res = userXmlMapper.findAll();
for (User user : res) {
System.out.println(user);
}
}
}
五、SpringBoot自動配置
5.1 Condition
Condition 是在Spring 4.0 增加的條件判斷功能,通過這個可以功能可以實現選擇性的創建 Bean 操作。
滿足條件才創建,不滿足不創建。
思考:
SpringBoot是如何知道要創建哪個Bean的?比如SpringBoot是如何知道要創建RedisTemplate的?
引出問題
看一個栗子:
當我們沒導入redis-start時,會報錯
@SpringBootApplication
public class SpringbootDemo01Application {
public static void main(String[] args) {
//啟動SpringBoot應用,返回Spring的IOC容器
ConfigurableApplicationContext run = SpringApplication.run(SpringbootDemo01Application.class, args);
//獲取Bean,redisTemplate
Object redisTemplate = run.getBean("redisTemplate");
System.out.println(redisTemplate);
}
}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'redisTemplate' available
當導入redis起步依賴后
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
org.springframework.data.redis.core.RedisTemplate@b7ff25
問題:
SpringBoot是怎么知道我們導入redis坐標的呢?
案例
需求:
在 Spring 的 IOC 容器中有一個 User 的 Bean,現要求:
- 導入Jedis坐標后,加載該Bean,沒導入,則不加載。
- 將類的判斷定義為動態的。判斷哪個字節碼文件存在可以動態指定。
bean:
public class User {
}
//自定義注解可以合並多個注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 將自定義注解放到@Conditional中
@Conditional(ClassCondition.class)
public @interface ConditionOnClass {
String[] value();
}
@Configuration
public class UserConfig {
@Bean
//@Conditional(ClassCondition.class)
//有Jedis字節碼
@ConditionOnClass("redis.clients.jedis.Jedis")
public User user(){
return new User();
}
}
自定義注解:
public class ClassCondition implements Condition {
/**
* @param context 上下文對象,用於獲取環境,ClassLoader對象
* @param metadata 注解的元對象,可以用於注解定義的屬性值
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
//1.需求:導入指定坐標后創建Bean
//思路:判斷指定坐標文件是否存在
//獲取注解屬性值 value
Map<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
String[] value = (String[]) map.get("value");
boolean flag = true;
try {
for (String className : value) {
// 獲得class對象
Class<?> cls = Class.forName(className);
}
} catch (ClassNotFoundException e) {
//異常報錯
flag = false;
}
return flag;
}
}
總結
自定義條件:
① 定義條件類:自定義類實現Condition接口,重寫 matches 方法,在 matches 方法中進行邏輯判斷,返回 boolean值 。 matches 方法兩個參數:
- context:上下文對象,可以獲取屬性值,獲取類加載器,獲取BeanFactory等。
- metadata:元數據對象,用於獲取注解屬性。
② 判斷條件:在初始化Bean時,使用 @Conditional(條件類.class)注解
SpringBoot 提供的常用條件注解:
- ConditionalOnProperty:判斷配置文件中是否有對應屬性和值才初始化Bean
@Bean
@ConditionalOnProperty(name = "itcast",havingValue = "itheima")
public User user1(){
return new User();
}
當配置文件中有一個鍵為itcast,有一個值為itheima時才會去加載對應的這個bean。
itcast=itheima
-
ConditionalOnClass:判斷環境中是否有對應字節碼文件才初始化Bean
-
ConditionalOnMissingBean:判斷環境中沒有對應Bean才初始化Bean
5.2 切換內置web服務器
SpringBoot的web環境中默認使用tomcat
作為內置服務器,其實SpringBoot提供了4中內置服務器供我們選擇,我們可 以很方便的進行切換。
默認Tomcat
如果要使用其他的服務器:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--排除tomcat依賴-->
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--引入相應服務器的依賴-->
<dependency>
<artifactId>spring-boot-starter-jetty</artifactId>
<groupId>org.springframework.boot</groupId>
</dependency>
5.3 @Enable*注解
SpringBoot中提供了很多Enable開頭的注解,這些注解都是用於動態啟用某些功能的。而其底層原理是使用@Import注 解導入一些配置類,實現Bean的動態加載。
提問:SpringBoot 工程是否可以直接獲取jar包中定義的Bean?
答:不可以
案例:
兩個子模塊,自己構造一個@Enable注解
①子模塊要得到②子模塊的User類的bean(這里用編號表示)
①導入②的依賴:
<dependency>
<groupId>com.itheima</groupId>
<artifactId>springboot-embal</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
①的引導類
/**
* 不能的原因在於 @ComponentScan
* @ComponentScan掃描范圍:當前引導類所在包及其子包
* //1.使用@ComponentScan掃描com.itheima.springbooyembal包
* //2.可以使用@Import注解,加載類,這些類都會被Spring創建,並放入IOC容器。
* //3.可以對@Import注解進行封裝
*/
@SpringBootApplication
//@ComponentScan("com.itheima.springbooyembal")
//@Import(UserConfig.class)
@EnableUser
public class SpringbootDemo01Application {
public static void main(String[] args) {
//啟動SpringBoot應用,返回Spring的IOC容器
ConfigurableApplicationContext run = SpringApplication.run(SpringbootDemo01Application.class, args);
Object user = run.getBean("user");
System.out.println(user);
}
}
②的配置類
@Configuration
public class UserConfig {
@Bean
public User user(){
return new User();
}
}
②的自定義@EnableUser
注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(UserConfig.class)
public @interface EnableUser {
}
5.4 @Import注解
@Enable*
底層依賴於@Import
注解導入一些類,使用@Import
導入的類會被Spring加載到IOC容器中。而@Import
提供4中用法:
導入Bean 【@Import(User.classs)
】
導入配置類 【@Import(UserConfig.class)
】
導入 ImportSelector
實現類。一般用於加載配置文件中的類
@Import(MyImportSelector.class)
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[{"com.itheima.springbooyembal.domain.User","com.itheima.springbooyembal.domain.Role"};
}
}
導入 ImportBeanDefinitionRegistrar
實現類。
@Import(MyImportBeanDefinitionRegistrar.class)
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
registry.registerBeanDefinition("user",beanDefinition);
}
}
5.5 @EnableAutoConfiguration
- @EnableAutoConfiguration 注解內部使用 @Import(AutoConfigurationImportSelector.class)來加載配置類。
- 配置文件位置:META-INF/spring.factories,該配置文件中定義了大量的配置類,當 SpringBoot 應用啟動時,會自動加載 這些配置類,初始化Bean
- 並不是所有的Bean都會被初始化,在配置類中使用Condition來加載滿足條件的Bean
5.6 starter案例
需求
自定義redis-starter。要求當導入redis坐標時,SpringBoot自動創建Jedis的Bean
實現步驟
① 創建 redis-spring-boot-autoconfigure
模塊
<!--引入jedis依賴-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
② 創建 redis-spring-boot-starter
模塊嗎,依賴 redis-spring-boot-autoconfigure
的模塊
<!--引入自定義的autocongifure-->
<dependency>
<groupId>com.ithiema</groupId>
<artifactId>redis-spring-boot-autocongifure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
③ 在 redis-spring-boot-autoconfigure
模塊中初始化 Jedis 的 Bean。並定義META-INF/spring.factories
文件
作用:
把需要加載的bean的配置類加入到EnableAutoConfiguration中
springboot啟動時會加載這些配置類,放入IOC容器中
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ithiema.redis.config.RedisAutoConfiguration
// 以redis開頭的配置 會和RedisProperties相綁定
@ConfigurationProperties(prefix = "redis")
@Data
public class RedisProperties {
// 用戶不配置 默認為本機
private String host="localhost";
private Integer port=6379;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
@Configuration
// 啟用RedisProperties 被spring識別
@EnableConfigurationProperties(RedisProperties.class)
@ConditionalOnClass(Jedis.class)
public class RedisAutoConfiguration {
/**
*提供Jedis的bean
*/
@Bean
@ConditionalOnMissingBean(name="jedis")
public Jedis jedis(RedisProperties redisProperties){
System.out.println("xppmzz");
return new Jedis(redisProperties.getHost(),redisProperties.getPort());
}
}
④ 在測試模塊中引入自定義的 redis-starter 依賴,測試獲取 Jedis 的Bean,操作 redis。
<dependency>
<groupId>com.itheima</groupId>
<artifactId>redis-sping-boot-start</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
@SpringBootApplication
public class SpringbootEnablrApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(SpringbootEnablrApplication.class, args);
Jedis jedis = run.getBean(Jedis.class);
jedis.set("name11", "xppmzz");
System.out.println(jedis);
}
}
六、SpringBoot 監聽機制
6.1 Java 監聽機制
SpringBoot 的監聽機制,其實是對Java提供的事件監聽機制的封裝。
Java中的事件監聽機制定義了以下幾個角色:
① 事件:Event,繼承 java.util.EventObject 類的對象
② 事件源:Source ,任意對象Object
③ 監聽器:Listener,實現 java.util.EventListener 接口 的對象
6.2 SpringBoot監聽機制
SpringBoot 在項目啟動時,會對幾個監聽器進行回調,我們可以實現這些監聽器接口,在項目啟動時完成 一些操作。 ApplicationContextInitializer、SpringApplicationRunListener、CommandLineRunner、ApplicationRunner
ApplicationContextInitializer
不是監聽器,但可以當做監聽器來用
// 在banner 圖標之后 就開始初始化
// 用於項目還沒有准備IOC容器之前,去檢測一些資源是否存在
@Component
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("ApplicationContextInitializer...initialize");
}
}
SpringApplicationRunListener
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
public MySpringApplicationRunListener(SpringApplication application,String[] args) {
}
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
SpringApplicationRunListener.super.starting(bootstrapContext);
}
@Override
public void starting() {
System.out.println("starting...項目啟動中");
}
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
SpringApplicationRunListener.super.environmentPrepared(bootstrapContext, environment);
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
System.out.println("environmentPrepared...環境對象開始准備");
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("contextPrepared...上下文對象開始准備");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
//到此時,IOC容器已經初始化好了
System.out.println("contextLoaded...上下文對象開始加載");
}
@Override
public void started(ConfigurableApplicationContext context) {
System.out.println("started...上下文對象加載完成");
}
@Override
public void running(ConfigurableApplicationContext context) {
System.out.println("running...項目啟動完成,開始運行");
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("failed...項目啟動失敗");
}
}
CommandLineRunner
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner...run");
System.out.println(Arrays.asList(args));
}
}
ApplicationRunner
/**
* 當項目啟動后執行run方法
* 可以用於提前加載緩存redis 緩存預熱
*/
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner...run");
System.out.println(Arrays.asList(args.getSourceArgs()));
}
}
ApplicationContextInitializer、SpringApplicationRunListener使用需要在META-INF中配置。
org.springframework.context.ApplicationContextInitializer=com.itheima.springbootlistener.listener.MyApplicationContextInitializer
org.springframework.boot.SpringApplicationRunListener=com.itheima.springbootlistener.listener.MySpringApplicationRunListener
6.3 SpringBoot啟動流程
6.4 SpringBoot Actuator
SpringBoot自帶監控功能Actuator
,可以幫助實現對程序內部運行情況監控,比如監控狀況、Bean加載情況、配置屬性 、日志信息等。
- 使用步驟
① 導入依賴坐標
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
② 訪問http://localhost:8080/actuator
- SpringBoot 監控使用
路徑 | 描述 |
---|---|
/beans | 描述應用程序上下文里全部的Bean,以及它們的關系 |
/env | 獲取全部環境屬性 |
/env/{name} | 根據名稱獲取特定的環境屬性值 |
/health | 報告應用程序的健康指標,這些值由HealthIndicator的實現類提供 |
/info | 獲取應用程序的定制信息,這些信息由info打頭的屬性提供 |
/mappings | 描述全部的URI路徑,以及它們和控制器(包含Actuator端點)的映射關系 |
/metrics | 報告各種應用程序度量信息,比如內存用量和HTTP請求計數 |
/metrics/{name} | 報告指定名稱的應用程序度量值 |
/trace | 提供基本的HTTP請求跟蹤信息(時間戳、HTTP頭等) |
6.5 SpringBoot Admin
Spring Boot Admin是一個開源社區項目,用於管理和監控SpringBoot應用程序。
Spring Boot Admin 有兩個角色,客戶端(Client)和服務端(Server)。
應用程序作為Spring Boot Admin Client向為Spring Boot Admin Server注冊
Spring Boot Admin Server 的UI界面將Spring Boot Admin Client的Actuator Endpoint上的一些監控信息
admin-server
① 創建 admin-server 模塊
② 導入依賴坐標 admin-starter-server
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
③ 在引導類上啟用監控功能@EnableAdminServer
@SpringBootApplication
@EnableAdminServer
public class SpringbootAdminServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootAdminServerApplication.class, args);
}
}
admin-client
① 創建 admin-client 模塊
② 導入依賴坐標 admin-starter-client
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
③ 配置相關信息:server地址等
#指定admin.server地址
spring.boot.admin.client.url=http://localhost:9000
#展示健康檢查詳細詳細展示出來
management.endpoint.health.show-details=always
#開啟所有配置
management.endpoints.web.exposure.include=*
④ 啟動server和client服務,訪問server
七、SpringBoot 項目部署
SpringBoot 項目開發完畢后,支持兩種方式部署到服務器:
① jar包(官方推薦)
② war包
jar類型項目會打成jar包:jar類型項目使用SpringBoot打包插件打包時,會在打成的jar中內置一個tomcat的jar。所以我們可以使用jdk直接運行該jar項目可,jar項目中有一個功能,將功能代碼放到其內置的tomcat中運行。我們直接使用瀏覽器訪問即可。
war類型項目會打成war包:在打包時需要將內置的tomcat插件排除,配置servlet的依賴。將war正常的放到tomcat服務器中運行即可。
7.1 jar打包方式
-
創建 spring-boot-deploy 模塊
-
將當前模塊打包
-
控制台打包成功,顯示target目錄
-
把jar包放在需要的目錄,在當前目錄打開cmd,輸入
java -jar .\jar包名稱
,啟動成功
7.2 war打包方式
- pom.xml里更改打包方式
<packaging>war</packaging>
- 在引導類繼承SpringBootServletInitializer類,並重寫configure方法
@SpringBootApplication
public class SpringBootDeployApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SpringBootDeployApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SpringBootDeployApplication.class);
}
}
- 控制台打包成功,顯示target目錄
-
將其放在tomcat目錄下的webapps目錄下
-
啟動tomcat即可
- 此時瀏覽器訪問需要加項目的名稱,因為WEB-INF文件在其之下