譯文:https://blog.csdn.net/dnc8371/article/details/106810876/
譯文作者:dnc8371
來源:CSDN
原文:https://www.javacodegeeks.com/2018/10/how-bind-requestparam-object-spring.html
您是否在請求映射方法中用@RequestParam註釋了多個參數,並認爲它不可讀?
當請求中需要一個或兩個輸入參數時,註釋看起來非常簡單,但是當列表變長時,您可能會感到不知所措。
您不能在對象內部使用@RequestParam批註,但這並不意味着您沒有其他解決方案。 在本文中,我將向您展示如何用object替換多個@RequestParams 。
1. @RequestParams的列表太長
無論是控制器還是其他類,我都相信您同意很難讀取一長串方法參數 。 另外,如果參數類型相同,則更容易出錯。
諸如Checkstyle之類的靜態代碼分析工具可以檢測方法中的大量輸入,因爲它被廣泛認爲是一種不好的做法。
通常,將一組參數一起傳遞到應用程序的不同層。 這樣的組通常可以形成一個對象 ,您要做的就是提取它並給它起一個適當的名稱 。
讓我們看一下用於搜索某些產品的示例GET端點:
@RestController @RequestMapping("/products") class ProductController { //... @GetMapping List<Product> searchProducts(@RequestParam String query, @RequestParam(required = false, defaultValue = "0") int offset, @RequestParam(required = false, defaultValue = "10") int limit) { return productRepository.search(query, offset, limit); } }
三個參數不是一個令人關注的數字,但它可以輕鬆增長。 例如,搜索通常包括排序順序或一些其他過濾器。 在這種情況下,它們都被傳遞到數據訪問層,因此它們似乎是參數對象提取的理想選擇。
2. 將@RequestParam綁定到POJO
根本不用註解@RequestParams,如下,直接把POJO作爲輸入即可。
@GetMapping List<Product> searchProducts(ProductCriteria productCriteria) { return productRepository.search(productCriteria); }
POJO不需要任何其他註釋。 它應具有與將與HTTP請求綁定的請求參數匹配的字段列表,標準的getter / setter和無參數的構造函數。
class ProductCriteria { private String query; private int offset; private int limit; ProductCriteria() { } public String getQuery() { return query; } public void setQuery(String query) { this.query = query; } // other getters/setters }
驗證POJO內部的請求參數
好的,但是我們不僅僅使用@RequestParam註釋來綁定HTTP參數。 註釋的另一個有用功能是可以根據需要標記給定參數。 如果請求中缺少參數,我們的端點可以拒絕它。
爲了使用 POJO達到相同的效果(甚至更多!),我們可以使用bean驗證 。 Java帶有許多內置約束,但是如果需要,您總是創建一個自定義驗證 。
讓我們回到POJO並向字段添加一些驗證規則。 如果只想模仿 @RequestParam(required = false) 的行爲,則只需在必填字段上使用 @NotNull 批註 。
在許多情況下,使用@NotBlack代替@NotNull更有意義,因爲它還涵蓋了不需要的空字符串問題(長度爲零的字符串)。
final class ProductCriteria { @NotBlank private String query; @Min(0) private int offset; @Min(1) private int limi; // ... }
請注意:
添加字段的驗證註釋不足以使其起作用。
您還需要在控制器的方法中使用@Valid批註標記POJO參數。 這樣,您通知Spring它應該在綁定步驟上執行驗證。
@GetMapping List<Product> searchProducts(@Valid ProductCriteria productCriteria) { // ... }
POJO內部的默認請求參數值
@RequestParam批註的另一個有用的功能是能夠在HTTP請求中未提供參數時定義默認值。
當我們擁有POJO時,不需要特殊的魔術。 您只需將默認值直接分配給字段。 當請求中缺少參數時,沒有任何內容將覆蓋預定義的值。
private int offset = 0; private int limit = 10;
3. 多個對象
您沒有被迫將所有HTTP參數放在單個對象中。 您可以在多個POJO中對參數進行分組。
爲了說明這一點,讓我們向端點添加排序條件。 首先,我們需要一個單獨的對象。 就像之前一樣,它具有一些驗證約束。
final class SortCriteria { @NotNull private SortOrder order; @NotBlank private String sortAttribute; // constructor, getters/setters }
在控制器中,只需將其添加爲單獨的輸入參數即可。 請注意,@ Valid批註在每個應驗證的參數上都是必需的。
@GetMapping List<Product> searchProducts(@Valid ProductCriteria productCriteria, @Valid SortCriteria sortCriteria) { // ... }
4. 嵌套對象
作爲多個輸入請求對象的替代,我們也可以使用組合。 參數綁定也適用於嵌套對象。
在下面,您可以找到一個示例,其中先前引入的排序條件已移至產品條件POJO。
要驗證所有嵌套屬性,應將@Valid批註添加到該字段。 請注意,如果該字段爲null,Spring將不會驗證其屬性。 如果所有嵌套屬性都是可選的,那可能是理想的解決方案。 如果不是,只需將@NotNull批註放在該嵌套對象字段上。
final class ProductCriteria { @NotNull @Valid private SortCriteria sort; // ... }
HTTP參數必須使用點符號匹配字段名稱。 在我們的情況下,它們應如下所示:
sort.order=ASC&sort.attribute=name
5. 不變的DTO
如今,您可以看到一種趨勢,它傾向於使用不固定對象,而使用二傳手來取代傳統的POJO。
不可變的對象有很多好處(還有缺點……但是……)。 我認爲,最大的一項是維護簡單 。
您是否曾經在應用程序的數十個層中進行過跟蹤,以瞭解哪些條件導致了對象的特定狀態? 這個或那個字段在哪裏改變了? 爲什麼要更新? setter方法的名稱什麼也沒解釋。 二傳手沒有任何意義。
考慮到創建Spring框架的事實,Spring強烈依賴POJO規範就不會讓人感到驚訝。 然而,時代變了,舊的模式變成了反模式。
沒有簡單的方法可以使用參數化的構造函數將HTTP參數神奇地綁定到POJO。 非參數構造函數是不可避免的。 但是,我們可以將該構造函數設爲私有 (但遺憾的是不能在嵌套對象中使用)並刪除所有的setter。 從公衆的角度來看,該對象將變得不可變。
默認情況下,Spring需要使用setter方法將HTTP參數綁定到字段。 幸運的是,可以重新配置綁定程序並使用直接字段訪問(通過反射)。
爲了爲整個應用程序全局配置數據綁定器,您可以創建一個控制器建議組件。 您可以在以@InitBinder批註註釋的方法內部更改綁定程序配置,該方法接受綁定程序作爲輸入。
@ControllerAdvice class BindingControllerAdvice { @InitBinder public void initBinder(WebDataBinder binder) { binder.initDirectFieldAccess(); } }
創建該小類後,我們可以返回到POJO並從該類中刪除所有setter方法,以使其變爲只讀狀態以供公衆使用。
final class ProductCriteria { @NotBlank private String query; @Min(0) private int offset = 0; @Min(1) private int limit = 10; private ProductCriteria() { } public String getQuery() { return query; } public int getOffset() { return offset; } public int getLimit() { return limit; } }
重新啓動您的應用程序,並使用HTTP請求的參數。 它應該像以前一樣工作。
6. 結論
在本文中,您可以看到使用@RequestParam綁定在Spring MVC控制器中的HTTP請求參數可以輕鬆地替換爲對多個屬性進行分組的參數對象,僅不過是簡單的POJO或可選的不可變DTO。
您可以在GitHub存儲庫中找到描述的樣本 。 我希望所介紹的案例是不言自明的,但是如果有任何疑問或您想花兩分錢,我強烈建議您將您的評論留在帖子下方。
翻譯自: https://www.javacodegeeks.com/2018/10/how-bind-requestparam-object-spring.html