2015-09-09
Tags: 程式語言 , java , gradle , spring
這篇內容寫的是 spring boot 1.2.5 官方文件 重點摘要,不做 spring boot 基礎教學。要看懂這些內容有下列前題假設
如果你完全不懂 spring boot,建議看一下 Bootify your spring application (投影片)(錄影),看完後會對 spring boot 有基本認知,有助於日後快速上手。
我針對官方文件寫了個 spring-boot-teach 教學程式 放在 github 上,請把它抓回來看看程式怎麼寫、怎麼運作。此外,這節出現的範列在內容上有前後關係,所以這節內容不要跳著看,不然會發生看完後卻看不懂在講什麼的鳥事
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="hello" class="cloudtu.bean.Hello"/>
</beans>
這個 spring xml 設定檔會在 java config 時被匯入
server.port=8080
# enable Tomcat's HTTP response compression
server.tomcat.compression=on
# set actuator HTTP port
management.port=8081
# 只許可經由內網網址連入 actuator,可避免監控資料外流
management.address=127.0.0.1
welcome.first-message=java run anywhere
welcome.secondMessage=spring boot is easy to use
appVersion=1.0.0
db.prd.name=prd123
db.dev.name=dev456
# 設定要啟用哪些 profile
spring.profiles.active=dev
application.properties
是 spring boot 預設的外部設定檔。因為我針對 actuator 功能設定了 management.port=8081
、management.address=127.0.0.1
,所以只能用 http://127.0.0.1:8081/${actuator_endpoint}
這類網址才可以取得 actuator 提供的資訊
author.name=cloudtu
author.department=RD team
除了 application.properties
之外自訂的設定檔,之後會提供給 author bean 使用
package cloudtu;
...etc
import cloudtu.bean.Author;
import cloudtu.bean.DbName;
// @SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan
@SpringBootApplication
// 匯入 XML 格式的 spring 設定檔
@ImportResource("classpath:application-context.xml")
// 設定 property file 設定檔的來源位置
@PropertySource("classpath:author.properties")
public class Application {
...etc
// author.properties 裡的 author.* 設定會自動綁定到 authorName, authorDept 變數
@Value("${author.name}") private String authorName;
@Value("${author.department}") private String authorDept;
@Bean
public Author author(){
Author author = new Author();
// 手工指定 author bean 裡的各項 setter 設定
author.setName(authorName);
author.setDepartment(authorDept);
return author;
}
@Bean
// application.properties 裡的 db.prd.* 設定會自動綁定到 prdDbName bean
@ConfigurationProperties(prefix="db.prd")
@Profile("prd")
public DbName prdDbName(){
return new DbName();
}
@Bean
// application.properties 裡的 db.dev.* 設定會自動綁定到 devDbName bean
@ConfigurationProperties(prefix="db.dev")
@Profile("dev")
public DbName devDbName(){
return new DbName();
}
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(Application.class, args);
...etc
}
}
程式碼關鍵處都加了註解,所以看完後你應該知道裡面各個 annotation 用法,不過有儿個地方再補充說明一下。
1. @ConfigurationProperties
可以把 *.property 設定檔的設定值經由各個 bean 的 setter 進行自動綁定動作
2. 在 application.properties
裡設定了 spring.profiles.active=dev
,所以程式裡有 @Profile("dev")
宣告的 devDbName bean 在執行時會產生,但是有 @Profile("prd")
宣告的 prdDbName bean 在執行時不會產生
package cloudtu.bean;
...etc
@Component
// application.properties 裡的 welcome.* 設定會自動綁定到 welcome bean
@ConfigurationProperties(prefix="welcome")
public class Welcome {
private String firstMessage;
private String secondMessage;
// application.properties 裡的 welcome.first-message 設定綁定到 firstMessage instance variable
public void setFirstMessage(String firstMessage) {
this.firstMessage = firstMessage;
}
// application.properties 裡的 welcome.secondMessage 設定綁定到 secondMessage instance variable
public void setSecondMessage(String secondMessage) {
this.secondMessage = secondMessage;
}
...etc
}
這個範例也是在介紹 @ConfigurationProperties
用法,不過你會發現設定檔裡的名稱格式不一致, welcome.first-message
用 -
當變數名稱裡的分隔符號,另一個 welcome.secondMessage
則是用 lower camel case 命名方式。這兩種設定方式 spirng boot 都可以接受
package cloudtu.bean;
...etc
@Component
public class AppVersion {
// application.properties 裡的 appVersion 設定會自動綁定到 appVersion 變數
@Value("${appVersion}") String appVersion;
...etc
}
application.properties
裡的設定可以用 @Value("${appVersion}")
這類的宣告方式直接綁定到 bean 裡面
package cloudtu.web;
...etc
@Configuration
public class Filters{
...etc
// spring boot 預設的 url mapping 是 "/*",所以任何 request 都會經過 firstFilter bean
@Component
private static class FirstFilter implements Filter{
...etc
}
private static class SecondFilter implements Filter{
...etc
}
@Bean
public FilterRegistrationBean secondFilter(){
FilterRegistrationBean registration = new FilterRegistrationBean(new SecondFilter());
// 改寫掉預設的 url mapping,只有 "/hello" 的 request 會經過 secondFilter bean
registration.addUrlPatterns("/hello");
return registration;
}
}
Filter
可以直接加 @Component
讓它變成 spring 裡的 bean,firstFilter bean 就是這樣宣告。但是這樣宣告 filter 會讓它的 url mapping 固定都是 /*
FilterRegistrationBean
把 Filter
給包起來,secondFilter bean 就是在講自訂 url mapping 的寫法application.properties
常用參數名稱與用途說明官方在 github 有放 spring boot 官方範列程式,搞不懂某些功能怎麼用時可以去那邊找找有沒有解答
官方文件裡較重要相關章節條列如下
官方文件裡較重要相關章節條列如下
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE")
}
}
// 引用 spring boot plugin
apply plugin: "spring-boot"
...etc
configurations {
providedRuntime
// spring boot 預設使用 logback 但是我要用 log4j,所以必需把 spring-boot-starter-logging 排除掉
compile.exclude module: "spring-boot-starter-logging"
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
// spring-boot-starter-actuator 提供 "監控 app 運作狀況" 功能
compile("org.springframework.boot:spring-boot-starter-actuator")
// 改用 log4j 不用預設的 logback
compile("org.springframework.boot:spring-boot-starter-log4j")
...etc
}
範例解說如下
1. 引用了 spring boot plugin 之後就可以利用它提供的各項專屬 task (e.g. bootRun, bootRepackage) 進行開發
2. spring boot 預設的 log 是 logback,我把它換成了 log4j。因為所有 spring-boot-starter-* 的 pom 都相依於 spring-boot-starter-logging,spring-boot-starter-logging 又相依於 logback,所以要加上 compile.exclude module: "spring-boot-starter-logging"
把所有 pom 裡的 spring-boot-starter-logging 相依都排除掉,不然程式裡的 log 會出現部份相依 logback 部份相依 log4j 的問題
gradle bootRun
gradle bootRepackage
官方文件有列出常見問題與解答,下列儿項是我目前比較會遇到的項目