1. 程式人生 > >play框架05--控制層--結果返回

play框架05--控制層--結果返回

5.3結果返回

   Action方法需要對客戶端作出HTTP響應,最簡單的方法就是傳送結果物件。當物件傳送後,常規的執行流程就會中斷。以下面這段程式碼為例,最後一句System.out.println的輸出不會被執行:

public static void show(Long id) {
   
Client client = Client.findById(id);
    render
(client);
   
System.out.println("This message will never be displayed !"
);
}

      render(…)方法向模板傳送client物件,之後的其他語句將不會執行,所以在控制檯中,並不會打印出“This message will never be displayed !”。


5.3.1 返回文字內容#

      renderText(…)方法直接將文字內容寫到底層HTTP響應中:

public static void countUnreadMessages(){
   
Integer unreadMessages
=MessagesBos.countUnreadMessage();
    renderText
(unreadMessages);
}

      也可以通過Java標準的格式化語法對輸出的文字進行處理:

public static void countUnreadMessages(){
   
Integer unreadMessages=MessagesBox.countUnreadMessages();
    renderText
("There are %s unread messages"
,unreadMessages);
}


5.3.2 返回JSON字串#

      越來越多的應用使用JSON作為資料格式進行互動,Play對此進行了很好的封裝,只需要使用renderJSON(…)方法就可以輕鬆地返回JSON字串。在使用renderJSON(…)方法時,Play會自動將伺服器返回的響應的content type值設定為application/json,並且將renderJSON(...)方法中的引數以JSON格式返回。

      在使用renderJSON(...)方法時,可以輸入字串格式的引數,自行指定JSON返回的內容。

public static void countUnreadMessages() {
   
Integer unreadMessages = MessagesBox.countUnreadMessages();
    renderJSON
("{\"messages\": " + unreadMessages +"}");
}

      以上範例在使用renderJSON(...)方法時,傳入了拼接成JSON格式的字串引數。Play框架會對其進行自動設定,改變content type的值為application/json。

      當然,renderJSON(...)方法的功能並不只有這些。因為大部分的應用需求,都會要求服務端返回比較複雜的JSON格式,如果都採用字串拼接的方式組成JSON內容,就太不人性化了。renderJSON(...)的輸入引數還可以是複雜的物件,如果採用這種方式使用renderJSON(...)方法,Play在執行renderJSON(...)時,底層會先呼叫GsonBuilder將物件引數進行序列化,之後再將複雜的物件以JSON的格式返回給請求。這樣開發者就可以完全透明地使用renderJSON(...)方法,不需要做其他的任何操作了,以下程式碼範例將會展示renderJSON(...)的這個功能。

public static void getUnreadMessages() {
   
List<Message> unreadMessages = MessagesBox.unreadMessages();
    renderJSON
(unreadMessages);
}


5.3.3 返回XML字串#

      與使用renderJSON(...)方法返回JSON內容類似,如果使用者希望以XML格式對內容進行渲染,可以在Controller控制器中直接使用renderXml(…)方法。 使用renderXml(...)方法時,Play會自動將伺服器返回的響應的content type值設定為application/xml。

      在使用renderXml(...)方法時,可以輸入字串格式的引數,自行指定XML返回的內容。

public static void countUnreadMessages() {
   
Integer unreadMessages = MessagesBox.countUnreadMessages();
    renderXml
("<unreadmessages>"+unreadMessages+"</unreadmessages>");
}

      如果希望將複雜的物件以XML格式進行渲染,可以在使用renderXml(...)方法時輸入org.w3c.dom.Document格式的物件,或者直接輸入POJO物件。以POJO物件作為引數使用renderXml(...)方法時,Play會使用XStream將其進行序列化操作。同樣的,這些序列化操作都不需要由開發者去做,全部交給Play就行,開發者需要做的就是按照規範簡單地呼叫renderXml(...)方法即可。

public static void getUnreadMessages() {
   
Document unreadMessages = MessagesBox.unreadMessagesXML();
    renderXml
(unreadMessages);
}


5.3.4 返回二進位制內容#

      Play為開發者提供了renderBinary(...)方法,可以非常方便的返回二進位制資料(如儲存在伺服器裡的檔案、圖片等)給客戶端。以下程式碼範例將會展示如何使用renderBinary(...)方法進行二進位制圖片的渲染。

public static void userPhoto(long id) { 
   
final User user = User.findById(id);
   response
.setContentTypeIfNotSet(user.photo.type());
   java
.io.InputStream binaryData = user.photo.get();
   renderBinary
(binaryData);
}

      首先,開發者需要建立用於持久化的域模型User,該User模型具有play.db.jpa.Blob型別的屬性photo。play.db.jpa.Blob是經過Play封裝的特有的屬性型別,可以很方便的處理二進位制資料。之後,在Controller控制器中使用時,需要呼叫域模型的findById(...)方法載入持久化的資料,並將圖片以二進位制資料流InputStream的形式進行渲染。


5.3.5 下載附件功能#

      如果開發者希望將儲存在伺服器端的檔案,採用下載的形式渲染給客戶端使用者,需要對HTTP的header進行設定。通常的做法是通知Web瀏覽器將二進位制響應資料以附件的形式,下載至使用者的本地電腦上。在Play中完成這個功能非常簡單,只需要在使用renderBinary(...)方法時多傳入一個檔名的引數即可。這樣做會觸發renderBinary(...)的額外功能,提供檔名並設定響應頭的Content-Disposition屬性。之後二進位制檔案(包括圖片)將會以附件下載的形式,渲染給使用者。

public static void userPhoto(long id) { 
   
final User user = User.findById(id);
   response
.setContentTypeIfNotSet(user.photo.type());
   java
.io.InputStream binaryData = user.photo.get();
   renderBinary
(binaryData, user.photoFileName);
}


5.3.6 執行模板#

      如果需要響應的內容比較複雜,那麼就應該使用模板來進行處理:

public class Clients extends Controller{
   
public static void index(){
        render
();
   
}
}

      模板的名稱遵從Play的約束規則,預設的模板路徑採用控制器和Action的名稱相結合的方式來定義,比如在上述例子中,模板對應的路徑為:app/views/Clients/index.html。


5.3.7 為模板作用域新增資料#

      通常情況下模板檔案都需要資料進行顯示,可以使用renderArg()方法為模板注入資料:

public class Clients extends Controller {
 
   
public static void show(Long id) {
       
Client client = Client.findById(id);
        renderArgs
.put("client", client);
        render
();    
   
}
 
}

      在模板執行過程當中,client變數可以被使用:

<h1>Client ${client.name}</h1>


5.3.8 更簡單方式#

      這裡介紹一種更簡單的方式向模板傳遞資料。直接使用render(…)方法注入模板資料:

public static void show(Long id){
   
Client client=Client.findById(id);
    render
(client);
}

      以該方式進行資料傳遞,模板中可訪問的變數與Java本地變數的名稱(也就是render()方法中的引數名)一致。當然也可以同時傳遞多個引數:

public static void show(Long id){
   
Client client=Client.findById(id);
    render
(id,client);
}


注意:

render()方法只允許傳遞本地變數。


5.3.9 指定其他模板進行渲染#

      如果讀者不希望使用預設的模板進行渲染,那麼可以在renderTemplate(…)方法的第一個引數中指定其他自定義的模板路徑,例如:

public static void show(Long id) {
   
Client client = Client.findById(id);
    renderTemplate
("Clients/showClient.html", id, client);    
}


5.3.10 重定向URL#

      redirect(…)方法產生HTTP重定向響應,可以將請求轉發到其他URL:

public static void index(){
    redirect
("http://www.oopsplay.org");
}


5.3.11 自定義Web編碼#

      Play推薦開發者使用UTF-8作為應用開發的編碼格式,如果不進行任何設定,Play框架預設使用的也就是UTF-8格式。但是具體情況並不總是這麼理想,有些特殊的需求可能要求某些響應(response)的格式為ISO-8859-1,或者要求整個應用都必須保持ISO-8859-1編碼。

為當前響應設定編碼格式

      如果需要改變某一個響應(response)的編碼格式,可以直接在Controller控制器中進行修改,具體做法如下所示:

response.encoding = "ISO-8859-1";
      當開發表單提交功能時,如果開發者希望某一表單提交的內容採用非框架預設使用的編碼(即Play框架採用預設的編碼格式UTF-8,而該form表單提交的內容希望採用ISO-8859-1編碼格式),Play的做法有一些特殊。在書寫form表單的HTML程式碼時,需要對採用何種編碼格式進行兩次標識。首先需要在<form>標籤中新增accept-charset屬性(如:accept-charset="ISO-8859-1"),accept-charset屬性會通知瀏覽器當form表單提交的時候,採用何種編碼格式;其次,需要在form表單中新增hidden隱藏域,name屬性規定為“_charset_”,value屬性為具體需要的編碼格式,這樣做的目的是當form提交的時候,可以通知服務端的Play採用何種編碼方式,具體範例如下:
<form action="@{application.index}" method="POST" accept-charset="ISO-8859-1">
   
<input type="hidden" name="_charset_" value="ISO-8859-1">
</form>

定義全域性編碼格式

      通常情況下,整個應用應該保持統一的編碼格式。如果開發者