Google Code Prettify

2018年3月23日 星期五

spring boot RESTful 程式的單元測試

用 spring boot 寫 RESTful service,如果要單元測試很簡單,如下:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class LibraryControllerTest {
 
    @LocalServerPort
    private int port;

    @Test
    public void test() {
        RestTemplate rest = new RestTemplate();
  
        List model = rest.getForObject("http://localhost:" + port + "/library/book", List.class);
        assertNotNull(model);  
    }
}
只要加上紅色的部份,執行單元測試不需要先啟動 ap server,直接執行,spring boot 會自動執行 embedded tomcat 並且動態的找到一個可以用的 port 進行測試。但是 … 如果只是這樣寫,很可能測試時會出現 403 Forbidden 的錯誤,這是因為 spring boot 自動加上的 web security,所以,要改變一下設定,如下,我新增了一個 SecurityConfig 的類別 …
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter { 
    @Override 
    protected void configure(HttpSecurity http) throws Exception {   
        http.authorizeRequests().anyRequest().permitAll();
    }
}
這個類別要繼承 WebSecurityConfigurerAdapter,並 override configure(HttpSecurity http) method,在裡面改變 request 的權限設定,我這裡很偷懶的全部的 request 都允許存取,實務上當然會加上一些限制。



2018年3月18日 星期日

在 embedded tomcat 中使用 Tomcat 資料庫連線

在 spring boot 中,如果在 build.gradle 中包含了 web 套件,就會自動包裝了 embedded tomcat,那麼,如果程式要連線資料庫,要怎麼利用這個 embedded tomcat 中的 connection pool ? 很簡單,如下。
  • build.gradle
buildscript {
    ext {
        springBootVersion = '2.0.0.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse-wtp'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'war'

group = 'idv.steven.jndi'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

configurations {
    providedRuntime
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.apache.tomcat:tomcat-jdbc')
    compileOnly('org.projectlombok:lombok')
    testCompile('org.springframework.boot:spring-boot-starter-test')
 
    compile group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '2.2.1'
}
如上所示,我引入了 spring boot 2.x 版,因為我的資料庫是 maria db,所以也要把相關的 JDBC 驅動程式引入,同時,因為這裡要使用 tomcat connection pool,要引入 tomcat jdbc。spring boot 在後續程式中,會根據資料庫的 url 判斷是什麼資料庫,而載入相關驅動程式。
  • application.properties
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
#spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://192.168.0.103:3306/demo
spring.datasource.username=steven
spring.datasource.password=P@ssw0rd

spring.datasource.tomcat.max-active=23
spring.datasource.tomcat.max-idle=7
spring.datasource.tomcat.min-idle=2
spring.datasource.tomcat.max-wait=9997
spring.datasource.type 指定要使用的 connection pool,spring.datasource.tomcat.*,是設定 connection pool 的一些參數,我故意設定一些比較奇怪的值,是為了觀察是否真的有使用到 tomcat connection pool。spring.datasource.driver-class-name 不需設定,spring boot 從 url 中可以自行判斷。在 application.properties 設定完,不需要寫任何程式,spring boot 就幫我們建立好 tomcat connection pool。
  • 觀察
我在 eclipse 使用 debug mode 執行,觀察 EntityManager 的值,於「em > h > target Factory > h > entityManagerFactoryBean > persistenceUnitInfo > nonJtaDataSource > poolProperties」裡看到如下內容,證明確實有用到 tomcat connection pool。