上篇文章咱們已經聊了SpringBoot的啓動過程當中的各種擴展點,那麼從http://start.spring.io上咱們生成的demo項目中,到目前就剩下了maven工程的pom.xml
尚未進行探索了,那麼本文咱們就來看看這裏面到底都有啥,把大力出奇跡的常見spring-boot-starter來聊一聊,以便更好地使用SpringBoot.css
首先,咱們仍是按照一向的做風,先上源碼,再解析:html
<?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>com.hafiz</groupId>
<artifactId>springboot-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.13.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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>
咱們能夠看到全部的結構都是咱們熟悉的。首先映入眼簾的是:<parent></parent>
標籤,熟悉Maven的朋友都知道,這個標籤用來定義要繼承的父pom的信息,它用來定義SpringBoot項目可能用到的依賴和插件聲明以及一些資源文件聲明,這樣咱們就能夠在本身的SpringBoot項目中用到這些依賴或者插件的時候直接飲用,而不用指定版本號,正如咱們上面看到的spring-boot-starter-web
、spring-boot-starter-test
依賴以及spring-boot-maven-plugin
插件同樣,父pom.xml的源碼以下:java
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.13.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
<artifactId>spring-boot-starter-parent</artifactId>
<packaging>pom</packaging>
<name>Spring Boot Starter Parent</name>
<description>Parent pom providing dependency and plugin management for applications
built with Maven</description>
<url>http://projects.spring.io/spring-boot/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>http://www.spring.io</url>
</organization>
<properties>
<java.version>1.6</java.version>
<resource.delimiter>@</resource.delimiter> <!-- delimiter that doesn't clash with Spring ${} placeholders -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<!-- Turn on filtering by default for application properties -->
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/application*.yml</include>
<include>**/application*.yaml</include>
<include>**/application*.properties</include>
</includes>
</resource>
<resource>
<directory>${basedir}/src/main/resources</directory>
<excludes>
<exclude>**/application*.yml</exclude>
<exclude>**/application*.yaml</exclude>
<exclude>**/application*.properties</exclude>
</excludes>
</resource>
</resources>
<pluginManagement>
<plugins>
<!-- Apply more sensible defaults for user projects -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>${start-class}</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Tests.java</include>
<include>**/*Test.java</include>
</includes>
<excludes>
<exclude>**/Abstract*.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<archive>
<manifest>
<mainClass>${start-class}</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<mainClass>${start-class}</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<delimiters>
<delimiter>${resource.delimiter}</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<verbose>true</verbose>
<dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
</configuration>
</plugin>
<!-- Support our own plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>${start-class}</mainClass>
</configuration>
</plugin>
<!-- Support shade packaging (if the user does not want to use our plugin) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.13.RELEASE</version>
</dependency>
</dependencies>
<configuration>
<keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope>
<createDependencyReducedPom>true</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer implementation="org.springframework.boot.maven.PropertiesMergingResourceTransformer">
<resource>META-INF/spring.factories</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>${start-class}</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
可是咱們發現,該父pom文件還有本身的父pom,做用相似,再也不詳解,感興趣的能夠本身去翻閱源碼。那麼這樣看來咱們本身的SpringBoot項目中的pom.xml
文件就剩下顯眼的兩個依賴以及一個插件了(沒有指定版本號的緣由前面已經解釋了),那咱們接下來就來聊一聊這些很是重要的spring-boot-starter依賴。mysql
咱們從前面就知道了,SpringBoot可以如此方便便捷,其實都是得益於這些「開箱即用」的依賴模塊,那SpringBoot設計者約定這些「開箱即用」的依賴模塊的命名都以spring-boot-starter-
開始,而且這些模塊都位於org.springframework.boot
包或者命名空間下面。咱們也能夠模仿者來實現本身的自動配置依賴模塊,也已spring-boot-starter-
開頭,是否是就很"正宗"呢?(雖然SpringBoot官方不建議咱們這樣作,以避免跟官方提供的混淆,可是其實咱們使用本身的groupId,這樣命名應該不是啥問題)。git
這些starter其實都有約定好的默認配置,可是它也容許咱們調整這些默認配置,以便完成定製化的需求,咱們能夠改變默認配置的常見方式有如下幾種:web
這幾種方式從上到下優先級從高到低排列,高優先級的配置會覆蓋優先級低的配置。還有就是無論位於文件系統仍是classpath中的配置文件,SpringBoot應用默認的文件名稱都是application.properties
,能夠放在當前項目的根目錄下或者名稱爲config的子目錄下。spring
SpringBoot其實提供了不少這樣的模塊,咱們就挑幾個咱們經常使用的這樣的模塊來解析,其餘的你們就觸類旁通。以達到在工做和開發中靈活運用這些spring-boot-starter模塊的效果。sql
若是咱們在maven依賴中添加了spring-boot-starter-logging
:mongodb
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
那也就意味着咱們的SpringBoot應用自動使用logback做爲日誌框架,在啓動的時候,由org.springframework.boot.logging.LoggingApplicationListener
根據狀況初始化並使用。默認狀況下,SpringBoot已經給咱們提供好了不少默認的日誌配置,咱們只須要將spring-boot-starter-logging
做爲依賴加入到你的SpringBoot應用就能夠了,可是若是咱們要對這些默認配置進行定製,能夠有兩種方式進行:數據庫
遵照logback的約定,在classpath中使用定製化的logback.xml配置文件。
在文件系統中任意一個地方提供本身的logback.xml配置文件,而後經過以下配置來application.properties
中指定咱們日誌系統配置文件位置:
logging.config=/{your config file location}}/logback.xml
若是咱們已經習慣了log4j或log4j2,那咱們只須要把spring-boot-starter-logging
換成以下的starter就好。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
</dependency>
或
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
現現在,咱們在工做中大部分實際用的仍是SpringMVC開發的web應用,SpringBoot固然貼心的爲咱們開發了一個web項目模塊,讓咱們更加方便的開發web應用。maven依賴以下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
這樣咱們就能夠獲得一個能夠直接執行的Web應用,而後咱們運行mvn spring-boot:run
,就能直接啓動一個基於嵌入式tomcat容器的Web應用了,而後就能夠像這篇文章中定義controller來供用戶訪問了。可是呢,這簡單的表象之下,其實卻隱藏着不少約定,咱們要把這些潛規則瞭解清楚才能更好地應用spring-boot-starter-web
。
傳統的Java Web項目中,咱們的靜態文件以及頁面模板都是放在src/main/webapp
目錄下,可是在SpringBoot應用中,這些文件被統一放在src/main/resources
相應的子目錄下:
src/main/resources/static
目錄用於存放各類靜態資源,如:js、css、image等。src/main/resources/template
目錄用於存放模板文件。細心地咱們會發現SpringBoot的web應用已經變成了jar包而再是war包,若是咱們仍是但願以war包的形式發佈也是能夠的。
spring-boot-starter-web
默認將爲咱們自動配置以下一些SpringMVC必要的組件:
ContentNegotiatingViewResolver
和BeanNameViewResolver
。GenericConverter
和Formatter
等bean被註冊到IoC容器。HttpMessageConverter
用於支持對Web請求和相應的類型轉換。MessageCodesResolver
。 咱們知道spring-boot-starter-web
默認把嵌入式tomcat做爲web容器來對外提供HTTP服務,默認使用8080端口對外監聽和提供服務。這裏咱們可能會有兩個疑問:
咱們不想使用默認的嵌入式tomcat容器怎麼辦?
很簡單,咱們只須要引入spring-boot-starter-jetty
或spring-boot-starter-undertow
依賴就能替代默認嵌入式tomcat容器了。
咱們想要把啓動後提供服務的端口改掉怎麼辦?
咱們能夠經過在配置文件中修改啓動端口就能夠了,如:
server.port=9000
其實,spring-boot-starter-web
提供了不少以server.
做爲前綴的配置以用來修改嵌入式容器的配置,如:
server.port
server.address
server.ssl.*
server.tomcat.*
那若這些還知足不了你,SpringBoot甚至都容許咱們直接對嵌入式Web容器實例進行定製化,咱們經過向IoC容器中註冊一個EmbeddedServletContainerCustomizer
類型的組件來實現:
package com.hafiz.springbootdemo;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
/**
* @author hafiz.zhang
* @description: 自定義內嵌容器配置
* @date Created in 2018/6/10 12:09.
*/
public class DemoEmbeddedTomcatCustomizer implements EmbeddedServletContainerCustomizer {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setPort(9111);
container.setContextPath("/demo");
// ...
}
}
若是還要再深刻的定製,那就須要實現對應內嵌容器的Factory並註冊到IoC容器:
可是,咱們幾乎沒有可能須要這樣的定製化,也不建議這樣的定製化,使用SpringBoot默認的spring-boot-starter-web
提供的配置項列表已經很簡單、很完整了。
咱們知道,現實中大多數的Java應用都須要訪問數據庫,那SpringBoot確定不會放過這個組件,它會很貼心的爲咱們自動配置好相應的數據訪問工具。咱們只須要在pom.xml
中添加如下依賴就行了:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
這樣,在咱們沒有配置任何DataSource的狀況下,SpringBoot會默認爲咱們自動配置一個基於嵌入式數據的DataSource,這種自動配置適合於測試場景,生產環境不適合。大多數狀況下,咱們都會本身配置DataSource實例,或經過自動配置模塊提供的配置參數對DataSource實例配置自定義的參數。
若咱們的SpringBoot應用只依賴一個數據庫,那咱們直接使用自動配置模塊提供的配置參數最方便快捷:
spring.datasource.url=jdbc:mysql://{db host}:{db port}/{db name}
spring.datasource.username={db user name}
spring.datasource.password={db password}
有的小夥伴說了:那我本身配置一個DataSource行不行?答案是固然能夠,SpringBoot會很智能的優先選擇使用咱們本身配置的這個DataSource,可是感受畫蛇添足!你要知道,SpringBoot除了自動幫咱們配置DataSource之外,還自動幫咱們配置了相應的JdbcTemplate
以及DataSourceTransactionManager
等相關的組件,咱們只須要在須要使用的地方直接使用@Autowired
註解引用就行了。
那SpringBoot是否是一直貼心呢?很明顯不是的,若是咱們的單個項目須要依賴和訪問多個數據庫,這個時候就不行了,就算是咱們在ApplicationContext中配置了多個DataSource實例來訪問多個數據庫:
@Bean
public DataSource dataSource1() throws Throwable {
DruidDataSource ds = new DruidDataSource();
ds.setUrl(...);
ds.setUsername(...);
ds.setPassword(...);
// set other db setting
return ds;
}
@Bean
public DataSource dataSource2() throws Throwable {
DruidDataSource ds = new DruidDataSource();
ds.setUrl(...);
ds.setUsername(...);
ds.setPassword(...);
// set other db setting
return ds;
}
啓動項目時,你就會發現以下的異常:
No qualifying bean of type [javax.sql.DataSource] is defined: expected single matching bean but found 2...
那怎麼解決這個問題呢?有兩種方式:
在SpringBoot的啓動類上「動手腳」
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class
})
public class DemoSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(DemoSpringBootApplication.class, args);
}
}
這也就是說咱們須要排除掉SpringBoot默認的DataSource的相關的自動配置。
使用@primary
註解
那咱們既要配置兩個數據源,又要使用SpringBoot默認的DataSource,這時咱們就能夠爲咱們配置的兩個DataSource中的任意一個使用@primary
註解就能夠了。
@Bean
@Primary
public DataSource dataSource1() throws Throwable {
DruidDataSource ds = new DruidDataSource();
ds.setUrl(...);
ds.setUsername(...);
ds.setPassword(...);
// set other db setting
return ds;
}
@Bean
public DataSource dataSource2() throws Throwable {
DruidDataSource ds = new DruidDataSource();
ds.setUrl(...);
ds.setUsername(...);
ds.setPassword(...);
// set other db setting
return ds;
}
除此以外,SpringBoot還提供了不少其餘數據源訪問相關的自動配置模塊,如:spring-boot-starter-jpa
、spring-boot-starter-mongodb
等。
除了本文咱們介紹的經常使用的三個spring-boot-starter之外,SpringBoot還提供了不少別的starter,包括spring-boot-starter-aop
、spring-boot-starter-security
、spring-boot-starter-actuator
等等。咱們經過本文觸類旁通,能夠作到用的時候駕輕就熟。棒!給本身一個贊~