在做專案的時候,身為開發者的我們經常會有「產生動態文字內容」這樣的需求,具體來說像是產生網頁、email內容、甚至寫程式來產生程式碼等等。如果為了一時貪求快速,而把這些文字處理的動作寫在程式裡面,這麼一來整體的維護性就會大打折扣。「模版引擎」(template engine) 就是因應這樣的需求而誕生的!
Java界的模版引擎有很多套,其中比較容易上手,功能也相當完備的,當屬 FreeMarker。 Continue reading →
在做專案的時候,身為開發者的我們經常會有「產生動態文字內容」這樣的需求,具體來說像是產生網頁、email內容、甚至寫程式來產生程式碼等等。如果為了一時貪求快速,而把這些文字處理的動作寫在程式裡面,這麼一來整體的維護性就會大打折扣。「模版引擎」(template engine) 就是因應這樣的需求而誕生的!
Java界的模版引擎有很多套,其中比較容易上手,功能也相當完備的,當屬 FreeMarker。 Continue reading →
在前三篇實作我們完成了 core, desktop, web 三個專案,接下來要給大家介紹 Maven 最典型的一種應用 — 多模組專案
上一回我們完成了用戶查詢系統–視窗程式的練習,這次我們從Web版開始吧!
請先確認Eclipse 已經整合了Tomcat,如果還沒,請參考Java web app 開發第一步 – 整合Eclipse + Tomcat
Web
1 2 3 4 5 6 |
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <display-name>Archetype Created Web Application</display-name> </web-app> |
1 2 3 4 5 6 7 8 9 10 11 |
<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.appx</groupId> <artifactId>user-service-core</artifactId> <version>1.0-SNAPSHOT</version> </dependency> |
搜尋結果為 tom
以下帶大家一步一步在Eclipse環境中設定Tomcat
延續上一回的實作,現在我們將從桌面視窗程式開始!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.0.0</version> <executions> <!-- Run shade goal on package phase --> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <!-- add Main-Class to manifest file --> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.appx.userservice.desktop.App</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> |
1 2 3 4 5 |
<dependency> <groupId>com.appx</groupId> <artifactId>user-service-core</artifactId> <version>1.0-SNAPSHOT</version> </dependency> |
jar -tf user-service-desktop-1.0-SNAPSHOT.jar
jar -tf original-user-service-desktop-1.0-SNAPSHOT.jar
接下來會帶大家動手實作幾個 Maven 專案,從練習過程中我們會更進一步了解到 Maven 所帶來各種方便的特性!
我們將會建立一個簡單的用戶查詢系統,由三個專案所組成,分別是 core, desktop, web,其中 desktop, web 專案會將core 當作 dependency,如下圖所示:
前言
有些時候,我們會需要將資料(物件) 覆製一份,
方便獨立操作 ~ 卻發現結果跟想像的不一樣。
讓我們從程式碼來做個說明~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class Person { Name name; Address address; Person(Person p) { this.name = p.name; this.address = p.address; } // 其它省略… } class Address { String road; String city; String zipcode; } class Name { String firstName; String lastName; } |
1 2 |
Person mother = new Person(new Name(), new Address()); Person son = new Person(mother); //將上一個物件傳到目前物件的建構子 |
1 2 3 4 5 6 7 8 |
public class Person { private Name name; private Address address; public Person(Person otherPerson) { this.name = new Name(otherPerson.name); //產生新物件 this.address = new Address(otherPerson.address); //產生新物件 } } |
1 2 3 |
//承接上面的程式碼 Person mother = new Person(new Name(), new Address()); //有mother自己的資料 Person son = new Person(mother); //將上一個物件的資料覆製一份,會另產生一份獨立的。 |
對了~
對參考點的概念(Reference) 還不是很清楚?!
對建構子的運用 還想更進一步嗎?! 可以參考我們提供的教育訓練。
參考資料:
https://dzone.com/articles/java-copy-shallow-vs-deep-in-which-you-will-swim
對於開發者來說,Maven最強大的功能莫過於 dependency management了!
在之前文章 Maven-05-一個簡單的POM範例 我們看到POM裡定義了一組 junit 的dependency,所以在執行 mvn install 時,Maven 會先檢查本機的 repository 是否有 junit 相關的 artifact ,如果沒有就會從網路上下載,然後放到 ~/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar
這邊我們可以觀察到 Maven 自動下載的東西除了jar 檔,還包括了其他檔案像是包了原始碼的jar,還有一個很關鍵的 junit-3.8.1.pom,為什麼 Maven 還會下載 junit的POM呢?
大家可以試著想想,如果今天我們需要的不是junit 這麼單純的套件,我們需要在專案裡使用 Hibernate,從它的 POM 我們得知 Hibernate 本身也有許多 dependencies,難道我們必須在自己專案的 POM 把這些 Hibernate 的 dependency 也全部都寫出來嗎??
答案當然是:NO !!
我們只需要定義 Hibernate dependency,Maven 就會自動把它關聯的 dependency 也一併下載回來,這種機制稱為 “transitive dependencies”, 實際上的運作方式是 Maven 會去查看 dependency 的 POM,並確認是否有相關的 dependency
在junit 的 <dependency> 定義裡,有一個 <scope>test</scope>,這是另一個重要的概念 ,常用的 dependency scope 有下列幾種:
更多 dependency scope 可參考
https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope
我們之前在 Maven-04-建置專案 裡執行了 mvn install 指令,如果是初次執行的話,會發現 maven 會自動從遠端 repository 下載很多 plugin 相關的檔案,這些檔案會存放在本機個人目錄下 .m2/repository 資料夾裡。現在我們一起來了解有關 repository 更多資訊吧!
Maven 官方預設的遠端 repository 在 http://repo1.maven.org/maven2/ ,如果有需要的話,像是公司內部私有專案的需求, Maven 也支援自行架設的 repository,其中比較有名的像是:
只要修改 maven 安裝目錄下的 conf/settings.xml 就可以指向自行架設的 repository
Maven repository 儲存了大大小小專案的成品 (project artifact),其中的目錄結構完全符合我們先前介紹過的 Maven coordinates,大家可以試著從官方的 http://repo1.maven.org/maven2/ 來觀察,這邊以 hibernate-core 版本 5.1.0.Final 為例子來說明
1 2 3 |
<groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.1.0.Final</version> |
Maven 從遠端下載的 project artifacts 會存在放本機 local repository 裡 (預設是 個人目錄 .m2/repository,也可以透過 settings.xml 修改),之後當有需要在專案裡引用這些 artifacts 時,Maven 就會直接參考 local repository 而不再從網路上尋找,順帶一提,local repository 裡面的資料夾結構,也和遠端 repository 一樣
mvn install 執行之後產生的project artifact,最後就會放置在 local repository 裡,這麼做的目的是日後可以供其它專案來參照引用。在下一篇,我們將為大家介紹對開發人員來說 Maven 最最最重要的功能 — dependency 管理
雖然Java 8 已經出來好一陣子了~ (記得是 2014的三月)
但還是有不少人會詢問什麼是 Lambda,什麼是 匿名類別 Anonymous class
藉著最近專案的機會,分享一下我們對 Lambda的了解,希望能有所幫助。
預計這一系列的文章,會有
今天就先針對 Java 8 Lambda 的出現,先做個應用的說明 ~
讓我們從一個很常用的例子開始~ 「使用者在畫面上按下按鈕,然後秀出 HelloWorld」
(*這部份機制,可應用在 Java Swing/FX 以及 Android )
以Java Swing 視窗程式為例,在 Lambda出現之前,我們可能的做法有下列幾項 ~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class MyActionListener implements ActionListener { public void actionPerformed(ActionListener a) { //... } } //=========== 在另外的程式裏產生按鈕 以及 處理事件 =========== public class MyForm { public static void main(String[] args) { //略過產生視窗以及 掛上(attach) 按鈕 JButton jb = new JButton(); MyActionListener ma = new MyActionListener(); jb.addAcctionListener(ma); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class MyForm { class MyActionListener implements ActionListener { public void actionPerformed(ActionListener a) { // say Hello } } public static void main(String[] args) { //略過產生視窗以及 掛下按鈕 JButton jb = new JButton(); MyActionListener ma = new MyActionListener(); jb.addAcctionListener(ma); //... } |
1 2 3 4 5 6 7 8 9 10 11 |
public class MyForm { public static void main(String[] args) { //略過產生視窗以及 掛上(attach)按鈕 JButton jb = new JButton(); jb.addAcctionListener( new ActionListener() { public void actionPerformed(ActionListener a) { //say Hello } }); } } |
在Java 8 Lambda 出現後,我們可以用下列的寫法
5 |
jb.addAcctionListener( (a) -> System.out.println("Hello")); |
jb.addActionListener( (a)-> System.out.println(“Hello”));
沒錯,就只要寫 一行,就可以有同樣的效果~~~
剩下的,就讓Java 8 Compiler 將程式碼 編譯成跟之前 actionListener 一樣的class code !!!
是不是很方便~~~ 趕快試試看囉~~
對了~
匿名類別 (Anonymous class)還不是很清楚?! 可以參考我們提供的教育訓練。
參考資料:
https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
http://www.coreservlets.com/java-8-tutorial/#setup