1. 程式人生 > >Play Framework 簡單例項分析以及基礎知識整合

Play Framework 簡單例項分析以及基礎知識整合

前言

通過分析官方使用Play建立的一個例子:To-Do List 來說明使用play建立web專案的一個基本結構和流程

首先要說明的是,整個demo是基於Play 2.1.0的,其他版本的play可能會有錯誤,所以在跟著官方demo走的時候,請保證版本一致性,我一開始是在2.0.4的play下建立整個專案的,在中間就有一些方法是不相容的,需要2.1.0的play才可以使用,所以只能下最新的play並且重新新建專案。

新建專案、繫結IDE、執行Play 這幾個步驟,我在這裡就不重複了,可以看部落格:Play Framework配置

在eclipse中開啟專案,可以看到專案的基本組成如下圖所示

在這裡要說的是,在使用eclipse或者是Intelij或者其他IDE進行編輯過程中,可能會提示有錯誤,如果不是拼寫錯誤,那麼可以先忽略,因為在執行的時候,play會幫你編譯,有錯誤的話,可以直接在瀏覽器中看到。而且IDE中指出的錯誤,很多時候都是錯的,因為IDE中並沒有play的全部資料,所以很多提示都是基於IDE現在擁有的sdk進行判斷的。所以專案中是否存在錯誤,由編譯時,play幫你查實最準的(個人覺得是這樣)。

上面看到的是整個專案的結構,現在對我來說最重要的就是app和conf這兩個資料夾。app資料夾是放java程式碼的地方,基於MVC規則。conf是配置專案的地方,路由以及資料庫連線的配置等,後面會一一說到。

概述

程式的主要入口是conf/routes檔案,這個檔案定義了程式中所有可訪問的URL。開啟檔案,可以看到play為我們生成了這樣一個路由對映關係

  1. # Home page  
  2. GET     /                           controllers.Application.index()  

這個語句告訴play,當伺服器收到一個對根目錄的GET請求時,必須呼叫controllers.Application.index()方法。

開啟app/controllers/Application.java檔案,可以看到如下:

其中Application繼承於controller,在Application中有一個共有的靜態方法index(),這個方法返回的是一個Result型別的物件。

這裡要理清 controller、Action、Result這幾個概念和這幾個概念之間的關係。詳細的說明可以看文件:Actions,Controllers and Results

簡單來說,當Play程式接收到一個請求時,一般都是交由Action進行處理,Action就是一個java的方法,處理來自客戶端的請求並返回結果給客戶端。

可以看到返回的是Result值,Result代表的是回送給客戶端的HTTP響應,就像上面的index()方法 返回的是ok,裡面包含的是一個200 OK狀態碼和一個帶有文字的響應主體。

而controller就是包含多個Action的類。

要注意的是重定向也是Result的一種哦,因為重定向也是由伺服器傳送給客戶端的一種響應報文,在主體中包含了新的URL,客戶端使用新的URL去發請求。

看回上面的程式碼,這個Action返回的是一個200 OK響應和一個HTML文件響應主體。HTML的內容是由模板提供的,Play模板會編譯成標準的java方法,使用的就是這個方法

views.html.index.render(String message). 而模板的定義 是定義在app/views/index.scala.html中,下面是預先生成的模板

第一行聲明瞭進入函式時候的引數,這裡宣告的是String型別的引數,所以在前面的index.render方法中,傳的就是一個String。

模板的內容是由HTML和Scala語句混合的,Scala語句是由@符號開始的。

—————————————————————————————————————————————————————————————————————————————

下面開始就是To-Do List的開發啦

Preparing the application

在這個程式中,外面需要幾個Action和相對應的URL,所以先從定義路由對映開始

開啟conf/routes檔案,新增以下的程式碼

可以看到,請求都是在tasks的目錄下進行的,最後一個刪除請求是帶有一個引數的。有關routing的相關知識,可以看文件:HTTP Routing

如果我們在這個時候就訪問9000埠,那麼肯定是報錯,因為我們並沒有定義Appication裡面的task等幾個方法

所以,接下來我們就要在Application.java中新增這三個新的Action

我們在三個Action中都返回了一個TODO,這是Play定義的一個Result,返回501 Not Implemented.

現在我們在瀏覽器執行 http://localhost:9000/tasks的話 就可以看到下面這樣啦

為了讓程式一執行就訪問tasks目錄,我們在index方法中返回一個重定向

Task Model

在實現上面定義的三個Action之前,我們需要先定義好一個Task是怎麼樣的,也就是定義我們的Model啦

在app目錄下,新建一個Model包,在Model包內新建一個Task類

在定義Model的同時,我們還定義了三個關於Task的靜態方法,用於對Task的操作,在後面會進行實現。

Application template

這個程式是一個single web page的程式,所有操作都在一個頁面進行,下面是修改index.scala.html模板

我們修改了模板為帶兩個引數的

一個是要展示的task連結串列,一個task表單

在模板中import了Helper._ 這個是form creation helper。關於Template和form Helper的相關內容,可以先看文件,後面我會再寫部落格分析

The tsak form

一個Form物件是內嵌在HTML form 標籤內,幷包含有相應的一些限制。

下面是為Task 類建立一個form,在Application中新增下面的程式碼

建立了一個基於Task的Form物件 taskForm 為了使用Form和Task類,我們需要import play.data.*和models.*

現在,我們可以在Task類中新增一些約束,例如,我們規定label是必須的

要新增限制 需要import play.data.validation.Constraints.*

Rendering the first page

現在,我們已經把所有需要展示的元素都搞定了,可以實現tasks action了

我們在render方法中傳入的兩個引數,正是定義template時指定的兩個引數,此時訪問9000埠,可以看到

handing the form submission

接下來就是要實現create task 了,下面是newTask的實現

至於為什麼在我們按下create按鈕的時候,會呼叫這個action呢,看回前面的template的定義就知道了

我們使用bindingFromRequest方法新建了一個from,這個form中包含了請求資料,也就是使用者輸入的task

因為網路的原因,可能會出現錯誤,所以我們需要進行判斷,如果沒有錯誤的話,我們就建立新的task並重新整理頁面。

Persist the tasks in a database

為了可以在頁面上顯示出使用者已經建立的task,我們需要將使用者已建立的task儲存在伺服器的資料庫中

首先,我們要在程式中啟用資料庫,在conf/application.conf檔案中新增下面的程式碼

[javascript] view plain copy

  1. db.default.driver=org.h2.Driver  
  2. db.default.url="jdbc:h2:mem:play"

我們就可以使用 in memory database H2.我們將使用EBean(Play的預設ORM)去訪問資料庫,

所以我們必須在這個檔案中啟用ebean,通過新增以下程式碼啟用

[javascript] view plain copy

  1. ebean.default="models.*"

通過這個,我們建立了一個Ebean server 連線到了預設的資料來源,管理models包中所有的entity

接下來,我們需要將我們的Task類轉換為相應的EBean entity,將原來Task類的程式碼中除了三個靜態方法外的修改為如下圖所示

首先import進兩個ebean相關操作的包,然後是讓Task繼承於play.db.ebean.Model,這樣Task才可以訪問Play內嵌的Ebean helper。

我們添加了persistence annotation,並建立了一個find helper去初始化查詢。

接下來就要實現剩下的三個CRUD(增刪查更)操作了。

現在,我們再重新整理一個瀏覽器,就可以看到我們新增的Task了

Delete tasks

上面只實現了建立,刪除的操作還沒做呢,因為我們的deleteTask action還沒實現

這樣就可以啦~