1. 程式人生 > >play框架使用起來(7)

play框架使用起來(7)

date.format=yyyy-MM-dd

      在application.conf檔案中設定預設的日期格式之後,就可以通過${date.format()}方法對模板中的日期進行格式化操作了。

日曆型別

      日曆型別和日期型別非常相像,當然Play會根據本地化選擇預設的日曆型別。讀者也可以通過@Bind註解來使用自定義的日曆型別。


檔案型別

      在Play中處理檔案上傳是件非常容易的事情,首先通過multipart/form-data編碼的請求將檔案傳送到伺服器,然後使用java.io.File型別提取檔案物件:

public
staticvoid create(String comment,File attachment){String s3Key = S3.post(attachment);Document doc =newDocument(comment, s3Key);
    doc
.save();
    show
(doc.id);}

      新建立檔案的名稱與原始檔案一致,儲存在應用的臨時檔案下(Application_name/tmp)。在實際開發中,需要將其拷貝到安全的目錄,否則在請求結束後會丟失。

陣列和集合型別

      所有Java支援的資料型別都可以通過陣列或者集合的形式來獲取。陣列形式:

publicstaticvoid show(Long[] id){...}
      List形式:
public staic void show(List<Long> id){...}
      集合形式:
publicstaticvoid show(Set<Long> id){...}
      Play還可以處理Map<String, String>對映形式:
publicstaticvoid show(Map<String,String> client){...}
      例如下面的查詢字串會轉化為帶有兩個元素的map型別,第一個元素key值為name,value為John;第二個元素key值為phone,value為111-1111, 222-2222。:
?
user.name=John&user.phone=111-1111&user.phone=222-2222


POJO物件繫結

      Play使用同名約束規則(即HTTP引數名必須與模型類中的屬性名一致),自動繫結模型類:

publicstaticvoid create(Client client){
    client
.save();
    show
(client);}

      以下的查詢字串可以通過上例的Action建立client:

?client.name=Zenexity&client.email=[email protected].fr
      框架通過Action建立Client的例項,並將HTTP引數解析為該例項的屬性。如果出現引數無法解析或者型別不匹配的情況,會自動忽略。

      引數繫結是遞迴執行的,這意味著可以深入到關聯物件:

?client.name=Zenexity&client.address.street=64+rue+taitbout
&client.address.zip=75009&client.address.country=France

      Play的引數繫結提供陣列的支援,可以將物件id作為對映規則,更新一組模型物件。假設Client模型有一組宣告為List<Customer>的customers屬性,那麼更新該屬性需要使用如下查詢字串:

?client.customers[0].id=123&client.customers[1].id=456&client.customers[2].id=789

2 JPA物件繫結#

      通過HTTP引數還可以實現JPA物件的自動繫結。Play會識別HTTP請求中提供的引數user.id,自動與資料庫中User例項的id進行匹配。一旦匹配成功,HTTP請求中的其他User屬性引數可以直接更新到資料庫相應的User記錄中:

publicstaticvoid save(User user){
    user
.save();}

      和POJO對映類似,可以使用JPA繫結來更改物件,但需要注意的是必須為每個需要更改的物件提供id:

user.id =1&user.name=morten
&user.address.id=34&user.address.street=MyStreet

3 自定義繫結#

      繫結機制支援自定義功能,可以按照讀者的需求,自定義引數繫結的規則。


@play.data.binding.As

      @play.data.binding.As註解可以依據配置提供繫結的支援。下例使用DateBinder指定日期的資料格式:

publicstaticvoid update(@As("dd/MM/yyyy")Date updatedAt){...}

      @As註解還具有國際化支援,可以為每個本地化提供專門的註解:

publicstaticvoid update(@As(
            lang
={"fr,de","en","*"},
            value
={"dd/MM/yyyy","dd-MM-yyyy","MM-dd-yy"})Date updatedAt
   
){...}

      @As註解可以和所有支援它的繫結一起工作,包括使用者自定義的繫結。以下是使用ListBinder的例子:

publicstaticvoid update(@As(",")List<String> items){...}

      上例中的繫結使用逗號將字串分隔成List。

      @play.data.binding.NoBinding

      @play.data.binding.NoBinding註解允許對不需要繫結的屬性進行標記,以此來解決潛在的安全問題。比如:

//User為Model類publicclassUserextendsModel{@NoBinding("profile")publicboolean isAdmin;@As("dd, MM yyyy")Date birthDate;publicString name;}//editProfile為Action方法publicstaticvoid editProfile(@As("profile")User user){...}

      在上述例子中,user物件的isAdmin屬性始終不會被editProfile方法(Action)所修改,即使有惡意使用者偽造POST表單提交user.isAdmin=true資訊,也不能修改user的isAdmin許可權。


play.data.binding.TypeBinder

      @As註解還提供完全自定義繫結的功能。自定義繫結必須是TypeBinder類的實現:

publicclassMyCustomStringBinderimplementsTypeBinder<String>{publicObject bind(String name,Annotation[] anns,String value,Class clazz){return"!!"+ value +"!!";}}
      定義完成後,就可以在任何Action中使用它:
publicstaticvoid anyAction(@As(binder=MyCustomStringBinder.class)String name){...}

@play.data.binding.Global

      Play中還可以自定義全域性Global繫結。以下是為java.awt.Point類定義繫結的例子:

@GlobalpublicclassPointBinderimplementsTypeBinder<Point>{publicObject bind(String name,Annotation[] anns,String value