日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

在Spring MVC中处理域对象

發布時間:2023/12/3 javascript 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在Spring MVC中处理域对象 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近,我驚訝于一個代碼庫在其所有域實體中都具有公共默認構造函數(即零參數構造函數),并且所有字段都具有getter和setter。 當我深入研究時,我發現域實體之所以如此,主要是因為該團隊認為Web / MVC框架需要它。 我認為這是消除一些誤解的好機會。

具體來說,我們將研究以下情況:

  • 生成的ID字段沒有設置器(即,生成的ID字段具有吸氣劑但沒有設置器)
  • 沒有默認的構造函數(例如,沒有公共的零參數構造函數)
  • 具有子實體的域實體(例如,子實體未顯示為可修改列表)
  • 綁定Web請求參數

    首先,一些細節和背景。 讓我們基于特定的Web / MVC框架-Spring MVC。 使用Spring MVC時,其數據綁定按名稱綁定請求參數。 讓我們舉個例子。

    @Controller @RequestMapping("/accounts") ... class ... {...@PostMappingpublic ... save(@ModelAttribute Account account, ...) {...}... }

    給定上面的控制器映射到“ / accounts”,一個Account實例可以從哪里來?

    根據文檔 ,Spring MVC將使用以下選項獲取實例:

    • 從模型(如果已通過Model添加(例如通過同一控制器中的@ModelAttribute方法 )。
    • 通過@SessionAttributes在HTTP會話中。
    • 來自通過Converter的URI路徑變量。
    • 從默認構造函數的調用開始。
    • (僅適用于Kotlin)通過調用具有與Servlet請求參數匹配的參數的“主要構造函數”; 參數名稱是通過JavaBeans @ConstructorProperties或字節碼中運行時保留的參數名稱確定的。

    假設沒有在會話中添加Account對象,并且沒有@ModelAttribute方法 ,Spring MVC最終將使用其默認構造函數實例化一個實例,并按name綁定Web請求參數。 例如,請求包含“ id”和“ name”參數。 Spring MVC將嘗試通過分別調用“ setId”和“ setName”方法將它們綁定到“ id”和“ name” bean屬性。 這遵循JavaBean約定。

    生成ID字段的無設置方法

    讓我們從簡單的事情開始。 假設我們有一個Account域實體。 它具有由持久性存儲生成的ID字段,并且僅提供getter方法(但不提供setter方法)。

    @Entity ... class Account {@Id @GeneratedValue(...) private Long id;...public Account() { ... }public Long getId() { return id; }// but no setId() method }

    那么,我們如何讓Spring MVC將請求參數綁定到Account域實體? 我們是否必須為生成的字段和只讀字段提供公共設置方法?

    在我們HTML表單中,我們不會將“ id”作為請求參數。 我們將其放置為路徑變量。

    我們使用@ModelAttribute方法。 在請求處理方法之前調用它。 它支持與常規請求處理方法幾乎相同的參數。 在我們的例子中,我們使用它來檢索具有給定唯一標識符的Account域實體,并將其用于進一步的綁定。 我們的控制器看起來像這樣。

    @Controller @RequestMapping("/accounts") ... class ... {...@ModelAttributepublic Account populateModel(HttpMethod httpMethod,@PathVariable(required=false) Long id) {if (id != null) {return accountRepository.findById(id).orElseThrow(...);}if (httpMethod == HttpMethod.POST) {return new Account();}return null;}@PutMapping("/{id}")public ... update(...,@ModelAttribute @Valid Account account, ...) {...accountRepository.save(account);return ...;}@PostMappingpublic ... save(@ModelAttribute @Valid Account account, ...) {...accountRepository.save(account);return ...;}... }

    更新現有帳戶時,請求將是對“ / accounts / {id}” URI的PUT 。 在這種情況下,我們的控制器需要檢索具有給定唯一標識符的域實體,并向Spring MVC提供相同的域對象以進行進一步綁定(如果有)。 “ id”字段將不需要設置方法。

    添加或保存新帳戶時,請求將是“ / accounts”的POST 。 在這種情況下,我們的控制器需要使用一些請求參數創建一個新的域實體,并向Spring MVC提供相同的域對象以進行進一步綁定(如果有)。 對于新的域實體,“ id”字段保留為null 。 基礎的持久性基礎結構將在存儲時生成一個值。 盡管如此,“ id”字段仍不需要設置方法。

    在這兩種情況下,@ @ModelAttribute方法populateModel均在映射的請求處理方法之前被調用。 因此,我們需要在populateModel使用參數來確定在哪種情況下使用它。

    域對象中沒有默認構造函數

    假設我們的Account域實體沒有提供默認構造函數(即,沒有零參數構造函數)。

    ... class Account {public Account(String name) {...}...// no public default constructor// (i.e. no public zero-arguments constructor) }

    那么,我們如何讓Spring MVC將請求參數綁定到Account域實體? 它不提供默認的構造函數。

    我們可以使用@ModelAttribute方法。 在這種情況下,我們要創建一個帶有請求參數的Account域實體,并將其用于進一步的綁定。 我們的控制器看起來像這樣。

    @Controller @RequestMapping("/accounts") ... class ... {...@ModelAttributepublic Account populateModel(HttpMethod httpMethod,@PathVariable(required=false) Long id,@RequestParam(required=false) String name) {if (id != null) {return accountRepository.findById(id).orElseThrow(...);}if (httpMethod == HttpMethod.POST) {return new Account(name);}return null;}@PutMapping("/{id}")public ... update(...,@ModelAttribute @Valid Account account, ...) {...accountRepository.save(account);return ...;}@PostMappingpublic ... save(@ModelAttribute @Valid Account account, ...) {...accountRepository.save(account);return ...;}... }

    具有子實體的域實體

    現在,讓我們看一下具有子實體的域實體。 這樣的東西。

    ... class Order {private Map<..., OrderItem> items;public Order() {...}public void addItem(int quantity, ...) {...}...public Collection<CartItem> getItems() {return Collections.unmodifiableCollection(items.values());} }... class OrderItem {private int quantity;// no public default constructor... }

    請注意,訂單中的項目不會顯示為可修改列表。 Spring MVC支持索引屬性,并將它們綁定到數組,列表或其他自然排序的集合。 但是,在這種情況下, getItems方法將返回無法修改的集合。 這意味著當對象嘗試向其添加/刪除項目時,將引發異常。 那么,如何讓Spring MVC將請求參數綁定到Order域實體? 我們是否被迫將訂單項公開為可變列表?

    并不是的。 我們必須避免用表示層關注點來稀釋域模型(例如Spring MVC)。 相反,我們使表示層成為域模型的客戶端。 為了處理這種情況,我們創建了另一個符合Spring MVC的類型,并使我們的域實體與表示層無關。

    ... class OrderForm {public static OrderForm fromDomainEntity(Order order) {...}...// public default constructor// (i.e. public zero-arguments constructor)private List<OrderFormItem> items;public List<OrderFormItem> getItems() { return items; }public void setItems(List<OrderFormItem> items) { this.items = items; }public Order toDomainEntity() {...} }... class OrderFormItem {...private int quantity;// public default constructor// (i.e. public zero-arguments constructor)// public getters and setters }

    請注意,完全可以創建一個了解域實體的表示層類型。 但是讓域實體知道表示層對象并不是全部。 更具體地說,表示層OrderForm知道Order域實體。 但是Order不了解表示層OrderForm 。

    這是我們的控制器的外觀。

    @Controller @RequestMapping("/orders") ... class ... {...@ModelAttributepublic OrderForm populateModel(HttpMethod httpMethod,@PathVariable(required=false) Long id,@RequestParam(required=false) String name) {if (id != null) {return OrderForm.fromDomainEntity(orderRepository.findById(id).orElseThrow(...));}if (httpMethod == HttpMethod.POST) {return new OrderForm(); // new Order()}return null;}@PutMapping("/{id}")public ... update(...,@ModelAttribute @Valid OrderForm orderForm, ...) {...orderRepository.save(orderForm.toDomainEntity());return ...;}@PostMappingpublic ... save(@ModelAttribute @Valid OrderForm orderForm, ...) {...orderRepository.save(orderForm.toDomainEntity());return ...;}... }

    總結思想

    正如我在之前的文章中提到的,可以讓您的域對象看起來像具有公共默認零參數構造函數,getter和setter的JavaBean。 但是,如果域邏輯開始變得復雜,并且要求某些域對象失去其JavaBean風格(例如,不再有公共的零參數構造函數,沒有更多的setter),則不必擔心。 定義新的JavaBean類型以滿足與表示相關的問題。 不要稀釋域邏輯。

    目前為止就這樣了。 我希望這有幫助。

    再次感謝Juno幫助我提供樣品。 相關代碼段可以在GitHub上找到 。

    翻譯自: https://www.javacodegeeks.com/2018/06/domain-objects-spring-mvc.html

    總結

    以上是生活随笔為你收集整理的在Spring MVC中处理域对象的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。