自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

MapStruct教程-四種條件映射實現(xiàn)

開發(fā) 前端
我們的例子中傳入的是屬性,還可以直接傳入源對象。還有其他的比如@TargetPropertyName、@SourcePropertyName、@Context等高級用法。

MapStruct是一個效率工具,可以在處理Java Bean映射時,幫助我們盡量減少樣板代碼,只需要定義接口,它會自動生成映射邏輯。本文中,我們一起看下如何使用MapStruct進(jìn)行條件映射。

一、準(zhǔn)備

在對象之間映射數(shù)據(jù)時,我們經(jīng)常需要根據(jù)某些條件映射屬性,MapStruct提供了一些配置選項來實現(xiàn)這一點。

我們定義一個目標(biāo)對象License,該對象需要根據(jù)一些條件映射屬性:

public class License {
    private UUID id;
    private OffsetDateTime startDate;
    private OffsetDateTime endDate;
    private boolean active;
    private boolean renewalRequired;
    private LicenseType licenseType;

    public enum LicenseType {
        INDIVIDUAL, FAMILY
    }
}

在定義一個源對象LicenseDto,包含可選的startDate、endDate和licenseType:

public class LicenseDto {
    private UUID id;
    private LocalDateTime startDate;
    private LocalDateTime endDate;
    private String licenseType;
}

以下是從LicenseDto到License的映射規(guī)則:

  • id:如果LicenseDto有id,則賦值;
  • startDate:如果LicenseDto沒有startDate,設(shè)置為當(dāng)前日期;
  • endDate:如果LicenseDto沒有endDate,設(shè)置為從當(dāng)前日期起一年后;
  • active:如果endDate在未來,我們將其設(shè)置為true;
  • renewalRequired:如果endDate在接下來的兩周內(nèi),我們將其設(shè)置為true;
  • licenseType:如果輸入的licenseType不為空且值是預(yù)期值INDIVIDUAL或FAMILY之一,則轉(zhuǎn)為枚舉并賦值。

上述規(guī)則其實很簡單,如果是手寫代碼也能實現(xiàn),不過既然有工具,還是要高效使用工具。

二、使用MapStruct進(jìn)行條件映射

我們一起看下,如何通過MapStruct實現(xiàn)上述邏輯。

(一)使用表達(dá)式

MapStruct提供了在映射表達(dá)式中,使用Java代碼的功能。讓我們利用此功能映射startDate:

@Mapper
public interface LicenseMapper {
    @Mapping(target = "startDate", expression = "java(mapStartDate(licenseDto))")
    License toLicense(LicenseDto licenseDto);

    default OffsetDateTime mapStartDate(LicenseDto licenseDto) {
        return licenseDto.getStartDate() != null
               ? licenseDto.getStartDate().atOffset(ZoneOffset.UTC) : OffsetDateTime.now();
    }
}

我們可以在@Mapping定義expression指定該字段賦值的Java代碼。我們看下MapStruct生成的代碼:

@Override
public License toLicense(LicenseDto licenseDto) {
    if ( licenseDto == null ) {
        return null;
    }

    License license = new License();
    license.setStartDate( mapStartDate(licenseDto) );
    // 其余生成的映射...
    return license;
}

我們也可以這樣寫:

@Mapping(target = "startDate", expression = "java(licenseDto.getStartDate() != null ? licenseDto.getStartDate().atOffset(java.time.ZoneOffset.UTC) : java.time.OffsetDateTime.now())")
License toLicense(LicenseDto licenseDto);

直接把三元運算符的邏輯放到expression表達(dá)式中,也能正常運行。

(二)使用條件表達(dá)式

MapStruct還提供了條件表達(dá)式,允許根據(jù)字符串中的條件表達(dá)式映射屬性。我們一起利用此功能映射License中的renewalRequired字段:

@Mapping(target = "renewalRequired", conditionExpression = "java(isEndDateInTwoWeeks(licenseDto))", source = ".")
License toLicense(LicenseDto licenseDto);

default boolean isEndDateInTwoWeeks(LicenseDto licenseDto) {
    return licenseDto.getEndDate() != null
            && Duration.between(licenseDto.getEndDate(), LocalDateTime.now()).toDays() <= 14;
}

我們可以在java()方法中傳遞任何有效的Java布爾表達(dá)式。

在編譯時,MapStruct可以生成代碼來設(shè)置renewalRequired:

@Override
public License toLicense(LicenseDto licenseDto) {
    if ( licenseDto == null ) {
        return null;
    }

    License license = new License();

    if ( isEndDateInTwoWeeks(licenseDto) ) {
        license.setRenewalRequired( isEndDateInTwoWeeks( licenseDto ) );
    }
    // 其余生成的映射...
    return license;
}

可以看到,生成的代碼在if塊中包含條件。當(dāng)條件匹配時,將使用源中的相應(yīng)值填充所需的屬性。

(三)使用映射前/后操作

在某些情況下,如果我們希望在映射之前或之后通過自定義修改對象,可以使用MapStruct的@BeforeMapping和@AfterMapping注解。

我們可以使用此功能有條件地映射endDate:

@Mapping(target = "endDate", ignore = true)
License toLicense(LicenseDto licenseDto);

我們可以定義AfterMapping注解來有條件地映射endDate。通過這種方式,我們可以根據(jù)特定條件控制映射:

@AfterMapping
default void afterMapping(LicenseDto licenseDto, @MappingTarget License license) {
    OffsetDateTime endDate = licenseDto.getEndDate() != null ? licenseDto.getEndDate().atOffset(ZoneOffset.UTC)
                                                             : OffsetDateTime.now().plusYears(1);
    license.setEndDate(endDate);
}

我們需要將輸入的LicenseDto和目標(biāo)License對象都作為參數(shù)傳遞給afterMapping方法。確保了MapStruct生成在返回License對象之前作為映射的最后一步調(diào)用此方法。

MapStruct生成的代碼是:

@Override
public License toLicense(LicenseDto licenseDto) {
    if ( licenseDto == null ) {
        return null;
    }

    License license = new License();

    // 其余生成的映射...

    afterMapping( licenseDto, license );

    return license;
}

同樣的,我們也可以使用BeforeMapping注解來達(dá)到相同的結(jié)果。

(四)使用@Condition

在映射時,我們可以使用@Condition為屬性添加自定義存在性檢查。

默認(rèn)情況下,MapStruct會對每個屬性執(zhí)行存在性檢查,但如果有@Condition注解的方法,則優(yōu)先使用該方法。

讓我們使用此功能映射licenseType。

源對象LicenseDto的licenseType是String類型,在映射期間,如果它不為null且解析為預(yù)期的枚舉INDIVIDUAL或FAMILY之一,我們需要將其映射到目標(biāo)。我們先定義條件函數(shù):

@Condition
default boolean mapsToExpectedLicenseType(String licenseType) {
    try {
        if (licenseType == null) {
            return false;
        }
        License.LicenseType.valueOf(licenseType);
        return true;
    } catch (IllegalArgumentException e) {
        return false;
    }
}

方法mapsToExpectedLicenseType的參數(shù)類型是String,與LicenseDto中的licenseType匹配,MapStruct在映射licenseType時生成使用此方法mapsToExpectedLicenseType()的代碼:

@Override
public License toLicense(LicenseDto licenseDto) {
    if ( licenseDto == null ) {
        return null;
    }

    License license = new License();
    if ( mapsToExpectedLicenseType( licenseDto.getLicenseType() ) ) {
        license.setLicenseType( Enum.valueOf( License.LicenseType.class, licenseDto.getLicenseType() ) );
    }
    // 其余生成的映射...
    return license;
}

我們的例子中傳入的是屬性,還可以直接傳入源對象。還有其他的比如@TargetPropertyName、@SourcePropertyName、@Context等高級用法。

在筆者實踐時,這些配置雖然能夠解決問題,但是有過渡依賴MapStruct或者炫技的嫌疑。我們要的是少寫無營養(yǎng)代碼,不是引入太多不可控因素,給自己埋雷。

責(zé)任編輯:武曉燕 來源: 看山的小屋
相關(guān)推薦

2011-03-16 09:05:53

NATiptables

2021-12-22 09:34:01

Golagn配置方式

2010-08-05 09:33:08

Flex頁面跳轉(zhuǎn)

2025-01-13 00:00:00

MapStruct枚舉映射

2025-01-10 00:00:00

MapStructArticlePerson

2015-04-02 16:54:52

災(zāi)難恢復(fù)VDI災(zāi)難恢復(fù)

2015-04-13 11:39:26

VDI災(zāi)難恢復(fù)

2021-10-24 08:37:18

網(wǎng)絡(luò)監(jiān)控網(wǎng)絡(luò)架構(gòu)網(wǎng)絡(luò)

2015-03-19 15:13:20

PHP基本排序算法代碼實現(xiàn)

2010-07-16 13:50:53

Perl哈希表

2022-01-12 11:02:01

云計算安全技術(shù)

2023-07-11 10:24:00

分布式限流算法

2025-01-13 00:00:00

MapStruct繼承關(guān)系Java

2011-07-06 18:07:16

ASP

2021-06-17 14:46:50

框架jQuery開發(fā)

2024-11-07 11:17:50

2020-01-21 19:15:23

漏洞安全IT

2025-03-12 09:54:02

2010-09-02 10:55:57

CSS

2022-08-01 07:56:23

React Hook開發(fā)組件
點贊
收藏

51CTO技術(shù)棧公眾號