• <li id="yeaqi"><button id="yeaqi"></button></li>
  • <fieldset id="yeaqi"></fieldset>
    <fieldset id="yeaqi"><table id="yeaqi"></table></fieldset>

    •  

      天天快消息!Springboot2
      發布時間:2023-04-13 13:26:07 文章來源:騰訊云
      參考:https://www.yuque.com/leifengyang/springboot2

      參考:https://www.yuque.com/leifengyang/springboot2

      參考:https://www.bilibili.com/video/BV19K4y1L7MT?p=1&vd_source=0c3c1f43c75954a15fba4e42c1d7883e


      (資料圖片)

      1. HelloWorld

      項目結構

      1. pom.xml

          4.0.0    com.example    springboot-test    1.0-SNAPSHOT    pom            springboot-01-hello                org.springframework.boot        spring-boot-starter-parent        2.3.4.RELEASE                            org.springframework.boot            spring-boot-starter-web                        8        8        UTF-8                                            org.springframework.boot                spring-boot-maven-plugin                        

      2. MainApplication

      package com.example;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * 主程序類 * @SpringBootApplication:這是一個springboot應用 */@SpringBootApplicationpublic class MainApplication {    public static void main(String[] args) {        SpringApplication.run(MainApplication.class, args);    }}

      3. HelloController

      package com.example.controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HelloController {    @RequestMapping("/hello")    public String home() {        return "Hello world";    }}

      4. 啟動服務,瀏覽器訪問

      2. Springboot特點

      2.1 依賴管理

      2.1.1 父項目做依賴管理

              org.springframework.boot        spring-boot-starter-parent        2.3.4.RELEASE點進spring-boot-starter-parent看到:    org.springframework.boot    spring-boot-dependencies    2.3.4.RELEASE點進spring-boot-dependencies看到:    幾乎聲明了所有開發中常用的依賴的版本號

      2.1.2 開發導入starter場景啟動器

      會見到很多spring-boot-starter-*: *就代表某種場景 只要引入starter,這個場景的所有常規需要的依賴我們都自動引入SpringBoot所有支持的場景:https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter見到的 *-spring-boot-starter: 第三方為我們提供的簡化開發的場景啟動器。 所有場景啟動器最底層的依賴
           org.springframework.boot     spring-boot-starter     2.3.4.RELEASE     compile

      2.1.3 無需關注版本號,自動版本仲裁

      spring-boot-dependencies幾乎聲明了所有開發中常用的依賴的版本號,引入依賴默認都可以不寫版本=>自動版本仲裁

      2.1.4 可以修改版本號

      引入非版本仲裁的jar,要寫版本號查看spring-boot-dependencies里面規定當前依賴的版本用的 key,版本不一致=>在當前項目里面重寫配置
          5.1.43

      2.2 自動配置

      2.2.1 自動配好Tomcat

      引入Tomcat依賴
            org.springframework.boot      spring-boot-starter-tomcat      2.3.4.RELEASE      compile
      配置Tomcat ???

      2.2.2 自動配好SpringMVC

      引入SpringMVC全套組件:spring-boot-starter-web引入自動配好SpringMVC常用組件(功能)

      2.2.3 自動配好Web常見功能

      SpringBoot幫我們配置好了所有web開發的常見場景

      dispatcherServlet字符編碼:characterEncodingFilter文件上傳:multipartResolver

      2.2.4 默認的包結構

      主程序所在包及其下面的所有子包里面的組件都會被默認掃描進來無需以前的包掃描配置想要改變掃描路徑,@SpringBootApplication(scanBasePackages="com.example")或者@ComponentScan 指定掃描路徑
      @SpringBootApplication等同于@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan("com.example")

      2.2.5 各種配置擁有默認值

      application.properties:默認配置最終都是映射到某個類上,如:MultipartPropertiesapplication.properties配置文件的值最終會綁定每個類上,這個類會在容器中創建對象

      2.2.6 按需加載所有自動配置項

      非常多的starter引入了哪些場景這個場景的自動配置才會開啟SpringBoot所有的自動配置功能都在 spring-boot-autoconfigure 包里面
      package com.example;import org.springframework.boot.SpringApplication;import org.springframework.boot.SpringBootConfiguration;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.context.annotation.ComponentScan;/**@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan("com.example")等價于@SpringBootApplication(scanBasePackages="com.example") 默認掃描主程序所在的包*/@SpringBootApplicationpublic class MainApplication {    public static void main(String[] args) {        //1、返回我們IOC容器        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);        //2、查看容器里面的組件        String[] names = run.getBeanDefinitionNames();        for (String name : names) {            System.out.println("組件:" + name);        }    }}

      3. 自動配置注解

      3.1 @Configuration

      Full模式與Lite模式項目結構User
      package com.example.bean;public class User {    private String name;    private int age;    private Pet pet;    public User() {    }    public User(String name, int age) {        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public Pet getPet() {        return pet;    }    public void setPet(Pet pet) {        this.pet = pet;    }    @Override    public String toString() {        return "User{" +                "name="" + name + "\"" +                ", age=" + age +                ", pet=" + pet +                "}";    }}
      Pet
      package com.example.bean;public class Pet {    private String name;    public Pet() {    }    public Pet(String name) {        this.name = name;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public String toString() {        return "Pet{" +                "name="" + name + "\"" +                "}";    }}
      MainConfig
      package com.example.config;import com.example.bean.Pet;import com.example.bean.User;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configuration(proxyBeanMethods=true) // 告訴springboot這是一個配置類public class MainConfig {    @Bean    public User userBean(){        User u = new User("zhangsan", 18);        u.setPet(petBean());        return u;    }    @Bean    public Pet petBean(){        Pet p = new Pet("cat");        return p;    }}
      MainApplication
      package com.example;import com.example.bean.Pet;import com.example.bean.User;import com.example.config.MainConfig;import org.springframework.boot.SpringApplication;import org.springframework.boot.SpringBootConfiguration;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.context.annotation.ComponentScan;/**@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan("com.example")等價于@SpringBootApplication(scanBasePackages="com.example") 默認掃描主程序所在的包*/@SpringBootApplicationpublic class MainApplication {    public static void main(String[] args) {        //1、返回我們IOC容器        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);        //2、查看容器里面的組件        String[] names = run.getBeanDefinitionNames();        for (String name : names) {            System.out.println("組件:" + name);        }        // 3. 從容器中獲取組件        User user = (User) run.getBean("userBean");        User user2 = (User) run.getBean("userBean");        System.out.println("組件默認是單例的:" + (user==user2));        // 4. 配置類也是組件        MainConfig bean = run.getBean(MainConfig.class);        System.out.println("配置類本身也是組件:" + bean);        // 5. proxyBeanMethods = true, mainConfig就是被增強的代理對象        // springboot總會檢查組件是否在容器中存在        // 保持組件單實例        // 外部無論對配置類中的這個組件注冊方法調用多少次,獲取的都是之前注冊容器中的單實例對象        User user3 = bean.userBean();        User user4 = bean.userBean();        System.out.println("主配置是否為代理對象: "+(user3==user4));        // full: proxyBeanMethods=true  => 應用場景: 解決組件依賴        // lite: proxyBeanMethods=false => 配置類在容器中不會保存代理對象,在外邊調用方法,每次都會產生一個新對象        // Full: 保證每個@Bean方法被調用多少次返回的組件都是單實例的。類組件之間有依賴關系,方法會被調用得到之前單實例組件,用Full模式        // Lite: 每個@Bean方法被調用多少次返回的組件都是新創建的。類組件之間無依賴關系用Lite模式加速容器啟動過程,減少判斷        // 組件依賴必須使用Full模式默認。其他默認是否Lite模式        Pet pet = (Pet) run.getBean("petBean");        System.out.println("proxyBeanMethods組件依賴" + (user.getPet()==pet));    }}

      3.2 @Bean、@Component、@Controller、@Service、@Repository

      項目結構MainConfig
      package com.example.config;import com.example.bean.Pet;import com.example.bean.User;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class MainConfig {}
      User
      package com.example.bean;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;import javax.annotation.Resource;@Component("userBean")public class User {    private String name;    private int age;    @Autowired    private Pet pet;    public User() {    }    public User(String name, int age) {        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public Pet getPet() {        return pet;    }    public void setPet(Pet pet) {        this.pet = pet;    }    @Override    public String toString() {        return "User{" +                "name="" + name + "\"" +                ", age=" + age +                ", pet=" + pet +                "}";    }}
      Pet
      package com.example.bean;import org.springframework.stereotype.Component;@Component("petBean")public class Pet {    private String name;    public Pet() {    }    public Pet(String name) {        this.name = name;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public String toString() {        return "Pet{" +                "name="" + name + "\"" +                "}";    }}
      MainApplication
      package com.example;import com.example.bean.Pet;import com.example.bean.User;import com.example.config.MainConfig;import org.springframework.boot.SpringApplication;import org.springframework.boot.SpringBootConfiguration;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.context.annotation.ComponentScan;/** * @SpringBootConfiguration * @EnableAutoConfiguration * @ComponentScan("com.example") 等價于@SpringBootApplication(scanBasePackages="com.example") * 默認掃描主程序所在的包 */@SpringBootApplicationpublic class MainApplication {    public static void main(String[] args) {        //1、返回我們IOC容器        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);        //2、查看容器里面的組件        String[] names = run.getBeanDefinitionNames();        for (String name : names) {            System.out.println("組件:" + name);        }        // 3. 從容器中獲取組件        User user = (User) run.getBean("userBean");        User user2 = (User) run.getBean("userBean");        System.out.println("組件默認是單例的:" + (user == user2));        // 4. 配置類也是組件        MainConfig bean = run.getBean(MainConfig.class);        System.out.println("配置類本身也是組件:" + bean);        // 5. 組件依賴        Pet pet = (Pet) run.getBean("petBean");        System.out.println("組件依賴" + (user.getPet() == pet));    }}

      3.3 @Import、@Conditional、@ImportResource、@ConfigurationProperties

      @Import:給容器中自動創建出指定類型的組件、默認組件的名字就是全類名

      @Conditional:條件裝配,滿足Conditional指定的條件,則進行組件注入

      @ImportResource:原生配置文件引入

      @ConfigurationProperties:配置文件中的配置項綁定給組件的屬性

      項目結構MainApplication
      package com.example;import ch.qos.logback.core.db.DBHelper;import com.example.bean.Pet;import com.example.bean.User;import com.example.config.MainConfig;import org.springframework.boot.SpringApplication;import org.springframework.boot.SpringBootConfiguration;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.context.annotation.ComponentScan;import java.util.Arrays;/** @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan("com.example") 等價于@SpringBootApplication(scanBasePackages="com.example") 默認掃描主程序所在的包 *//** * @Import:給容器中自動創建出指定類型的組件、默認組件的名字就是全類名 * @Conditional:條件裝配,滿足Conditional指定的條件,則進行組件注入 * @ImportResource:原生配置文件引入 * @ConfigurationProperties:配置文件中的配置項綁定給組件的屬性 */@SpringBootApplicationpublic class MainApplication {    public static void main(String[] args) {        //1、返回我們IOC容器        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);        //2、查看容器里面的組件        String[] names = run.getBeanDefinitionNames();        for (String name : names) {            System.out.println("組件:" + name);        }        // 3. 獲取組件        Boolean flag = run.containsBean("petBean");        System.out.println("容器中是否存在petBean組件:" + flag);        Boolean flag2 = run.containsBean("userBean");        System.out.println("容器中是否存在userBean組件:" + flag2);                // 4. 容器中組件數量        System.out.println("組件數量:" + run.getBeanDefinitionCount()); // 167    }}
      mainApplication.xml
                                                      
      User
      package com.example.bean;public class User {    private String name;    private int age;    private Pet pet;    public User() {    }    public User(String name, int age) {        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public Pet getPet() {        return pet;    }    public void setPet(Pet pet) {        this.pet = pet;    }    @Override    public String toString() {        return "User{" +                "name="" + name + "\"" +                ", age=" + age +                ", pet=" + pet +                "}";    }}
      Pet
      package com.example.bean;public class Pet {    private String name;    public Pet() {    }    public Pet(String name) {        this.name = name;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public String toString() {        return "Pet{" +                "name="" + name + "\"" +                "}";    }}
      Car
      package com.example.bean;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;// @Component // MainConfig中使用了@EnableConfigurationProperties(Car.class),則不用@Component@ConfigurationProperties(prefix = "car")public class Car {    private String brand;    private double price;    public Car() {    }    public Car(String brand, double price) {        this.brand = brand;        this.price = price;    }    public String getBrand() {        return brand;    }    public void setBrand(String brand) {        this.brand = brand;    }    public double getPrice() {        return price;    }    public void setPrice(double price) {        this.price = price;    }    @Override    public String toString() {        return "Car{" +                "brand="" + brand + "\"" +                ", price=" + price +                "}";    }}
      MainConfig
      package com.example.config;import ch.qos.logback.core.db.DBHelper;import com.example.bean.Car;import com.example.bean.Pet;import com.example.bean.User;import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.*;// @ConditionalOnBean(name="petBean") // 有petBean類里的組件注冊才生效,否則都不生效@EnableConfigurationProperties(Car.class)// @EnableConfigurationProperties(Car.class)的作用:// 1. 開啟Car配置綁定功能// 2. 把這個Car這個組件自動注冊到容器中@ImportResource("classpath:mainApplication.xml")@Import({User.class, DBHelper.class})@Configuration(proxyBeanMethods=true) // 告訴springboot這是一個配置類public class MainConfig {    @ConditionalOnBean(name="petBean") // 容器中存在petBean才執行userBean的組件注冊    @Bean    public User userBean(){        User u = new User("zhangsan", 18);        u.setPet(petBean());        return u;    }    // @Bean    public Pet petBean(){        Pet p = new Pet("cat");        return p;    }}

      4. 自動配置原理

      4.1 引導加載自動配置類

      @SpringBootApplication主要組成:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan
      @SpringBootConfiguration@EnableAutoConfiguration@ComponentScan(    excludeFilters = {@Filter(    type = FilterType.CUSTOM,    classes = {TypeExcludeFilter.class}), @Filter(    type = FilterType.CUSTOM,    classes = {AutoConfigurationExcludeFilter.class})})public @interface SpringBootApplication {}

      4.1.1 @SpringBootConfiguration

      @Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Configuration // SpringBootConfiguration用來注解 配置類 => MainApplication是一個配置類(核心配置類)public @interface SpringBootConfiguration {    @AliasFor(        annotation = Configuration.class    )    boolean proxyBeanMethods() default true;}

      4.1.2 @ComponentScan:包掃描,指定要掃描哪些

      兩個自定義掃描器

      4.1.3 @EnableAutoConfiguration

      @AutoConfigurationPackage@Import({AutoConfigurationImportSelector.class})public @interface EnableAutoConfiguration {}
      @AutoConfigurationPackage
      @Import({AutoConfigurationPackages.Registrar.class}) // 給容器中導入一個組件// 指定了默認的包規則public @interface AutoConfigurationPackage {}// 利用Registrar給容器中導入一系列組件// 將指定的MainApplication所在包下的所有組件導入進來
      @Import({AutoConfigurationImportSelector.class})
      1. 利用getAutoConfigurationEntry(annotationMetadata)給容器中批量導入一些組件2. 調用List configurations = getCandidateConfigurations(annotationMetadata, attributes)獲取到所有需要導入到容器中的配置類3. 利用工廠加載 Map> loadSpringFactories(@Nullable ClassLoader classLoader)得到所有的組件4. 從META-INF/spring.factories位置來加載一個文件。    默認掃描我們當前系統里面所有META-INF/spring.factories位置的文件    spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories    文件里面寫死了spring-boot一啟動就要給容器中加載的所有配置類

      4.2 按需開啟自動配置項

      spring.factories@Conditional
      1. 雖然我們127個場景的所有自動配置啟動的時候默認全部加載。    META-INF/spring.factories文件中:xxxxAutoConfiguration2. 按照條件裝配規則(@Conditional),最終會按需配置。    eg. @ConditionalOnClass({Gson.class})

      4.3 修改默認配置

      @Bean@ConditionalOnBean(MultipartResolver.class)  //容器中有這個類型組件@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中沒有這個名字 multipartResolver 的組件public MultipartResolver multipartResolver(MultipartResolver resolver) {    //給@Bean標注的方法傳入了對象參數,這個參數的值就會從容器中找。    //SpringMVC multipartResolver。防止有些用戶配置的文件上傳解析器不符合規范// Detect if the user has created a MultipartResolver but named it incorrectlyreturn resolver;}

      SpringBoot默認會在底層配好所有的組件。但是如果用戶自己配置了以用戶的優先

      @Bean@ConditionalOnMissingBeanpublic CharacterEncodingFilter characterEncodingFilter() {}

      總結:

      SpringBoot先加載所有的自動配置類 xxxxxAutoConfiguration每個自動配置類按照條件進行生效,默認都會綁定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件進行了綁定生效的配置類就會給容器中裝配很多組件(pom.xml配置了)只要容器中有這些組件,相當于這些功能就有了定制化配置用戶直接自己@Bean替換底層的組件用戶去看這個組件是獲取的配置文件什么值就去修改

      xxxxxAutoConfiguration ---> 組件 ---> xxxxProperties里面拿值 ----> application.properties

      4,4 最佳實踐

      引入場景依賴https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter查看自動配置了哪些(選做)自己分析,引入場景對應的自動配置一般都生效了配置文件中debug=true開啟自動配置報告。Negative(不生效)\Positive(生效)是否需要修改參照文檔修改配置項https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties自己分析。xxxxProperties綁定了配置文件的哪些。自定義加入或者替換組件@Bean、@Component。。。自定義器 XXXXXCustomizer;例子resources目錄下放一張jpg圖片配置文件中添加配置項:
      spring.banner.image.location=classpath:timg.jpg

      4.5 簡化開發

      4.5.1 lombok

      引入依賴
          org.projectlombok    lombok
      idea安裝插件使用
      @ToString // toString@Data // getter、setter@AllArgsConstructor // 全參構造器@NoArgsConstructor // 無參構造器@Slf4j // 日志
      例子
      package com.example.bean;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import lombok.ToString;@ToString // toString@Data // getter、setter@AllArgsConstructor // 全參構造器@NoArgsConstructor // 無參構造器public class LombokBean {    private String str;    private int i;}
      import com.example.bean.LombokBean;import lombok.extern.slf4j.Slf4j;import org.junit.Test;@Slf4jpublic class LombokBeanTest {    @Test    public void testLombokBean(){        LombokBean o = new LombokBean();        o.setStr("abc");        o.setI(10);        System.out.println(o);        log.info(o.toString());    }}
      關鍵詞:

      樂活HOT

      娛樂LOVE