成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

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

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

一、準(zhǔn)備

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

我們定義一個(gè)目標(biāo)對(duì)象License,該對(duì)象需要根據(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
    }
}

在定義一個(gè)源對(duì)象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在未來(lái),我們將其設(shè)置為true;
  • renewalRequired:如果endDate在接下來(lái)的兩周內(nèi),我們將其設(shè)置為true;
  • licenseType:如果輸入的licenseType不為空且值是預(yù)期值INDIVIDUAL或FAMILY之一,則轉(zhuǎn)為枚舉并賦值。

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

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

我們一起看下,如何通過MapStruct實(shí)現(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);

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

(二)使用條件表達(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á)式。

在編譯時(shí),MapStruct可以生成代碼來(lái)設(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)條件匹配時(shí),將使用源中的相應(yīng)值填充所需的屬性。

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

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

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

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

我們可以定義AfterMapping注解來(lái)有條件地映射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對(duì)象都作為參數(shù)傳遞給afterMapping方法。確保了MapStruct生成在返回License對(duì)象之前作為映射的最后一步調(diào)用此方法。

MapStruct生成的代碼是:

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

    License license = new License();

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

    afterMapping( licenseDto, license );

    return license;
}

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

(四)使用@Condition

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

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

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

源對(duì)象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時(shí)生成使用此方法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;
}

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

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

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

2021-12-22 09:34:01

Golagn配置方式

2011-03-16 09:05:53

NATiptables

2010-08-05 09:33:08

Flex頁(yè)面跳轉(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基本排序算法代碼實(shí)現(xiàn)

2010-07-16 13:50:53

Perl哈希表

2022-01-12 11:02:01

云計(jì)算安全技術(shù)

2023-07-11 10:24:00

分布式限流算法

2025-01-13 00:00:00

MapStruct繼承關(guān)系Java

2011-07-06 18:07:16

ASP

2010-08-05 13:44:12

Flex布局

2011-11-24 16:34:39

Java

2013-10-17 09:25:52

2023-11-27 13:42:00

消息隊(duì)列RocketMQ

2024-11-07 11:17:50

2021-06-17 14:46:50

框架jQuery開發(fā)
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 91久久精| 999精品在线 | 欧美国产一区二区 | 精品中文在线 | 亚洲综合在线视频 | 久久久久一区二区三区四区 | 亚洲精品视频在线 | 亚洲自拍偷拍免费视频 | 中文二区 | www在线| 成人国产精品免费观看视频 | 黄片毛片 | 97精品超碰一区二区三区 | 亚洲精品黄色 | jizz亚洲人 | 日本久久久一区二区三区 | 日本精品久久 | 成人精品一区二区三区中文字幕 | 天堂免费看片 | 国产成人综合一区二区三区 | 免费av一区二区三区 | 伦理片97 | 欧美久久一级特黄毛片 | 最新av中文字幕 | 视频1区2区| 久草精品视频 | 精品一区二区久久久久久久网站 | 成人av在线大片 | 在线午夜| 欧美午夜一区 | 影音av | 亚洲夜夜爽 | 国产成人叼嘿视频在线观看 | 性高湖久久久久久久久3小时 | 国产第一页在线播放 | 色爱综合网| 黄色大片视频 | 国产羞羞视频在线观看 | 久久久免费精品 | 成人免费精品视频 | 中文字幕亚洲一区 |