spring boot項(xiàng)目搭建

  1. <strong>寫在前面</strong>
    ======
    通過閱讀官方文檔以及編寫一些demo辈毯,個(gè)人認(rèn)為spring boot的核心思想是約定大于配置以及使用java配置代替xml配置湘换,簡化繁瑣的項(xiàng)目配置同時(shí)避免維護(hù)繁雜的xml文件午磁。
  2. <strong>使用idea創(chuàng)建項(xiàng)目</strong>
    ======



    這里創(chuàng)建一個(gè)web項(xiàng)目砚著,查看pom文件咳秉,spring boot默認(rèn)將項(xiàng)目打包成一個(gè)fat jar而不是war

<groupId>com.jd</groupId>
    <artifactId>sblearn</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

打包成可執(zhí)行jar需要引入spring boot的插件

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

項(xiàng)目配置可以繼承starter-parent,通常只需要指定parent的版本秉颗,其他需要的starter版本parent都會(huì)給出相應(yīng)的版本

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
    </parent>

啟動(dòng)一個(gè)spring boot web項(xiàng)目還需要依賴

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

這里解釋一下starter痢毒,starter包含了需要的各種依賴也可以包含代碼以及配置的元數(shù)據(jù),由于有了starter蚕甥,我們使用的時(shí)候就無需再去添加各種依賴哪替,同時(shí)starter有許多默認(rèn)的配置,比如默認(rèn)使用內(nèi)置tomcat菇怀,默認(rèn)使用的端口號(hào)凭舶,默認(rèn)的上下文路徑,我們就無需再配置爱沟。

  1. <strong>認(rèn)識(shí)代碼和配置文件</strong>
    ======
    項(xiàng)目的目錄如下所示:

    項(xiàng)目創(chuàng)建過后帅霜,idea會(huì)生成一個(gè)spring boot啟動(dòng)類,啟動(dòng)類需要被@SpringBootApplication注解呼伸,同時(shí)在main函數(shù)里面啟動(dòng)應(yīng)用(注:這是jar包的啟動(dòng)方式身冀,如果使用本地tomcat war包啟動(dòng),代碼有差別)括享。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SblearnApplication {

    public static void main(String[] args) {
        SpringApplication.run(SblearnApplication.class, args);
    }
}

看一看@SpringBootApplication搂根,該注解源代碼如下,注意Java doc最后一句奶浦,該注解等價(jià)于
@Configuration兄墅,@EnableAutoConfiguration,@ComponentScan

/**
 * Indicates a {@link Configuration configuration} class that declares one or more
 * {@link Bean @Bean} methods and also triggers {@link EnableAutoConfiguration
 * auto-configuration} and {@link ComponentScan component scanning}. This is a convenience
 * annotation that is equivalent to declaring {@code @Configuration},
 * {@code @EnableAutoConfiguration} and {@code @ComponentScan}.
 *
 * @author Phillip Webb
 * @author Stephane Nicoll
 * @since 1.2.0
 */
@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 

第一是通過@SpringBootConfiguration表明該注解是一個(gè)@configuration注解的替代物澳叉,@configuration注解的部分java doc如下,可以看出該注解是告訴spring容器可以讀取類里面被@Bean注解的方法并生成相應(yīng)的bean沐悦。不難看出成洗,如果啟動(dòng)類里面不包含需要添加到容器的bean,那么@SpringBootConfiguration可以省略

* Indicates that a class declares one or more {@link Bean @Bean} methods and
 * may be processed by the Spring container to generate bean definitions and
 * service requests for those beans at runtime, for example:
 *
 * <pre class="code">
 * @Configuration
 * public class AppConfig {
 *
 *     @Bean
 *     public MyBean myBean() {
 *         // instantiate, configure and return bean ...
 *     }
 * }

@EnableAutoConfiguration則是告訴spring boot使用上下文自動(dòng)配置藏否,spring boot將會(huì)盡可能聰明的配置應(yīng)用需要的bean瓶殃。
@ComponentScan則是掃描啟動(dòng)類路徑下所有的bean,因此啟動(dòng)類要放在類路徑最外層副签,保證所有bean都被掃描到遥椿。
再看resource目錄,分別包含static映射靜態(tài)資源淆储,templates包含模板文件冠场,以及項(xiàng)目配置屬性文件application.properties,此時(shí)配置文件為空本砰。
此時(shí)web項(xiàng)目已經(jīng)可以啟動(dòng)碴裙,從這里至少可以看出,spring boot啟用了內(nèi)置tomcat幫我們完成配置,同時(shí)也不需要配置web.xml和spring mvc的一些基礎(chǔ)配置舔株,比如靜態(tài)資源路徑莺琳,mvc注解驅(qū)動(dòng)

<!-- 添加MVC注解模式 -->
    <mvc:annotation-driven/>
    <!-- 映射靜態(tài)資源 -->
    <mvc:resources location="/WEB-INF/statics/" mapping="/resource/**"/>

此外還將resources目錄下的資源文件打包到了jar/war,不需要在pom里面另行配置载慈。

  1. <strong>spring boot的屬性配置</strong>
    ======
    spring boot的屬性配置具有一定的優(yōu)先級(jí)別惭等,這里直接給出官方文檔的內(nèi)容:
1. home目錄下的devtools全局設(shè)置屬性( ~/.spring-bootdevtools.
properties ,如果devtools激活)办铡。
2. 測試用例上的@TestPropertySource注解辞做。
3. 測試用例上的@SpringBootTest#properties注解。
4. 命令行參數(shù)
5. 來自 SPRING_APPLICATION_JSON 的屬性(環(huán)境變量或系統(tǒng)屬性中內(nèi)嵌的內(nèi)聯(lián)
JSON)料扰。
6. ServletConfig 初始化參數(shù)凭豪。
7. ServletContext 初始化參數(shù)。
8. 來自于 java:comp/env 的JNDI屬性晒杈。
9. Java系統(tǒng)屬性(System.getProperties())嫂伞。
10. 操作系統(tǒng)環(huán)境變量。
11. RandomValuePropertySource拯钻,只包含 random.* 中的屬性帖努。
12. 沒有打進(jìn)jar包的Profile-specific應(yīng)用屬性( application-
{profile}.properties 和YAML變量)。
13. 打進(jìn)jar包中的Profile-specific應(yīng)用屬性( application-
{profile}.properties 和YAML變量)粪般。
14. 沒有打進(jìn)jar包的應(yīng)用配置( application.properties 和YAML變量)拼余。
15. 打進(jìn)jar包中的應(yīng)用配置( application.properties 和YAML變量)。
16. @Configuration 類上的 @PropertySource 注解亩歹。
17. 默認(rèn)屬性(使用 SpringApplication.setDefaultProperties 指定)匙监。

劃重點(diǎn),4在15小作,16確保了可以在命令行可以根據(jù)環(huán)境選擇哪一個(gè)配置文件以及特定的屬性配置亭姥。
spring boot支持yml文件進(jìn)行配置,個(gè)人比較支持這種新的方式顾稀,簡潔明了达罗。spring會(huì)加載application.yml,如果想要加載特定文件可以在application.yml里面提供如下配置:

#需要額外引入其他配置文件的時(shí)候可以通過spring.profiles.include=a,b静秆,其中a,b代表配置文件“-”后的部分粮揉,比如
#applicaition-important.yml,那么就應(yīng)該使用important
spring:
  profiles:
    active: dev
    include: important,log

這里在項(xiàng)目中已經(jīng)存在application-dev.yml抚笔,application-important.yml扶认,以及application-log.yml。該配置表示要激活application-dev.yml(默認(rèn)是激活application-default.yml)塔沃,同時(shí)引入application-important.yml蝠引,application-log.yml阳谍。也可以在命令行通過--spring.profiles.active=dev來進(jìn)行激活。
3.1 <strong>yml的使用</strong>


yml文件采用key:value的形式螃概,比起properties文件更加簡潔和直觀矫夯,注意的是冒號(hào)后面需要一個(gè)空格。yml文件中可以引入已經(jīng)定義的屬性吊洼,如果是yml文件中的屬性通過${}引入训貌,如果是pom文件中的屬性則使用@@,如下:

production: dev
boot:
  word: hey + ${production}
  name: jason
env:
  basic: @env.demo.basic@
<profiles>
        <profile>
            <id>all-env</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <env.demo.basic>demo-basic-prop</env.demo.basic>
            </properties>
        </profile>
    </profiles>

3-2 <strong>使用隨機(jī)值</strong>

spring boot可以使用random.*為配置文件生成隨機(jī)值冒窍,這種方式利于測試

my: 
    secret: ${random.value}
    number: ${random.int}
    bignumber: ${random.long}
    number.less.than.ten: ${random.int(10)}
    number.in.range: ${random.int[1024,65536]}

使用規(guī)則是random.int*語法是 OPEN value (,max) CLOSE 递沪,此處 OPEN,CLOSE 可以是任何字符综液,并且 value款慨,max 是整數(shù)。如果提供 max 谬莹,那么 value 是最小值檩奠, max 是最大值(不包含在內(nèi))。
3-3 <strong>屬性值的使用</strong>


項(xiàng)目中的屬性值都保存在上下文的enviroment中附帽,要使用屬性值有三種方式埠戳,第一種是使用@Value進(jìn)行注入:

@Value("${env.basic}")
private String basicProp;

第二種是使用@ConfigurationProperties通過在類或者方法上進(jìn)行注解,參數(shù)prefix表示屬性名的前綴蕉扮,spring將會(huì)盡可能的將以擁有該前綴的數(shù)值型注入到類和方法返回對(duì)象中整胃,下面注解到類上時(shí),boot.word以及boot.name將可以注入到BootProperties類的實(shí)例上面喳钟。@ConfigurationProperties還可以和java提供的一些校驗(yàn)注解搭配使用屁使,比如@NotEmpty

@ConfigurationProperties(prefix = "boot")
@Component
public class BootProperties {
   @NotEmpty
    private String word;
    @NotEmpty
    private String name;

    public String getWord() {
        return word;
    }

    public BootProperties setWord(String word) {
        this.word = word;
        return this;
    }

    public String getName() {
        return name;
    }

    public BootProperties setName(String name) {
        this.name = name;
        return this;
    }

注解到方法上時(shí),屬性值將會(huì)注入到返回對(duì)象之中奔则,比如下面datasource的配置屋灌,只要在配置文件中寫好datasource相應(yīng)的屬性配置,@ConfigurationProperties就可以完成自動(dòng)注入应狱。

@Bean("masterDataSource")
    @Primary
    @ConfigurationProperties(prefix = "masterDb.dataSource")
    public DataSource getMasterDataSource() throws SQLException {
        DruidDataSource druidDataSource = new DruidDataSource();
        //masterDataSourceProperties.setPropertyForDruid(druidDataSource);
        return druidDataSource;
    }

第三種方式是通過enviroment訪問,如下通過實(shí)現(xiàn)了ApplicationContextAware接口祠丝,spring啟動(dòng)時(shí)將會(huì)調(diào)用setApplicationContext方法獲取應(yīng)用上下文疾呻,應(yīng)用上下文可以訪問項(xiàng)目的各種屬性,包括java環(huán)境變量以及屬性文件中加入的屬性等

@Component
public class LocalApplicationContext implements ApplicationContextAware{

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public static String getPropertyByName(String name){
        return applicationContext.getEnvironment().getProperty(name);
    }

    public static  <T> T getBeanByName(String beanName){
        return (T) applicationContext.getBean(beanName);
    }

    public static  <T> T getBeanByType(Class<T> type){
        return applicationContext.getBean(type);
    }
}

3-4 <strong>在代碼中引入配置文件</strong>

某些組件對(duì)spring boot的支持不夠好或者使用了自定義的一些xml標(biāo)簽写半,仍然需要通過xml文件進(jìn)行配置岸蜗,可以使用@ImportResource注解,方式如下叠蝇,注意這里還需要使用@Configuration注解璃岳,有了它spring才回去掃描這個(gè)類。這樣,jsf.xml中定義的bean都將注入到spring容器铃慷。

@Configuration
@ImportResource(locations = {"classpath:jsf.xml"})
public class AdditionalBeanConfig {
}

在代碼中也可以引入properties文件和yml文件单芜,這里需要注意的是sprint boot暫時(shí)還不支持通過注解引入yml文件,通過@PropertySources或者@PropertySource都可以引入properties文件犁柜。

@Configuration
//@PropertySources({@PropertySource(""), @PropertySource("")})
@PropertySource("classpath:/important.properties")
public class ImportantProperty {
}

如果一定要通過代碼引入yml文件可以采用如下方式洲鸠,首先定義yml文件的初始化器

/**
 * Created by admin360buyad on 2017-06-12.
 * 通過實(shí)現(xiàn)ApplicationContextInitializer來添加其他的yml文件,不過這種方式硬編碼了
 */
public class YmlApplicationContextInitializer implements 
        ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        Resource resource = applicationContext.getResource(
                "classpath:/important.yml");
        YamlPropertySourceLoader yamlPropertySourceLoader = new YamlPropertySourceLoader();
        try {
            PropertySource<?> propertySource = yamlPropertySourceLoader
                    .load("importantyml", resource, null);
            applicationContext.getEnvironment().getPropertySources()
                    .addLast(propertySource);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

接下來在應(yīng)用初始化時(shí)注冊(cè)到應(yīng)用

springApplication.addInitializers(new YmlApplicationContextInitializer());

不過以上兩種方式不推薦使用馋缅,因?yàn)橛簿幋a了扒腕。
3-5 <strong>使用@Profile決定加載時(shí)機(jī)</strong>


@Profile可以作用到任何 的@Component 或 @Configuration,使得他們只有在特定的配置文件被激活時(shí)才會(huì)被spring進(jìn)行處理萤悴。比如ProductionConfiguration類只有當(dāng)spring.profiles.active=production時(shí)才會(huì)被spring處理瘾腰。

@Configuration
@Profile("production")
public class ProductionConfiguration {
// ...
}
  1. <strong>springapplication的啟動(dòng)</strong>
    =========
    一般情況下我們按照如下的方式啟動(dòng)springapplication,啟動(dòng)前我們可以設(shè)置一些相關(guān)的屬性覆履,比如是否啟用banner蹋盆,是否設(shè)置web環(huán)境以及添加特定的初始化器
@SpringBootApplication
public class SelfDefApplication{
    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(SelfDefApplication.class);
        springApplication.setBannerMode(Banner.Mode.OFF);
        //springApplication.setWebEnvironment(false);
        //springApplication.addInitializers(new YmlApplicationContextInitializer());
        springApplication.run(args);
        //bootByBuilder(args);
    }

我們看看構(gòu)造函數(shù)的代碼葡盗,通過java doc可以明白spring可以根據(jù)我們傳入的sources來加載相關(guān)的bean垒迂。

/**
     * Create a new {@link SpringApplication} instance. The application context will load
     * beans from the specified sources (see {@link SpringApplication class-level}
     * documentation for details. The instance can be customized before calling
     * {@link #run(String...)}.
     * @param sources the bean sources
     * @see #run(Object, String[])
     * @see #SpringApplication(ResourceLoader, Object...)
     */
    public SpringApplication(Object... sources) {
        initialize(sources);
    }

第二種方式是可以通過SpringApplicationBuilder的流式API進(jìn)行創(chuàng)建蹋偏,實(shí)質(zhì)上底層都將調(diào)用SpringApplication的構(gòu)造方法

public static void bootByBuilder(String[] args){
        System.out.println("boot by builder");
        new SpringApplicationBuilder(SelfDefApplication.class)
                .bannerMode(Banner.Mode.OFF)
                .run(args);
    }

前面兩種方式都是使用內(nèi)置的tomcat啟動(dòng)猎塞,我們可以通過配置文件或者自定義EmbeddedServletContainerCustomizer來設(shè)置tomcat的參數(shù)控汉。

server:
  port: 8082
@Configuration
public class CustomServletConfig {
    @Bean
    public EmbeddedServletContainerCustomizer getServletContainer(){
        return new EmbeddedServletContainerCustomizer() {
            @Override
            public void customize(ConfigurableEmbeddedServletContainer container) {
                container.setPort(8083);
            }
        };
    }
}

如果需要本地tomcat啟動(dòng)則需要繼承SpringBootServletInitializer類跃赚,并且重寫configure方法瞄摊,將啟動(dòng)類添加到SpringApplicationBuilder的sources之中箱季。通過這種方式啟動(dòng)自定義的SpringApplication類的main方法將不會(huì)得到執(zhí)行赂鲤。在代碼中或者配置文件中設(shè)置的tomcat屬性也會(huì)被自己配置的tomcat本身屬性覆蓋噪径。

@Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        builder.sources(this.getClass()).bannerMode(Banner.Mode.OFF);
        return super.configure(builder);
    }

除此之外我們需要在pom文件中排除tomcat的starter同時(shí)引入servlet的jar包

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <!--去掉內(nèi)置tomcat-->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>

如果想要在應(yīng)用啟動(dòng)后做一些事情有三種方法,第一種是往bean的構(gòu)造函數(shù)注入ApplicationArguments数初,ApplicationArguments是封裝了命令行啟動(dòng)參數(shù)的對(duì)象

@Component
public class ApplicationArgumentsBean {
    @Autowired
    public ApplicationArgumentsBean(ApplicationArguments applicationArguments){
        Set<String> names = applicationArguments.getOptionNames();
        for(String name : names){
            System.out.println(name + ":" + applicationArguments.getOptionValues(name));
        }
    }
}

第二種方式是實(shí)現(xiàn)ApplicationRunner接口

@Component
@Order(1)
public class ApplicationRunnerImple implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        Set<String> names = args.getOptionNames();
        for(String name : names){
            System.out.println(name + ":" + args.getOptionValues(name));
        }
    }
}

第三種方式是實(shí)現(xiàn)CommandLineRunner接口找爱,@Order會(huì)決定加載順序,與ApplicationRunner 接口不同的是泡孩,CommandLineRunner的run方法參數(shù)是原始的命令行參數(shù)字符串

@Component
@Order(2)
public class CommandLineRunnerImpl implements CommandLineRunner{
    @Override
    public void run(String... args) throws Exception {
        System.out.println("application has booted, the args is ");
        for(String arg : args){
            System.out.println(arg);
        }
    }
}
  1. <strong>使用Log4j2</strong>
    =========
    springboot默認(rèn)使用logback作為日志系統(tǒng)车摄,如果想要使用log4j2需要從starter中exclude掉logging部分,同時(shí)引入Log4j2的starter
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <!--去掉boot自帶的日志系統(tǒng)使用Log4j-->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
                <!--去掉內(nèi)置tomcat-->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
</dependency>
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

去掉Logging的starter過后也去掉了springboot本身需要的日志jar包仑鸥,需要在pom中引入

<!--boot默認(rèn)的日志系統(tǒng)是這個(gè)吮播,去掉log的starter后需要重新引入-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

關(guān)于Log4j2的配置文件可以使用xml也可以使用yml,使用yml的時(shí)候需要額外的添加一個(gè)jar包依賴眼俊,這樣springboot才能解析yml中的配置

<!--解析log4j2.yml-->
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-yaml</artifactId>
            <version>2.8.8</version>
        </dependency>

一個(gè)log4j2的簡單配置如下:

Configuration:
  status: info

  appenders:
    Console:
      name: STDOUT
      PatternLayout:
        Pattern: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"

  Loggers:
    Root:
      level: info
      AppenderRef:
        ref: STDOUT

如果我們想看springboot使用了哪些默認(rèn)配置意狠,將日志級(jí)別該為debug就可看到,這里給出一部分日志內(nèi)容:

Positive matches:
-----------------

   DataSourceAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

   DataSourceAutoConfiguration#dataSourceInitializer matched:
      - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer; SearchStrategy: all) did not find any beans (OnBeanCondition)

   DataSourceConfiguration.Tomcat matched:
      - @ConditionalOnClass found required class 'org.apache.tomcat.jdbc.pool.DataSource'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - @ConditionalOnProperty (spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource) matched (OnPropertyCondition)

   DataSourcePoolMetadataProvidersConfiguration.TomcatDataSourcePoolMetadataProviderConfiguration matched:
      - @ConditionalOnClass found required class 'org.apache.tomcat.jdbc.pool.DataSource'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

   DataSourceTransactionManagerAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'org.springframework.jdbc.core.JdbcTemplate', 'org.springframework.transaction.PlatformTransactionManager'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

   DataSourceTransactionManagerAutoConfiguration.DataSourceTransactionManagerConfiguration matched:
      - @ConditionalOnSingleCandidate (types: javax.sql.DataSource; SearchStrategy: all) found a primary bean from beans 'masterDataSource', 'clusterDataSource' (OnBeanCondition)

   DefaultValidatorConfiguration#defaultValidator matched:
      - @ConditionalOnMissingBean (types: javax.validation.Validator,org.springframework.validation.Validator; SearchStrategy: all) did not find any beans (OnBeanCondition)

   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)

   DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched:
      - @ConditionalOnClass found required class 'javax.servlet.ServletRegistration'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition)

   DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration matched:
      - @ConditionalOnClass found required class 'javax.servlet.ServletRegistration'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - DispatcherServlet Registration did not find servlet registration bean (DispatcherServletAutoConfiguration.DispatcherServletRegistrationCondition)

   DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration#dispatcherServletRegistration matched:
      - @ConditionalOnBean (names: dispatcherServlet; types: org.springframework.web.servlet.DispatcherServlet; SearchStrategy: all) found beans 'dispatcherServlet', 'dispatcherServlet' (OnBeanCondition)

   EmbeddedServletContainerAutoConfiguration matched:
      - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)

   EmbeddedServletContainerAutoConfiguration.EmbeddedTomcat matched:
      - @ConditionalOnClass found required classes 'javax.servlet.Servlet', 'org.apache.catalina.startup.Tomcat'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - @ConditionalOnMissingBean (types: org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; SearchStrategy: current) did not find any beans (OnBeanCondition)

   ErrorMvcAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'javax.servlet.Servlet', 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)

   ErrorMvcAutoConfiguration#basicErrorController matched:
      - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.ErrorController; SearchStrategy: current) did not find any beans (OnBeanCondition)

   ErrorMvcAutoConfiguration#errorAttributes matched:
      - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.ErrorAttributes; SearchStrategy: current) did not find any beans (OnBeanCondition)

   ErrorMvcAutoConfiguration.DefaultErrorViewResolverConfiguration#conventionErrorViewResolver matched:
      - @ConditionalOnBean (types: org.springframework.web.servlet.DispatcherServlet; SearchStrategy: all) found bean 'dispatcherServlet'; @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.DefaultErrorViewResolver; SearchStrategy: all) did not find any beans (OnBeanCondition)

   ErrorMvcAutoConfiguration.WhitelabelErrorViewConfiguration matched:
      - @ConditionalOnProperty (server.error.whitelabel.enabled) matched (OnPropertyCondition)
      - ErrorTemplate Missing did not find error template view (ErrorMvcAutoConfiguration.ErrorTemplateMissingCondition)

   ErrorMvcAutoConfiguration.WhitelabelErrorViewConfiguration#beanNameViewResolver matched:
      - @ConditionalOnMissingBean (types: org.springframework.web.servlet.view.BeanNameViewResolver; SearchStrategy: all) did not find any beans (OnBeanCondition)

   ErrorMvcAutoConfiguration.WhitelabelErrorViewConfiguration#defaultErrorView matched:
      - @ConditionalOnMissingBean (names: error; SearchStrategy: all) did not find any beans (OnBeanCondition)

   GenericCacheConfiguration matched:
      - Cache org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration automatic cache type (CacheCondition)

   GuavaCacheConfiguration matched:
      - @ConditionalOnClass found required classes 'com.google.common.cache.CacheBuilder', 'org.springframework.cache.guava.GuavaCacheManager'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - Cache org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration automatic cache type (CacheCondition)

   HttpEncodingAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.filter.CharacterEncodingFilter'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)
      - @ConditionalOnProperty (spring.http.encoding.enabled) matched (OnPropertyCondition)

   HttpEncodingAutoConfiguration#characterEncodingFilter matched:
      - @ConditionalOnMissingBean (types: org.springframework.web.filter.CharacterEncodingFilter; SearchStrategy: all) did not find any beans (OnBeanCondition)

   HttpMessageConvertersAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.http.converter.HttpMessageConverter'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

   HttpMessageConvertersAutoConfiguration.StringHttpMessageConverterConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.http.converter.StringHttpMessageConverter'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

   HttpMessageConvertersAutoConfiguration.StringHttpMessageConverterConfiguration#stringHttpMessageConverter matched:
      - @ConditionalOnMissingBean (types: org.springframework.http.converter.StringHttpMessageConverter; SearchStrategy: all) did not find any beans (OnBeanCondition)

   JacksonAutoConfiguration matched:
      - @ConditionalOnClass found required class 'com.fasterxml.jackson.databind.ObjectMapper'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

   JacksonAutoConfiguration.Jackson2ObjectMapperBuilderCustomizerConfiguration matched:
      - @ConditionalOnClass found required classes 'com.fasterxml.jackson.databind.ObjectMapper', 'org.springframework.http.converter.json.Jackson2ObjectMapperBuilder'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

   JacksonAutoConfiguration.JacksonObjectMapperBuilderConfiguration matched:
      - @ConditionalOnClass found required classes 'com.fasterxml.jackson.databind.ObjectMapper', 'org.springframework.http.converter.json.Jackson2ObjectMapperBuilder'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

   JacksonAutoConfiguration.JacksonObjectMapperBuilderConfiguration#jacksonObjectMapperBuilder matched:
      - @ConditionalOnMissingBean (types: org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; SearchStrategy: all) did not find any beans (OnBeanCondition)

   JacksonAutoConfiguration.JacksonObjectMapperConfiguration matched:
      - @ConditionalOnClass found required classes 'com.fasterxml.jackson.databind.ObjectMapper', 'org.springframework.http.converter.json.Jackson2ObjectMapperBuilder'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

   JacksonAutoConfiguration.JacksonObjectMapperConfiguration#jacksonObjectMapper matched:
      - @ConditionalOnMissingBean (types: com.fasterxml.jackson.databind.ObjectMapper; SearchStrategy: all) did not find any beans (OnBeanCondition)
  1. <strong>配置Mybatis雙數(shù)據(jù)源</strong>
    =========
    這里數(shù)據(jù)源使用druid疮胖,數(shù)據(jù)庫使用mysql环戈,引入mybatis的starter闷板,pom配置如下:
<!--數(shù)據(jù)庫-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.29</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>

為了使用雙數(shù)據(jù)源,在配置文件中我們?cè)O(shè)置兩套數(shù)據(jù)庫配置院塞,一套是master遮晚,一套是cluster,前綴分別使用masterDb.dataSource和clusterDb.dataSource迫悠,同時(shí)給出兩套不同的mybatis別名和mapper文件路徑的配置鹏漆。

masterDb:
  dataSource:
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8
    username: root
    password: 123456
    driverClassName: com.mysql.jdbc.Driver
    filters: stat
    maxActive: 20
    initialSize: 1
    maxWait: 60000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    maxOpenPreparedStatements: 20
  mapperLocations: classpath:mapper/master/*.xml
  typeAliasesPackage: com.example.domain.master

clusterDb:
  dataSource:
      url: jdbc:mysql://127.0.0.1:3306/seckill?useUnicode=true&characterEncoding=utf8
      username: root
      password: 123456
      driverClassName: com.mysql.jdbc.Driver
      filters: stat
      maxActive: 20
      initialSize: 1
      maxWait: 60000
      minIdle: 1
      timeBetweenEvictionRunsMillis: 60000
      minEvictableIdleTimeMillis: 300000
      validationQuery: select 'x'
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      poolPreparedStatements: true
      maxOpenPreparedStatements: 20
  mapperLocations: classpath:mapper/cluster/*.xml
  typeAliasesPackage: com.example.domain.cluster
  basePackage: com.example.dao.cluster

將配置引入到代碼中仍然是通過@Configuration注解的配置類,第一點(diǎn)需要注意的是這里我們需要引入@MapperScan注解创泄,給出dao層包的位置艺玲,mybatis會(huì)自動(dòng)實(shí)現(xiàn)該路徑下的所有接口,實(shí)現(xiàn)方式是根據(jù)類名與同名的mapper文件匹配鞠抑,將類里面的方法名和mapper文件內(nèi)的sql語句匹配并以此實(shí)現(xiàn)該接口饭聚,典型的約定大于配置哈!第二點(diǎn)是可以看出完成mybatis的配置需要數(shù)據(jù)源的配置搁拙,sessionfactory的配置以及事務(wù)管理器的配置秒梳。第三點(diǎn)是增加@Primary注解表明該數(shù)據(jù)源配置為最高優(yōu)先,在cluster的配置中不需要改注解箕速。第四點(diǎn)是注意使用不同的bean名稱酪碘。這樣我們已經(jīng)可以在一個(gè)應(yīng)用中使用兩套數(shù)據(jù)源配置了。

/**
 * Created by admin360buyad on 2017-06-07.
 * 多數(shù)據(jù)源配置盐茎,配置主數(shù)據(jù)源
 * spring容器可以自動(dòng)識(shí)別哪些Bean需要先裝配兴垦,下面的代碼中,spring首先會(huì)注入masterDataSource
 * 接下來才是masterSqlSessionFactory和masterDataSourceTm
 */
@Configuration
@MapperScan(basePackages = "com.example.dao.master", sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDbConfig {

    /**
     * mybatis自動(dòng)掃描該包下的domain并且根據(jù)類名的首字母小寫設(shè)置別名
     */
    @Value("masterDb.dataSource.typeAliasPackage")
    private String typeAliasPackage;

    /**
     * mybatis mapper文件的地址
     */
    @Value("masterDb.dataSource.mapperLocations")
    private String mapperLocations;

    @Bean("masterDataSource")
    @Primary
    @ConfigurationProperties(prefix = "masterDb.dataSource")
    public DataSource getMasterDataSource() throws SQLException {
        DruidDataSource druidDataSource = new DruidDataSource();
        //masterDataSourceProperties.setPropertyForDruid(druidDataSource);
        return druidDataSource;
    }

    @Bean("masterSqlSessionFactory")
    @Primary
    public SqlSessionFactory getMasterSqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setTypeAliasesPackage(typeAliasPackage);
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(mapperLocations));
        return factoryBean.getObject();
    }

    @Bean("masterDataSourceTm")
    @Primary
    public DataSourceTransactionManager getTransactionManager(@Qualifier("masterDataSource") DataSource dataSource)
            throws SQLException {
        return new DataSourceTransactionManager(dataSource);
    }
}
  1. <strong>配置velocity</strong>
    =========
    springboot的最新版本默認(rèn)已經(jīng)不支持velocity字柠,所以需要我們通過@Configuration自動(dòng)配置探越,首先引入velocity的starter
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-velocity</artifactId>
            <version>1.4.6.RELEASE</version>
</dependency>

接下來是配置類,我們需要提供VelocityViewResolver和VelocityConfigurer兩個(gè)bean窑业。這里對(duì)VelocityViewResolver使用了@Order(1)表明spring mvc會(huì)嘗試首先使用該viewResolver來返回請(qǐng)求(如果存在比1的值更低的order將具有更高優(yōu)先級(jí))钦幔,所有的viewResolver都將被ContentNegotiatingViewResolver管理,ContentNegotiatingViewResolver本身不對(duì)請(qǐng)求處理常柄,只負(fù)責(zé)管理其他viewResolver鲤氢,并且在其初始化時(shí)將獲取spring容器中所有的viewResolver

@Configuration
public class VelocityConfig {
    @Bean("velocityViewResolver")
    @Order(1)
    public ViewResolver getViewResolver(){
        VelocityViewResolver resolver = new VelocityViewResolver();
        resolver.setSuffix(".vm");
        return resolver;
    }

    @Bean("velocityConfigurer")
    public VelocityConfigurer getVelocityConfigurer(){
        VelocityConfigurer configurer = new VelocityConfigurer();
        configurer.setResourceLoaderPath("classpath:/templates/");
        configurer.setConfigLocation(new PathMatchingResourcePatternResolver()
                .getResource("classpath:/properties/velocity.properties"));
        return configurer;
    }
}
  1. <strong>spring mvc的一些配置</strong>
    =========
    spring mvc靜態(tài)資源的配置可以寫在配置文件
resources:
    static-locations: classpath:/statics/
  mvc:
    static-path-pattern: /resource/**

下載上傳的限制也可以

spring:
  http:
    multipart:
      max-file-size: 2MB

spring boot提供了很多默認(rèn)的mvc配置,如果我們想要修改都可以通過在配置溫江中自己配置西潘。

  1. <strong>springboot測試</strong>
    =========
    一個(gè)簡單的spring boot測試代碼如下所示
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class, webEnvironment = SpringBootTest.WebEnvironment.MOCK)
public class DemoApplicationTests {


    @Autowired
    private HobbyDao hobbyDao;

    @Test
    public void contextLoads() {
    }

    @Test
    public void testHobbyDao(){
        System.out.println(JSON.toJSONString(hobbyDao.selectAllHobby()));

    }

}

第一步通過@RunWith配置SpringRunner铜异,第二步則是通過@SpringBootTest注解配置測試的啟動(dòng)信息,先看第一個(gè)參數(shù)classes秸架,其java doc如下,可以看出其作用是通過參數(shù)類加載一個(gè)spring的上下文咆蒿,如果改參數(shù)未指定將在該測試類內(nèi)部尋找可加載的配置類

/**
     * The <em>annotated classes</em> to use for loading an
     * {@link org.springframework.context.ApplicationContext ApplicationContext}. Can also
     * be specified using
     * {@link ContextConfiguration#classes() @ContextConfiguration(classes=...)}. If no
     * explicit classes are defined the test will look for nested
     * {@link Configuration @Configuration} classes, before falling back to a
     * {@link SpringBootConfiguration} search.
     * @see ContextConfiguration#classes()
     * @return the annotated classes used to load the application context
     */

第二個(gè)參數(shù)是webEnvironment 东抹,java doc如下蚂子,意思是我們創(chuàng)建web環(huán)境的類型,默認(rèn)是一個(gè)mock缭黔,選項(xiàng)包括

/**
         * Creates a {@link WebApplicationContext} with a mock servlet environment or a
         * regular {@link ApplicationContext} if servlet APIs are not on the classpath.
         */
        MOCK(false),

        /**
         * Creates an {@link EmbeddedWebApplicationContext} and sets a
         * {@code server.port=0} {@link Environment} property (which usually triggers
         * listening on a random port). Often used in conjunction with a
         * {@link LocalServerPort} injected field on the test.
         */
        RANDOM_PORT(true),

        /**
         * Creates an {@link EmbeddedWebApplicationContext} without defining any
         * {@code server.port=0} {@link Environment} property.
         */
        DEFINED_PORT(true),

        /**
         * Creates an {@link ApplicationContext} and sets
         * {@link SpringApplication#setWebEnvironment(boolean)} to {@code false}.
         */
        NONE(false);

該注解還包括如下兩個(gè)參數(shù)用于自定義一些需要使用的屬性配置

/**
     * Alias for {@link #properties()}.
     * @return the properties to apply
     */
    @AliasFor("properties")
    String[] value() default {};

    /**
     * Properties in form {@literal key=value} that should be added to the Spring
     * {@link Environment} before the test runs.
     * @return the properties to add
     */
    @AliasFor("value")
    String[] properties() default {};
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末食茎,一起剝皮案震驚了整個(gè)濱河市馏谨,隨后出現(xiàn)的幾起案子别渔,更是在濱河造成了極大的恐慌,老刑警劉巖惧互,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哎媚,死亡現(xiàn)場離奇詭異,居然都是意外死亡喊儡,警方通過查閱死者的電腦和手機(jī)拨与,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來艾猜,“玉大人买喧,你說我怎么就攤上這事〈以撸” “怎么了淤毛?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長算柳。 經(jīng)常有香客問我低淡,道長,這世上最難降的妖魔是什么埠居? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任查牌,我火速辦了婚禮,結(jié)果婚禮上滥壕,老公的妹妹穿的比我還像新娘纸颜。我一直安慰自己,他們只是感情好绎橘,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布胁孙。 她就那樣靜靜地躺著,像睡著了一般称鳞。 火紅的嫁衣襯著肌膚如雪涮较。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天冈止,我揣著相機(jī)與錄音狂票,去河邊找鬼。 笑死熙暴,一個(gè)胖子當(dāng)著我的面吹牛闺属,可吹牛的內(nèi)容都是我干的慌盯。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼掂器,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼亚皂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起国瓮,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤灭必,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后乃摹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體禁漓,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡峡懈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年荚恶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雾狈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片善榛。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡悼院,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出叙甸,到底是詐尸還是另有隱情裆蒸,我是刑警寧澤哪痰,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站肋演,受9級(jí)特大地震影響爹殊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜反症,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一胞谈、第九天 我趴在偏房一處隱蔽的房頂上張望烦绳。 院中可真熱鬧,春花似錦径密、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伪很。三九已至,卻和暖如春奋单,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背览濒。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓洞就,卻偏偏與公主長得像油昂,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子倾贰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容