javascript
如何在Spring中将@RequestParam绑定到对象
您是否在請求映射方法中用@RequestParam注釋了多個參數,并認為它不可讀?
當請求中需要一個或兩個輸入參數時,注釋看起來非常簡單,但是當列表變長時,您可能會感到不知所措。
您不能在對象內部使用@RequestParam批注,但這并不意味著您沒有其他解決方案。 在本文中,我將向您展示如何用object替換多個@RequestParams 。
1. @RequestParams的列表太長
無論是控制器還是其他類,我都相信您同意很難讀取一長串方法參數 。 另外,如果參數類型相同,則更容易出錯。
諸如Checkstyle之類的靜態代碼分析工具可以檢測方法中的大量輸入,因為它被廣泛認為是一種不好的做法。
通常,將一組參數一起傳遞到應用程序的不同層。 這樣的組通常可以形成一個對象 ,您要做的就是提取它并給它起一個適當的名稱 。
讓我們看一下用于搜索某些產品的示例GET端點:
@RestController @RequestMapping("/products") class ProductController {//...@GetMappingList<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,因為他們根本不知道這是可能的。 @RequestParam的文檔沒有提到替代解決方案。
從更新控制器的方法開始,接受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 {@NotBlankprivate 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 {@NotNullprivate SortOrder order;@NotBlankprivate 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@Validprivate SortCriteria sort;// ...}HTTP參數必須使用點符號匹配字段名稱。 在我們的情況下,它們應如下所示:
sort.order=ASC&sort.attribute=name5.不變的DTO
如今,您可以看到一種趨勢,它傾向于使用不固定對象,而使用二傳手來取代傳統的POJO。
不可變的對象有很多好處(還有缺點……但是……)。 我認為,最大的一項是維護簡單 。
您是否曾經在應用程序的數十個層中進行過跟蹤,以了解哪些條件導致了對象的特定狀態? 這個或那個字段在哪里改變了? 為什么要更新? setter方法的名稱什么也沒解釋。 二傳手沒有任何意義。
考慮到創建Spring框架的事實,Spring強烈依賴POJO規范就不會讓人感到驚訝。 然而,時代變了,舊的模式變成了反模式。
沒有簡單的方法可以使用參數化的構造函數將HTTP參數神奇地綁定到POJO。 非參數構造函數是不可避免的。 但是,我們可以將該構造函數設為私有 (但遺憾的是不能在嵌套對象中使用)并刪除所有的setter。 從公眾的角度來看,該對象將變得不可變。
默認情況下,Spring需要使用setter方法將HTTP參數綁定到字段。 幸運的是,可以重新配置綁定程序并使用直接字段訪問(通過反射)。
為了為整個應用程序全局配置數據綁定器,您可以創建一個控制器建議組件。 您可以在以@InitBinder批注注釋的方法內部更改綁定程序配置,該方法接受綁定程序作為輸入。
@ControllerAdvice class BindingControllerAdvice {@InitBinderpublic void initBinder(WebDataBinder binder) {binder.initDirectFieldAccess();}}創建該小類后,我們可以返回到POJO并從該類中刪除所有setter方法,以使其變為只讀狀態以供公眾使用。
final class ProductCriteria {@NotBlankprivate 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請求的參數。 它應該像以前一樣工作。
結論
在本文中,您可以看到使用@RequestParam綁定在Spring MVC控制器中的HTTP請求參數可以輕松地替換為對多個屬性進行分組的參數對象,僅不過是簡單的POJO或可選的不可變DTO。
您可以在GitHub存儲庫中找到描述的樣本 。 我希望所介紹的案例是不言自明的,但是如果有任何疑問或您想花兩分錢,我強烈建議您將您的評論留在帖子下方。
翻譯自: https://www.javacodegeeks.com/2018/10/how-bind-requestparam-object-spring.html
總結
以上是生活随笔為你收集整理的如何在Spring中将@RequestParam绑定到对象的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何快速清理电脑垃圾如何快速清理电脑垃圾
- 下一篇: spring基于注释的配置_基于注释的S