2014年8月16日 星期六

Spring 教學(1) - 從 Spring Boot 開始

這個系列的文章會陸續介紹 Spring Framework 的一些使用方式,並分享平常使用 Spring Framework 的一些經驗。

關於 Spring Framework

先簡單地從Spring Framework的起源開始說起。Spring Framework 是一個應用程式開發框架, 由Rod Johnson於2002年建立,起初建立的目的是要降低企業級應用程式開發的複雜度,作為替代EJB開發框架的另一種選擇。

發展到現在,Spring Framework已經成為一個相當龐大,提供一系列的模組及套件,來協助開發企業級應用。其中,又以依賴注入(DI, Depecdency Injection) 以及 AOP (Aspect Oriented Programming) 可以說是其核心的模組。

想當初還在就讀二技的時候,約莫是2007年左右,尚未真正地開發過任何的企業應用。因緣際會地到一家軟體公司擔任實習工程師,這才接觸到一個大型專案的開發方式。而在實習的期間,第一個要跨過去的龐大門檻就是所謂的SSH框架(Spring Framework、Struts、Hibernate),當初是花了好大一番功夫,才勉強了解 Spring Framework 皮毛,一直到最近幾年在工作上使用,才算真正地清楚 Spring Framework 背後的運作方式。

也因為對初學者而言,Spring Framework不易了解,因此有了 Spring Boot 專案的誕生。Spring Boot 提供了一系列的 starter 專案,讓使用者可以無腦地很簡單地直接套用,不需自己一步步尋找所有需要用到的套件,或建構複雜的POM (Project Object Model)文件,就能建立具備標準企業級應用能力的Java專案。

在此先以 Spring Boot 建立一個Web專案作為範例,本部落格範例專案皆會以 Gradle 作為建構的工具,若較不清楚Gradle的朋友,可以改以Maven作為建構工具,或可以參考Gradle的教學,來了解Gradle的使用方式。

建立Spring Boot Web專案

欲建立 Spring Boot Web 專案,只需要於 build.gradle 中加入一項 dependency (spring-boot-starter-web)。

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:1.1.5.RELEASE")
}

當建置專案時,gradle即會將所有spring-boot-starter-web相依的套件庫抓下來,讓我們從eclipse上來檢視有多少套件被參考:

spring-boot-starter-web dependencies

您沒看錯!有這麼多的套件被參考,除了Spring Framework的核心套件外,尚包括了jackson、logging(以slf4j作為façade)、embeded Tomcat等套件。

接下來只需撰寫簡單的主程式:

//這邊使用 Java Class 作為設定,而非XML
@Configuration
//啟用 Spring Boot 自動配置,將自動判斷專案使用到的套件,建立相關的設定。
@EnableAutoConfiguration
//自動掃描 Spring Bean 元件
@ComponentScan( basePackages = {"peace.application", "peace.controller"} )
public class WebApplication {
    public static void main(String args[]){
        //執行SpringApplication
        SpringApplication.run(WebApplication.class, args);
    }
}

以及一支 HelloController:

package peace.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

//此類別為Spring Controller元件
@Controller
public class HelloController {

    //透過 @RequestMapping 指定從/hello會被對應到此hello()方法
    @RequestMapping("/hello")
    //透過 @ResponseBody 告知Spring,此函數的回傳值是HTTP Response的本文
    public @ResponseBody String hello(){
        return "Hello World!";
    }
}

撰寫完上述兩支類別後,我們可以直接執行Java Application,執行後可以從console看到印出的訊息,包括Spring Boot的版本以及embeded Tomcat啟動的位置(localhot:8080)。
Spring Boot Console

打開瀏覽器,輸入http://localhost:8080/hello 可以看到「Hello World!」,就完成了最基本的Hello World範例。

Hello World

讓我們略作修正,於HelloController增加一個方法,讓使用者可以指定其想要Hello的對象。

//加入{}對URL進行參數化
@RequestMapping("/hello/{name}")
//加入 @PathVariable 讓Spring自動將對應的URL參數轉換為此方法的參數
public @ResponseBody String hello(@PathVariable("name") String name){
    return "Hello " + name;
}

這時候,我們的程式對使用者提供了兩個介面,包括不指定對象的/hello,會印出Hello World!,以及可以指定對象的/hello/{name},例如於瀏覽器輸入http://localhost:8080/hello/Peace 的結果:
Hello Peace

Spring Framework 做了些什麼事?

  1. 我們透過 @RequestMapping簡化傳統 J2EE 程式要在 web.xml 設定 URL pattern 對應到 Servlet。之所以能夠做到,是因為 Spring Boot 自動註冊了一支DispatcherServlet,來攔截所有的 HTTP Request,並根據開發者在 @RequestMapping 的設定,將使用者的 HTTP Request 轉給對應的方法進行處理,而當使用者要求的URL無法被對應到正確的controller時,則會被轉到/error,顯示錯誤訊息。
  2. 我們透過了 @ResponseBody 告訴 Spring Framework「此方法的回傳值就是網頁的回傳值」。我們簡化了直接使用 HttpServletRespnse 物件來輸出HTML,Spring Framework 直接幫我們將回傳值序列化為 HTTP Response Body。
  3. 我們在 @RequestMapping 加入{}將網址格式化為參數,當Spring Framework偵測到/hello/xxx,而非/hello時,會呼叫第二個方法。而透過 @PathVariable 的搭配,讓Spring Framework 自動地將URL上的參數反序列化為Java物件。
  4. 透過上述兩個簡單的範例,我們可以發現,Spring Framework**簡化**了相當多的開發細節,開發者不需要處理HTTP的序列化/反序列化,讓開發者可以更專心地開發該方法本身的內涵。

以上範例程式碼可至這裏下載

Share:

3 則留言:

  1. 感謝您的分享,您能否寫些 結合 JPA 的做法呢? 例如 EclipseLink等。

    回覆刪除
  2. 感謝支持,很久沒有更新囉!若之後有時間會再進一步介紹Spring MVC 與 Spring Data、JPA的使用方式。

    回覆刪除