在Spring Boot: 定制HTTP消息轉(zhuǎn)換器一文中我們學(xué)習(xí)了如何配置消息轉(zhuǎn)換器用于HTTP請求和響應(yīng)數(shù)據(jù),實際上,在一次請求的完成過程中還發(fā)生了其他的轉(zhuǎn)換,我們這次關(guān)注將參數(shù)轉(zhuǎn)換成多種類型的對象,如:字符串轉(zhuǎn)換成Date對象或字符串轉(zhuǎn)換成Integer對象。
在編寫控制器中的action方法時,Spring允許我們使用具體的數(shù)據(jù)類型定義函數(shù)簽名,這是通過PropertyEditor實現(xiàn)的。PropertyEditor本來是JDK提供的API,用于將文本值轉(zhuǎn)換成給定的類型,結(jié)果Spring的開發(fā)人員發(fā)現(xiàn)它恰好滿足Spring的需求——將URL參數(shù)轉(zhuǎn)換成函數(shù)的參數(shù)類型。
針對常用的類型(Boolean、Currency和Class),Spring MVC已經(jīng)提供了很多PropertyEditor實現(xiàn)。假設(shè)我們需要創(chuàng)建一個Isbn類并用它作為函數(shù)中的參數(shù)。
package com.test.bookpub.utils;
public class Isbn {
private String isbn;
public Isbn(String isbn) {
this.isbn = isbn;
}
public String getIsbn() {
return isbn;
}
}
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 "";
}
}
}
@InitBinderpublic
void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Isbn.class, new IsbnEditor());
}
@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;
}
運(yùn)行程序,通過Httpie訪問http localhost:8080/books/9781-1234-1111
,可以得到正常結(jié)果,跟之前用String表示isbn時沒什么不同,說明我們編寫的IsbnEditor已經(jīng)起作用了。
Spring提供了很多默認(rèn)的editor,我們也可以通過繼承PropertyEditorSupport實現(xiàn)自己定制化的editor。
由于ProperteyEditor是非線程安全的。通過@InitBinder注解修飾的initBinder函數(shù),會為每個web請求初始化一個editor實例,并通過WebDataBinder對象注冊。