play框架使用起來(7)
date.format=yyyy-MM-dd
在application.conf檔案中設定預設的日期格式之後,就可以通過${date.format()}方法對模板中的日期進行格式化操作了。
日曆型別
日曆型別和日期型別非常相像,當然Play會根據本地化選擇預設的日曆型別。讀者也可以通過@Bind註解來使用自定義的日曆型別。
檔案型別
在Play中處理檔案上傳是件非常容易的事情,首先通過multipart/form-data編碼的請求將檔案傳送到伺服器,然後使用java.io.File型別提取檔案物件:
publicstaticvoid 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