SpringBoot 框架


一、SpringBoot 概述

1.1 SpringBoot 概念

SpringBoot提供了一種快速使用Spring的方式,基於約定優於配置的思想,可以讓開發人員不必在配置與邏輯業務之間進行思維的切換,全身心的投入到邏輯業務的代碼編寫中,從而大大提高了開發的效率,一定程度上縮短了項目周期。

2014 年 4 月,Spring Boot 1.0.0 發布。Spring的頂級項目之一(https://spring.io)。

img

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);
    }
}

⑤ 啟動測試

http://localhost:8080/hello/

2.3、Spring Initializr創建SpringBoot工程

(1)直接選中Spring Initializr
img

(2)我們這里創建web工程,選中web即可
img(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

img
在主配置文件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配置
img

②打包方式配置

img

進入target文件夾(快捷鍵Ctrl+Alt+F12)

img

在當前目錄打開cmd

輸入java –jar xxx.jar啟動SpringBoot項目

輸入java –jar xxx.jar --spring.profiles.active=xxx即可更改環境

3.5 內置配置加載順序

Springboot程序啟動時,會從以下位置加載配置文件:

  1. file:./config/:當前項目下的/config目錄下
  2. file:./ :當前項目的根目錄
  3. classpath:/config/:classpath的/config目錄
  4. classpath:/ :classpath的根目錄(之前我們用的就是這種)

加載順序為上文的排列順序,高優先級配置的屬性會生效

img

3.6 外部配置加載順序

命令行參數

通過官網查看外部屬性加載順序:

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

四、整合其他框架

4.1 整合Junit

  1. 搭建SpringBoot工程

  2. 引入starter-test起步依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
  1. 編寫測試類
@Service
public class UserService {
    public void add(){
        System.out.println("add...");
    }
}

  1. 編寫測試方法
@SpringBootTest(classes = SpringbootTestApplication.class)
//這里加不加classes取決於當前測試類包所在的位置
//在引導類所在包的子包或同級則不需要加(會自動找引導類),否則要加
class SpringbootRedisApplicationTests {

    @Autowired
    UserService userService;
    @Test
    void contextLoads() {
        userService.add();
    }
}

4.2 整合Redis

  1. 搭建SpringBoot工程

  2. 引入redis起步依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. 配置redis相關屬性
spring:
  redis:
    host: 127.0.0.1 #redis的主機ip
    port: 6379
  1. 注入RedisTemplate模板

  2. 編寫測試方法,測試(記得打開本機的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

  1. 搭建SpringBoot工程

  2. 引入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>

  1. 編寫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的核心配置文件
  1. 定義表和實體類

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;
}

  1. 編寫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();
}

  1. 測試
@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,現要求:

  1. 導入Jedis坐標后,加載該Bean,沒導入,則不加載。
  2. 將類的判斷定義為動態的。判斷哪個字節碼文件存在可以動態指定。

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中內置服務器供我們選擇,我們可 以很方便的進行切換。

image-20220425132501138

默認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 模塊

image-20221024094229414

<!--引入jedis依賴-->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

② 創建 redis-spring-boot-starter 模塊嗎,依賴 redis-spring-boot-autoconfigure的模塊

image-20221024095641398

<!--引入自定義的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啟動流程

SpringBoot啟動流程

6.4 SpringBoot Actuator

SpringBoot自帶監控功能Actuator,可以幫助實現對程序內部運行情況監控,比如監控狀況、Bean加載情況、配置屬性 、日志信息等。

  1. 使用步驟

① 導入依賴坐標

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

② 訪問http://localhost:8080/actuator

  1. 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

image-20221025100651781

七、SpringBoot 項目部署

SpringBoot 項目開發完畢后,支持兩種方式部署到服務器:

① jar包(官方推薦)

② war包

jar類型項目會打成jar包:jar類型項目使用SpringBoot打包插件打包時,會在打成的jar中內置一個tomcat的jar。所以我們可以使用jdk直接運行該jar項目可,jar項目中有一個功能,將功能代碼放到其內置的tomcat中運行。我們直接使用瀏覽器訪問即可。

war類型項目會打成war包:在打包時需要將內置的tomcat插件排除,配置servlet的依賴。將war正常的放到tomcat服務器中運行即可。

7.1 jar打包方式

  1. 創建 spring-boot-deploy 模塊

  2. 將當前模塊打包

    image-20221025101053783

  3. 控制台打包成功,顯示target目錄

    image-20221025101551301

  4. 把jar包放在需要的目錄,在當前目錄打開cmd,輸入java -jar .\jar包名稱,啟動成功

7.2 war打包方式

  1. pom.xml里更改打包方式
<packaging>war</packaging>
  1. 在引導類繼承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);
    }
}
  1. 控制台打包成功,顯示target目錄

image-20221025101923042

  1. 將其放在tomcat目錄下的webapps目錄下

    image-20221025101956115

  2. 啟動tomcat即可

image-20221025102020368

  1. 此時瀏覽器訪問需要加項目的名稱,因為WEB-INF文件在其之下


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM