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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

在Spring MVC中处理域对象

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

最近,我驚訝于一個代碼庫在其所有域?qū)嶓w中都具有公共默認構(gòu)造函數(shù)(即零參數(shù)構(gòu)造函數(shù)),并且所有字段都具有g(shù)etter和setter。 當(dāng)我深入研究時,我發(fā)現(xiàn)域?qū)嶓w之所以如此,主要是因為該團隊認為Web / MVC框架需要它。 我認為這是消除一些誤解的好機會。

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

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

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

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

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

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

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

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

    生成ID字段的無設(shè)置方法

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

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

    那么,我們?nèi)绾巫孲pring MVC將請求參數(shù)綁定到Account域?qū)嶓w? 我們是否必須為生成的字段和只讀字段提供公共設(shè)置方法?

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

    我們使用@ModelAttribute方法。 在請求處理方法之前調(diào)用它。 它支持與常規(guī)請求處理方法幾乎相同的參數(shù)。 在我們的例子中,我們使用它來檢索具有給定唯一標(biāo)識符的Account域?qū)嶓w,并將其用于進一步的綁定。 我們的控制器看起來像這樣。

    @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 ...;}... }

    更新現(xiàn)有帳戶時,請求將是對“ / accounts / {id}” URI的PUT 。 在這種情況下,我們的控制器需要檢索具有給定唯一標(biāo)識符的域?qū)嶓w,并向Spring MVC提供相同的域?qū)ο笠赃M行進一步綁定(如果有)。 “ id”字段將不需要設(shè)置方法。

    添加或保存新帳戶時,請求將是“ / accounts”的POST 。 在這種情況下,我們的控制器需要使用一些請求參數(shù)創(chuàng)建一個新的域?qū)嶓w,并向Spring MVC提供相同的域?qū)ο笠赃M行進一步綁定(如果有)。 對于新的域?qū)嶓w,“ id”字段保留為null 。 基礎(chǔ)的持久性基礎(chǔ)結(jié)構(gòu)將在存儲時生成一個值。 盡管如此,“ id”字段仍不需要設(shè)置方法。

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

    域?qū)ο笾袥]有默認構(gòu)造函數(shù)

    假設(shè)我們的Account域?qū)嶓w沒有提供默認構(gòu)造函數(shù)(即,沒有零參數(shù)構(gòu)造函數(shù))。

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

    那么,我們?nèi)绾巫孲pring MVC將請求參數(shù)綁定到Account域?qū)嶓w? 它不提供默認的構(gòu)造函數(shù)。

    我們可以使用@ModelAttribute方法。 在這種情況下,我們要創(chuàng)建一個帶有請求參數(shù)的Account域?qū)嶓w,并將其用于進一步的綁定。 我們的控制器看起來像這樣。

    @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 ...;}... }

    具有子實體的域?qū)嶓w

    現(xiàn)在,讓我們看一下具有子實體的域?qū)嶓w。 這樣的東西。

    ... 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支持索引屬性,并將它們綁定到數(shù)組,列表或其他自然排序的集合。 但是,在這種情況下, getItems方法將返回?zé)o法修改的集合。 這意味著當(dāng)對象嘗試向其添加/刪除項目時,將引發(fā)異常。 那么,如何讓Spring MVC將請求參數(shù)綁定到Order域?qū)嶓w? 我們是否被迫將訂單項公開為可變列表?

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

    ... 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 }

    請注意,完全可以創(chuàng)建一個了解域?qū)嶓w的表示層類型。 但是讓域?qū)嶓w知道表示層對象并不是全部。 更具體地說,表示層OrderForm知道Order域?qū)嶓w。 但是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 ...;}... }

    總結(jié)思想

    正如我在之前的文章中提到的,可以讓您的域?qū)ο罂雌饋硐窬哂泄材J零參數(shù)構(gòu)造函數(shù),getter和setter的JavaBean。 但是,如果域邏輯開始變得復(fù)雜,并且要求某些域?qū)ο笫テ銳avaBean風(fēng)格(例如,不再有公共的零參數(shù)構(gòu)造函數(shù),沒有更多的setter),則不必擔(dān)心。 定義新的JavaBean類型以滿足與表示相關(guān)的問題。 不要稀釋域邏輯。

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

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

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

    總結(jié)

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

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。