**一、**Spring Boot 入門
<!-- 這個插件,可以將應用打包成一個可執行的jar包;-->
<artifactId>spring-boot-maven-plugin</artifactId>
將這個應用打成jar包,直接使用java -jar的命令進行執行;
1、啓動器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Spring Boot將所有的功能場景都抽取出來,做成一個個的starters(啓動器),只需要在項目裏面引入這些starter相關場景的所有依賴都會導入進來。要用什麼功能就導入什麼場景的啓動器
2、主程序類
@SpringBootApplication: Spring Boot應用標註在某個類上說明這個類是SpringBoot的主配置類,SpringBoot就應該運行這個類的main方法來啓動SpringBoot應用;
J2EE的整體整合解決方案和自動配置都在spring-boot-autoconfigure-1.5.9.RELEASE.jar;
1、配置文件
SpringBoot使用一個全局的配置文件,配置文件名是固定的;
•application.properties
•application.yml
我們可以導入配置文件處理器,以後編寫配置就有提示了
<!--導入配置文件處理器,配置文件進行綁定就會有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
2、@Value VS @ConfigurationProperties
@Value:只是在某個業務邏輯中需要獲取一下配置文件中的某項值,;
@ConfigurationProperties:我們專門編寫了一個javaBean來和配置文件進行映射;
4、@PropertySource VS @ImportResource
@PropertySource:加載指定的配置文件;
@ImportResource:導入Spring的配置文件,
@ImportResource(locations = {"classpath:beans.xml"})
導入Spring的配置文件讓其生效
spring給容器中注入組件的幾種方式
1.包掃描+組件標註註解(@Controller/@Service/@Repository/@Component)適用於把自己寫的類加入組件(默認ID類名首字母小寫)
2.@Bean[導入的第三方包裏面的組件] (注意一定要在這個配置類上加上@Configuration)
3.@Import[快速給容器中導入一個組件]
4.使用Spring提供的 FactoryBean(工廠Bean);
2、Profile
1、多Profile文件
我們在主配置文件編寫的時候,文件名可以是 application-{profile}.properties/yml 默認使用application.properties的配置;
3、激活指定profile
1、在配置文件中指定 spring.profiles.active=dev
2、命令行:java -jar XXX.jar --spring.profiles.active=dev;
3、虛擬機參數;-Dspring.profiles.active=dev
3、配置文件加載位置
springboot 啓動會掃描以下位置的application.properties或者application.yml文件作爲Spring boot的默認配置文件
–file:./config/
–file:./
–classpath:/config/(mvn項目 resources 目錄就是默認的classpath)
–classpath:/
優先級由高到底,高優先級的配置會覆蓋低優先級的配置,SpringBoot會從這四個位置全部加載主配置文件;互補配置;可通過spring.config.location來改變默認配置文件位置
java -jar XXX.jar --spring.config.location=G:/application.properties
4、外部配置加載順序
1.命令行參數**
2.來自java:comp/env的JNDI屬性
3.Java系統屬性(System.getProperties())
4.操作系統環境變量
5.RandomValuePropertySource配置的random.*屬性值
6.jar包外部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
7.jar包內部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
8.jar包外部的application.properties或application.yml(不帶spring.profile)配置文件
9.jar包內部的application.properties或application.yml(不帶spring.profile)配置文件
10.@Configuration註解類上的@PropertySource
11.通過SpringApplication.setDefaultProperties指定的默認屬性
二、自動配置原理
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
1、自動配置原理:
1)、SpringBoot啓動的時候加載主配置類,開啓了自動配置功能
@SpringBootConfiguration:Spring Boot的配置類;
—@Configuration:配置類;
——@Component 配置類也是容器中的一個組件;
2)、@EnableAutoConfiguration 作用:
@EnableAutoConfiguration
—@AutoConfigurationPackage:自動配置包: 將主配置類(@SpringBootApplication標註的類)的所在包及下面所有子包裏面的所有組件掃描到Spring容器;
—@Import(AutoConfigurationImportSelector.class): 給容器中導入組件,AutoConfigurationImportSelector:導入組件選擇器;將所有需要導入的組件以全類名的方式返回;這些組件就會被添加到容器中:
- —selectImports()方法:
- ——List configurations = getCandidateConfigurations(, );獲取候選的配置
-
SPI機制傳送門:深入理解SPI機制List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); SPI技術:掃描所有jar包類路徑下 META-INF/spring.factories
spring.factories中每一個 xxxAutoConfiguration類都是容器中的一個組件,都加入到容器中;用他們來做自動配置;
-
3)、每一個自動配置類進行自動配置功能;
4)、以**HttpEncodingAutoConfiguration(Http編碼自動配置)**爲例解釋自動配置原理;
@Configuration //表示這是一個配置類,以前編寫的配置文件一樣,也可以給容器中添加組件
@EnableConfigurationProperties(HttpEncodingProperties.class) //啓動指定類的ConfigurationProperties功能;將配置文件中對應的值和HttpEncodingProperties綁定起來;並把HttpEncodingProperties加入到ioc容器中
@ConditionalOnWebApplication //Spring底層@Conditional註解(Spring註解版),根據不同的條件,如果滿足指定的條件,整個配置類裏面的配置就會生效; 判斷當前應用是否是web應用,如果是,當前配置類生效
@ConditionalOnClass(CharacterEncodingFilter.class) //判斷當前項目有沒有這個類CharacterEncodingFilter;SpringMVC中進行亂碼解決的過濾器;
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) //判斷配置文件中是否存在某個配置 spring.http.encoding.enabled;如果不存在,判斷也是成立的
//即使我們配置文件中不配置pring.http.encoding.enabled=true,也是默認生效的;
public class HttpEncodingAutoConfiguration {
//他已經和SpringBoot的配置文件映射了
private final HttpEncodingProperties properties;
//只有一個有參構造器的情況下,參數的值就會從容器中拿
public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
this.properties = properties;
}
@Bean //給容器中添加一個組件,這個組件的某些值需要從properties中獲取
@ConditionalOnMissingBean(CharacterEncodingFilter.class) //判斷容器沒有這個組件?
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
return filter;
}
根據當前不同的條件判斷,決定這個配置類是否生效
一但這個配置類生效;這個配置類就會給容器中添加各種組件;這些組件的屬性是從對應的properties類中獲取的,這些類裏面的每一個屬性又是和配置文件綁定的;
5)、所有在配置文件中能配置的屬性都是在xxxxProperties類中封裝者‘;配置文件能配置什麼就可以參照某個功能對應的這個屬性類
精髓:
1)、SpringBoot啓動會加載大量的自動配置類
2)、我們看我們需要的功能有沒有SpringBoot默認寫好的自動配置類;
3)、我們再來看這個自動配置類中到底配置了哪些組件;(只要我們要用的組件有,我們就不需要再來配置了)
4)、給容器中自動配置類添加組件的時候,會從properties類中獲取某些屬性。我們就可以在配置文件中指定這些屬性的值;
xxxxAutoConfigurartion:自動配置類;
給容器中添加組件 :@Bean
xxxxProperties:封裝配置文件中相關屬性;
2、細節
自動配置類必須在一定的條件下才能生效;我們怎麼知道哪些自動配置類生效;
我們可以通過啓用 debug=true屬性;來讓控制檯打印自動配置報告,這樣我們就可以很方便的知道哪些自動配置類生效
三、日誌
1、日誌框架
異步模式、自動歸檔。
一個統一的接口層:日誌門面(日誌的一個抽象層);給項目中導入具體的日誌實現就行了;
市面上的日誌框架;
日誌門面 (日誌的抽象層) | 日誌實現 |
---|---|
Log4j JUL(java.util.logging) Log4j2 Logback |
左邊選一個門面(抽象層)、右邊來選一個實現;
SpringBoot默認 SLF4j和logback;
2、SLF4j使用
1、如何在系統中使用SLF4j
開發的時候,日誌記錄方法的調用,不應該來直接調用日誌的實現類,而是調用日誌抽象層裏面的方法;
給系統裏面導入slf4j的jar和 logback的jar
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
2、遺留問題
如何讓系統中所有的日誌都統一到slf4j;
1、將系統中其他日誌框架先排除出去;
2、用中間包來替換原有的日誌框架;
3、我們導入slf4j其他的實現
底層依賴關係
總結:
1)、SpringBoot底層也是使用slf4j+logback的方式進行日誌記錄
2)、SpringBoot也把其他的日誌都替換成了slf4j;
3)、中間替換包
@SuppressWarnings("rawtypes")
public abstract class LogFactory {
static String UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J = "http://www.slf4j.org/codes.html#unsupported_operation_in_jcl_over_slf4j";
static LogFactory logFactory = new SLF4JLogFactory();
4、日誌使用;
1、默認配置
SpringBoot默認幫我們配置好了日誌;
//日誌由低到高 trace<debug<info<warn<error
logging.level.com.atguigu=trace
給類路徑下放上每個日誌框架自己的配置文件即可;SpringBoot就不使用他默認配置的了
三、嵌入式Servlet容器原理
SpringBoot默認使用Tomcat作爲嵌入式的Servlet容器;
1)、如何定製和修改Servlet容器的相關配置;
1、修改和server有關的配置(ServerProperties【也是EmbeddedServletContainerCustomizer】);
server.port=8081
server.context-path=/crud
server.tomcat.uri-encoding=UTF-8
//通用的Servlet容器設置
server.xxx
//Tomcat的設置
server.tomcat.xxx
2、編寫一個嵌入式的Servlet容器的定製器;來修改Servlet容器的配置
2)、註冊Servlet三大組件【Servlet、Filter、Listener】
由於SpringBoot默認是以jar包的方式啓動嵌入式的Servlet容器來啓動SpringBoot的web應用,沒有web.xml文件。
註冊三大組件用以下方式
ServletRegistrationBean
//註冊三大組件
@Bean
public ServletRegistrationBean myServlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new MyServlet(),"/myServlet");
return registrationBean;
}
FilterRegistrationBean
@Bean
public FilterRegistrationBean myFilter(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new MyFilter());
registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet"));
return registrationBean;
}
ServletListenerRegistrationBean
@Bean
public ServletListenerRegistrationBean myListener(){
ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>(new MyListener());
return registrationBean;
}
SpringBoot幫我們自動MVC的時候,自動註冊SpringMVC的前端控制器;DIspatcherServlet;
DispatcherServletAutoConfiguration中:
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public ServletRegistrationBean dispatcherServletRegistration(
DispatcherServlet dispatcherServlet) {
ServletRegistrationBean registration = new ServletRegistrationBean(
dispatcherServlet, this.serverProperties.getServletMapping());
//默認攔截: / 所有請求;包靜態資源,但是不攔截jsp請求; /*會攔截jsp
//可以通過server.servletPath來修改SpringMVC前端控制器默認攔截的請求路徑
registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
registration.setLoadOnStartup(
this.webMvcProperties.getServlet().getLoadOnStartup());
if (this.multipartConfig != null) {
registration.setMultipartConfig(this.multipartConfig);
}
return registration;
}
默認支持:引入web模塊默認就是使用嵌入式的Tomcat作爲Servlet容器;
嵌入式Servlet容器啓動原理;
什麼時候創建嵌入式的Servlet容器工廠?什麼時候獲取嵌入式的Servlet容器並啓動Tomcat;
獲取嵌入式的Servlet容器工廠:
1)、SpringBoot應用啓動運行run方法
2)、refreshContext(context);SpringBoot刷新IOC容器【創建IOC容器對象,並初始化容器,創建容器中的每一個組件】
3)、refresh(context);刷新剛纔創建好的ioc容器;
4)、 onRefresh(); web的ioc容器重寫了onRefresh方法
由 refresh() 可知,重寫方法的執行順序爲:postProcessBeanFactory()、onRefresh()、finishRefresh()。
.postProcessBeanFactory()
- 添加後置處理器 WebApplicationContextServletContextAwareProcessor
- 忽略自動裝配以來接口 ServletContextAware
- 註冊 web 應用的作用域
.onRefresh()
- 調用父類的 onRefresh() 方法
- 創建 Web 服務器
onRefresh() 創建 Web 服務器時,首先從 BeanFactory 獲取 ServletWebServerFactory 類型的 Bean,即Tomcat/Jetty/Undertow ,默認 TomcatServletWebServerFactory。利用這個工廠類的方法public WebServer getWebServer(ServletContextInitializer... initializers)
來創建 TomcatWebServer,這個方法主要就是爲 TomcatWebServer 創建 Tomcat 實例。此外,注意其入參 ServletContextInitializer 是函數式接口,可以將其方法作爲參數傳入,初始化 TomcatWebServer 時,調用 Tomcat.start() 啓動 Server,以異步的方式執行該函數接口的實現類,即執行 onStartup() 方法。
創建 Tomcat 實例這一步完成初始化的工作,其生命週期狀態變化爲:NEW
->INITIALIZING
->INITIALIZED
,INITIALIZED
表示已經初始化的狀態。
.finishBeanFactoryInitialization(beanFactory)
從 BeanFactory 獲取 name 爲 requestMappingHandlerMapping 的 Bean,並初始化這個 Bean,過程中執行其實現的接口方法 InitializingBean.afterPropertiesSet(),該方法遍歷所有可用的 Bean,找到 @Controller 或者 @RequestMapping 註解的類,利用反射技術,遍歷出這些類的方法及其請求 URL 的映射關係進行緩存。
.finishRefresh()
真正完成啓動 Tomcat,其生命週期狀態變化爲:INITIALIZED
->STARTING_PREP
->STARTING
->STARTED
,即表示啓動成功。
9、使用外置的Servlet容器
嵌入式Servlet容器:應用打成可執行的jar
優點:簡單、便攜;
缺點:默認不支持JSP、優化定製比較複雜(自己編寫嵌入式Servlet容器的創建工廠);
外置的Servlet容器:外面安裝Tomcat—應用war包的方式打包;
流程:
1)、啓動Tomcat
2)、spring-web-4.3.14.RELEASE.jar!\META-INF\services\javax.servlet.ServletContainerInitializer:
Spring的web模塊裏面有這個文件:org.springframework.web.SpringServletContainerInitializer
3)、SpringServletContainerInitializer將@HandlesTypes(WebApplicationInitializer.class)標註的所有這個類型的類都傳入到onStartup方法的Set<Class<?>>;爲這些WebApplicationInitializer類型的類創建實例;
4)、每一個WebApplicationInitializer都調用自己的onStartup;
.png)]
5)、相當於我們的SpringBootServletInitializer的類會被創建對象,並執行onStartup方法
6)、SpringBootServletInitializer實例執行onStartup的時候會createRootApplicationContext;創建容器
7)、Spring的應用就啓動並且創建IOC容器
啓動Servlet容器,再啓動SpringBoot應用
#Docker
docker主機(Host):安裝了Docker程序的機器(Docker直接安裝在操作系統之上);
docker客戶端(Client):連接docker主機進行操作;
docker倉庫(Registry):用來保存各種打包好的軟件鏡像;
docker鏡像(Images):軟件打包好的鏡像;放在docker倉庫中;
docker容器(Container):鏡像啓動後的實例稱爲一個容器;容器是獨立運行的一個或一組應用
1)、SpringData簡介
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-b93b42EV-1591340161211)(images/搜狗截圖.png)]
自定義starter:
2、如何編寫自動配置
@Configuration //指定這個類是一個配置類
@ConditionalOnXXX //在指定條件成立的情況下自動配置類生效
@AutoConfigureAfter //指定自動配置類的順序
@Bean //給容器中添加組件
@ConfigurationPropertie結合相關xxxProperties類來綁定相關的配置
@EnableConfigurationProperties //讓xxxProperties生效加入到容器中
自動配置類要能加載
將需要啓動就加載的自動配置類,配置在META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
3、模式:
啓動器只用來做依賴導入;
專門來寫一個自動配置模塊;
別人只需要引入啓動器(starter),啓動器依賴自動配置:自定義啓動器名-spring-boot-starter
步驟:
- 編寫屬性類: HelloProperties
- 編寫服務類 :HelloService
- 編寫配置類:
@Configuration
@ConditionalOnWebApplication //web應用才生效
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {
@Autowired
HelloProperties helloProperties;
@Bean
public HelloService helloService(){
HelloService service = new HelloService();
service.setHelloProperties(helloProperties);
return service;
}
}
4 編寫spring.factories 文件
5.mvn install 打到本地倉庫