Spring Boot專案中定製PropertyEditors方法
在Spring Boot: 定製HTTP訊息轉換器一文中我們學習瞭如何配置訊息轉換器用於HTTP請求和響應資料,實際上,在一次請求的完成過程中還發生了其他的轉換,我們這次關注將引數轉換成多種型別的物件,如:字串轉換成Date物件或字串轉換成Integer物件。
在編寫控制器中的action方法時,Spring允許我們使用具體的資料型別定義函式簽名,這是通過PropertyEditor實現的。PropertyEditor本來是JDK提供的API,用於將文字值轉換成給定的型別,結果Spring的開發人員發現它恰好滿足Spring的需求——將URL引數轉換成函式的引數型別。
針對常用的型別(Boolean、Currency和Class),Spring MVC已經提供了很多PropertyEditor實現。假設我們需要建立一個Isbn類並用它作為函式中的引數。
實戰
考慮到PropertyEditor屬於工具範疇,選擇在專案根目錄下增加一個包——utils。在這個包下定義Isbn類和IsbnEditor類,各自程式碼如下:
Isbn類:
package com.test.bookpub.utils; public class Isbn { private String isbn; public Isbn(String isbn) { this.isbn = isbn; } public String getIsbn() { return isbn; } }
IsbnEditor類,繼承PropertyEditorSupport類,setAsText完成字串到具體物件型別的轉換,getAsText完成具體物件型別到字串的轉換。
package com.test.bookpub.utils; import org.springframework.util.StringUtils; import java.beans.PropertyEditorSupport; public class IsbnEditor extends PropertyEditorSupport { @Override public void setAsText(String text) throws IllegalArgumentException { if (StringUtils.hasText(text)) { setValue(new Isbn(text.trim())); } else { setValue(null); } } @Override public String getAsText() { Isbn isbn = (Isbn) getValue(); if (isbn != null) { return isbn.getIsbn(); } else { return ""; } } }
在BookController中增加initBinder函式,通過@InitBinder註解修飾,則可以針對每個web請求建立一個editor例項。
@InitBinderpublic void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Isbn.class,new IsbnEditor()); }
修改BookController中對應的函式
@RequestMapping(value = "/{isbn}",method = RequestMethod.GET) public Map<String,Object> getBook(@PathVariable Isbn isbn) { Book book = bookRepository.findBookByIsbn(isbn.getIsbn()); Map<String,Object> response = new LinkedHashMap<>(); response.put("message","get book with isbn(" + isbn.getIsbn() +")"); response.put("book",book); return response; }
執行程式,通過Httpie訪問http localhost:8080/books/9781-1234-1111,可以得到正常結果,跟之前用String表示isbn時沒什麼不同,說明我們編寫的IsbnEditor已經起作用了。
分析
Spring提供了很多預設的editor,我們也可以通過繼承PropertyEditorSupport實現自己定製化的editor。
由於ProperteyEditor是非執行緒安全的。通過@InitBinder註解修飾的initBinder函式,會為每個web請求初始化一個editor例項,並通過WebDataBinder物件註冊。