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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

在Java中进行输入验证时用错误通知替换异常

發布時間:2023/12/3 java 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在Java中进行输入验证时用错误通知替换异常 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在我以前的文章中,我寫了一個輸入驗證設計,該設計取代了難以維護和測試的 if-else塊。 但是,正如某些讀者指出的那樣,它有一個缺點–如果輸入數據有多個驗證錯誤,則用戶將不得不多次提交請求以查找所有錯誤。 從可用性的角度來看,這不是一個好的設計。

當我們發現驗證錯誤時,拋出異常的另一種方法是返回一個包含錯誤的Notification對象。 這將使我們能夠在用戶輸入上運行所有驗證規則,并同時捕獲所有違規行為。 Martin Fowler 撰寫了一篇文章,詳細介紹了該方法。 我強烈建議您繼續閱讀,如果您還沒有讀過的話。

在本文中,我將重構以前的實現,以使用錯誤通知對象來驗證用戶輸入。

第一步,我將創建一個ErrorNotification對象,該對象封裝了我的應用程序錯誤-

public class ErrorNotification {private List<String> errors = new ArrayList<>();public void addError(String message) {this.errors.add(message);}public boolean hasError() {return !this.errors.isEmpty();}public String getAllErrors() {return this.errors.stream().collect(joining(", "));} }

然后,我將更改OrderItemValidator接口以返回ErrorNotification對象–

public interface OrderItemValidator {ErrorNotification validate(OrderItem orderItem); }

然后更改所有實現以適應新的返回類型。

最初,我將更改所有實現以返回一個空的錯誤對象,以便擺脫編譯錯誤。 例如,我將通過以下方式更改ItemDescriptionValidator –

class ItemDescriptionValidator implements OrderItemValidator {@Overridepublic ErrorNotification validate(OrderItem orderItem) {ErrorNotification errorNotification = new ErrorNotification();Optional.ofNullable(orderItem).map(OrderItem::getDescription).map(String::trim).filter(description -> !description.isEmpty()).orElseThrow(() -> new IllegalArgumentException("Item description should be provided"));return errorNotification;} }

修復編譯錯誤之后,我現在將開始用每個驗證器中的通知消息替換異常。 為此,我將首先修改相關測試以反映我的意圖,然后修改驗證器以通過測試。

讓我們從ItemDescriptionValidatorTest類開始–

public class ItemDescriptionValidatorTest {@Testpublic void validate_descriptionIsNull_invalid() {ItemDescriptionValidator validator = new ItemDescriptionValidator();ErrorNotification errorNotification = validator.validate(new OrderItem());assertThat(errorNotification.getAllErrors()).isEqualTo("Item description should be provided");}@Testpublic void validate_descriptionIsBlank_invalid() {OrderItem orderItem = new OrderItem();orderItem.setDescription(" ");ItemDescriptionValidator validator = new ItemDescriptionValidator();ErrorNotification errorNotification = validator.validate(new OrderItem());assertThat(errorNotification.getAllErrors()).isEqualTo("Item description should be provided");}@Testpublic void validate_descriptionGiven_valid() {OrderItem orderItem = new OrderItem();orderItem.setDescription("dummy description");ItemDescriptionValidator validator = new ItemDescriptionValidator();ErrorNotification errorNotification = validator.validate(orderItem);assertThat(errorNotification.getAllErrors()).isEmpty();} }

當我運行這些測試時,只有其中一項通過,而其中兩項失敗,這是預料之中的。 我現在將修改驗證器代碼以通過測試–

class ItemDescriptionValidator implements OrderItemValidator {static final String MISSING_ITEM_DESCRIPTION = "Item description should be provided";@Overridepublic ErrorNotification validate(OrderItem orderItem) {ErrorNotification errorNotification = new ErrorNotification();Optional.ofNullable(orderItem).map(OrderItem::getDescription).map(String::trim).filter(description -> !description.isEmpty()).ifPresentOrElse(description -> {},() -> errorNotification.addError(MISSING_ITEM_DESCRIPTION));return errorNotification;} }

我對上面的ifPresentOrElse方法的使用感到不舒服。 我在這里使用它的主要原因是因為Optionals沒有ifNotPresent方法之類的東西,該方法允許我僅在不存在該值的情況下才采取措施(請向讀者提出要求-如果您知道一種更好的方法,為此,請發表評論!)。

進行此重構后, ItemValidatorTest類中的所有測試均通過測試。 大!

現在,讓我們重構MenuValidatorTest類中的測試–

public class MenuValidatorTest {@Testpublic void validate_menuIdInvalid_invalid() {OrderItem orderItem = new OrderItem();String menuId = "some menu id";orderItem.setMenuId(menuId);MenuRepository menuRepository = mock(MenuRepository.class);when(menuRepository.menuExists(any())).thenReturn(false);MenuValidator validator = new MenuValidator(menuRepository);ErrorNotification errorNotification = validator.validate(orderItem);assertThat(errorNotification.getAllErrors()).isEqualTo(String.format(MenuValidator.INVALID_MENU_ERROR_FORMAT, menuId));}@Testpublic void validate_menuIdNull_invalid() {MenuRepository menuRepository = mock(MenuRepository.class);when(menuRepository.menuExists(any())).thenReturn(true);MenuValidator validator = new MenuValidator(menuRepository);ErrorNotification errorNotification = validator.validate(new OrderItem());assertThat(errorNotification.getAllErrors()).isEqualTo(MenuValidator.MISSING_MENU_ERROR);}@Testpublic void validate_menuIdIsBlank_invalid() {OrderItem orderItem = new OrderItem();orderItem.setMenuId(" \t");MenuRepository menuRepository = mock(MenuRepository.class);when(menuRepository.menuExists(any())).thenReturn(true);MenuValidator validator = new MenuValidator(menuRepository);ErrorNotification errorNotification = validator.validate(orderItem);assertThat(errorNotification.getAllErrors()).isEqualTo(MenuValidator.MISSING_MENU_ERROR);}@Testpublic void validate_menuIdValid_validated() {OrderItem orderItem = new OrderItem();String menuId = "some menu id";orderItem.setMenuId(menuId);MenuRepository menuRepository = mock(MenuRepository.class);when(menuRepository.menuExists(menuId)).thenReturn(true);MenuValidator validator = new MenuValidator(menuRepository);ErrorNotification errorNotification = validator.validate(orderItem);assertThat(errorNotification.getAllErrors()).isEmpty();} }

然后是MenuValidator類–

@RequiredArgsConstructor class MenuValidator implements OrderItemValidator {private final MenuRepository menuRepository;static final String MISSING_MENU_ERROR = "A menu item must be specified.";static final String INVALID_MENU_ERROR_FORMAT = "Given menu [%s] does not exist.";@Overridepublic ErrorNotification validate(OrderItem orderItem) {ErrorNotification errorNotification = new ErrorNotification();Optional.ofNullable(orderItem.getMenuId()).map(String::trim).filter(menuId -> !menuId.isEmpty()).ifPresentOrElse(validateMenuExists(errorNotification),() -> errorNotification.addError(MISSING_MENU_ERROR));return errorNotification;}private Consumer<String> validateMenuExists(ErrorNotification errorNotification) {return menuId -> {if (!menuRepository.menuExists(menuId)) {errorNotification.addError(String.format(INVALID_MENU_ERROR_FORMAT, menuId));}};} }

等等。

修改了各個驗證器之后,我現在將修改Composite以收集單個訂單商品的所有錯誤–

@RequiredArgsConstructor class OrderItemValidatorComposite implements OrderItemValidator {private final List<OrderItemValidator> validators;@Overridepublic ErrorNotification validate(OrderItem orderItem) {ErrorNotification errorNotification = new ErrorNotification();validators.stream().map(validator -> validator.validate(orderItem)).forEach(errorNotification::addAll);return errorNotification;} }

為此,我在ErrorNotification類中添加了一個名為addAll的新方法,該方法基本上從另一個ErrorNotification對象復制所有錯誤。

最后,我現在將修改服務方法以收集訂單中所有訂單項的所有錯誤消息–

@Service @Slf4j @RequiredArgsConstructor class OrderService {private final OrderItemValidator validator;void createOrder(OrderDTO orderDTO) {ErrorNotification errorNotification = new ErrorNotification();orderDTO.getOrderItems().stream().map(validator::validate).forEach(errorNotification::addAll);if (errorNotification.hasError()) {throw new IllegalArgumentException(errorNotification.getAllErrors());}log.info("Order {} saved", orderDTO);} }

進行此更改會導致OrderServiceIT中的測試之一失敗,因為當價格無效時,它專門查找原因設置為NumberFormatException的異常。 重構后,我們可以安全地刪除此檢查,因為它不再相關。

本文的完整源代碼已推送到GitHub (特定的提交URL在此處 )。

翻譯自: https://www.javacodegeeks.com/2017/11/replacing-exceptions-error-notifications-input-validation-java.html

總結

以上是生活随笔為你收集整理的在Java中进行输入验证时用错误通知替换异常的全部內容,希望文章能夠幫你解決所遇到的問題。

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