Table of contents


pom.xml

    <?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.example</groupId>
        <artifactId>myproject</artifactId>
        <version>0.0.1-SNAPSHOT</version>

        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.1.0.M2</version>
        </parent>

        <!-- Additional lines to be added here... -->

    </project>

maven設定檔是透過<parent> tag繼承 spring-boot預先定義好的 parent pom,在parent的pom檔中,有許多預設的dependencies,所以,引用到 parent pom裡已預先定義好的 dependency 時,就不需再定義該 <dependency> tag下的 <version> tag。在本文章中的 <dependency> 只要是沒加 <version> tag的,都是因為 parent pom 已有預先定義好的 dependencies.

建議可以調 parent 的 pom.xml 出來看看,會比較清楚 spring boot 的 building 機制,eclipse 跟 intelliJ 都支援 link 到 parent pom 的功能。

Spring Boot Hello World:

@Controller
@EnableAutoConfiguration
public class Application {

    @RequestMapping("/")
    @ResponseBody
    String home() {
        return "Hello World!";
    }


    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);

        System.out.println("Let's inspect the beans provided by Spring Boot:");

        String[] beanNames = ctx.getBeanDefinitionNames();
        Arrays.sort(beanNames);
        // 表列出引用到的 beans
        for (String beanName : beanNames) {
            System.out.println(beanName);
        }
    }

}

比起傳統的 Spring RESTful 程式,spring boot簡單許多。

spring-boot-maven-plugin主要的功能是 build 出 war 檔或可執行的 jar 檔

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

執行 mvn spring-boot:run , 加入 --debug 參數可以dump auto config 的細節, 方便除錯 mvn spring-boot:run --debug,如果是在IDE執行成 Application,那把--debug加到program argument即可,或者是直接寫到SpringApplicationBuilder

new SpringApplicationBuilder(MyConfig.class).run(new String[]{"--debug"});

=========================
AUTO-CONFIGURATION REPORT
=========================


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

   AuditAutoConfiguration.AuditEventRepositoryConfiguration
      - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.audit.AuditEventRepository; SearchStrategy: all) found no beans (OnBeanCondition)

   EndpointAutoConfiguration#autoConfigurationAuditEndpoint
      - @ConditionalOnBean (types: org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport; SearchStrategy: all) found the following [autoConfigurationReport] @ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.AutoConfigurationReportEndpoint; SearchStrategy: current) found no beans (OnBeanCondition)

   EndpointAutoConfiguration#beansEndpoint
      - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.BeansEndpoint; SearchStrategy: all) found no beans (OnBeanCondition)

如果想要抓到Application傳進來的參數,可以implement CommandLineRunner

import org.springframework.boot.*
import org.springframework.stereotype.*

@Component
public class MyBean implements CommandLineRunner {

    public void run(String... args) {
        // Do something...
    }

}

Properties

屬性檔預設預案是在 classpath下的 application.properties或 application-{profile}.properties

屬性中可以用亂數產生器,因為使用了RandomValuePropertySource

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

在屬性檔的屬性可以透過@Value@ConfigurationProperties binding 到程式, 也可以jsr-303的 bean validation 進行驗證。

JPA

要在 spring boot 中啟用 JPA也相當簡單, 只要加入 spring-boot-starter-data-jpa 跟 database driver即可,其他的設定像 hibernate.dialect 等 spring boot 會依照使用的資料庫選擇適合的設定。

使用 hsqldb 當 database

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
        </dependency>

使用 mysql 當 database

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

如果用 in-memory database,像hsqldb,h2,derby … 當db,jpa會自動建立 entity 對應的table,如果是其他 database,則需自行建立,或者也可以透過 application.properties 設定檔來改寫預設的行為。

Testing

Unit Test

spring一向強調測試的重要性,在spring寫測試比起在其它 framework 下會愉快許多。spring boot 在測試上,在基於 spring 本身的基礎上,又加了一些方便的配置。

在繼承 parent pom之後,unit test常用的三板斧,就會被配置在 test scope了(不會被 deploy 成product),這三板斧是:

  1. Junit - 單元測試lib
  2. Hamcrest - 斷言工具 (assertion),搭配 assertThat 用的(不要再 assertEquals,請一律assertThat吧)
  3. Mockito - 目前java最流行的 mock framework

Database Test

如果要做的測試跟db有關,建議採用in-memory database,不要mock,但如果沒有採用像 jpa 這種會自動依 dialect 轉換 sql 語法的 framework時,可能就要對測試方式做調整。在資料庫的測試,我通常是採用 hsqldb + dbunit,而production的database,即依專案需求而決定,使用jpa時,單元測試時在 hsqldb,真正執行時在其他db ex: mysql, postgresql,…,都沒遇過太大的問題。

但是如果沒辦法使用jpa時(通常會換成 JdbcTemplate),而且又使用到許多特定資料庫特有的功能時,就會採用 dbunit + rollback base的測試,這一類的測試,在測試程式的撰寫上,通常需要花比較多的心力。

Web Test

web test,spring 本來就有提供 MockMvc 的 mock object,4.x 版後以的 spring mvc test 都改用 fluent api 來寫測試了。

Spring Boot Application Test

unsorted

  • 在專案中所有的 classes 都會被 @ComponentScan 掃描 ﹣》 只有base package