1. 简介

MapStruct 是Java中一个强大的库,它能在编译时简化不同对象模型之间的映射过程。它通过注解自动生成类型安全的映射器实现,既高效又易于维护。

MapStruct常用于需要对象间映射的应用场景,比如在分层架构中传输数据或将DTO转换为实体类。一个常见的需求是将String转换为Date对象,这个过程可能因为日期格式多样和解析要求复杂而变得棘手。本文将探讨使用MapStruct实现这种转换的多种方法。

2. 依赖配置

要开始使用MapStruct,我们需要在项目中添加必要的依赖。对于Maven项目,在pom.xml中添加以下依赖

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.5.Final</version>
</dependency>

此外,还需要配置*maven-compiler-plugin*以包含MapStruct的处理器

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.13.0</version>
            <configuration>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>1.5.5.Final</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

完成这些依赖配置后,就可以在项目中使用MapStruct了。

3. 使用@Mapping注解实现基础映射

MapStruct提供了*@Mapping注解来定义不同类型之间的属性映射规则。默认情况下,MapStruct不支持StringDate之间的直接转换,但我们可以利用@Mapping注解的format*属性来处理这种转换。

看一个将UserDto映射到User实体的基础示例:

public class UserDto {
    private String name;
    // 字符串格式的日期
    private String birthDate; 
    // getters and setters
}

public class User {
    private String name;
    private Date birthDate;
    // getters and setters
}

@Mapper
public interface UserMapper {
    @Mapping(source = "birthDate", target = "birthDate", dateFormat = "yyyy-MM-dd")
    User toUser(UserDto userDto);
}

在这个例子中,*@Mapping注解指定了UserDto中的birthDate字段应映射到User中的birthDate字段。dateFormat*属性用于定义日期字符串的格式,让MapStruct自动处理转换。

验证这个转换:

@Test
public void whenMappingUserDtoToUser_thenMapsBirthDateCorrectly() throws ParseException {
    UserDto userDto = new UserDto();
    userDto.setName("John Doe");
    userDto.setBirthDate("2024-08-01");

    User user = userMapper.toUser(userDto);

    assertNotNull(user);
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    Date expectedDate = dateFormat.parse("2024-08-01");
    Assertions.assertEquals(expectedDate, user.getBirthDate());
}

这个测试用例验证了通过UserMapperbirthDateUserDto正确映射到User,确认了日期转换的准确性。

4. 实现自定义转换方法

对于更复杂的场景,我们可能需要实现自定义转换方法。这些方法可以直接定义在映射器接口中。通过使用*@Mapping*注解的expression属性,我们可以指示MapStruct使用这些自定义转换方法。

下面是如何定义一个将String转换为Date的自定义方法:

@Mapper
public interface UserMapper {
    @Mapping(target = "birthDate", expression = "java(mapStringToDate(userDto.getBirthDate()))")
    User toUserCustom(UserDto userDto) throws ParseException;

    default Date mapStringToDate(String date) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return dateFormat.parse(date);
    }
}

在这个例子中,mapStringToDate()方法使用SimpleDateFormatString转换为Date。我们在*@Mapping*注解中使用显式表达式告诉MapStruct在映射时调用这个方法。

5. 复用通用自定义方法

假设项目中多个映射器需要相同类型的转换,那么将自定义映射方法定义在独立的工具类中并在不同映射器间复用会更高效。

首先,创建一个包含转换方法的工具类:

public class DateMapper {
    public Date mapStringToDate(String date) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return dateFormat.parse(date);
    }
}

然后在映射器中使用这个工具类:

@Mapper(uses = DateMapper.class)
public interface UserConversionMapper {
    @Mapping(source = "birthDate", target = "birthDate")
    User toUser(UserDto userDto);
}

通过在*@Mapper注解中指定uses = DateMapper.class,我们告诉MapStruct在转换时使用DateMapper*中的方法。这种方式促进了代码复用,使映射逻辑更有条理且易于维护。

6. 总结

MapStruct是Java中对象映射的强大工具。通过自定义方法,我们可以轻松处理开箱即用不支持的类型转换,例如将String转换为Date

按照本文概述的步骤,我们可以在项目中高效实现并复用自定义转换方法。此外,对于简单的日期转换,使用*@Mapping注解中的dateFormat*属性可以简化过程。

这些技术让我们能在Java应用的各种映射场景中充分发挥MapStruct的潜力。

源代码可在GitHub上获取。


原始标题:How to Convert String to Date Using MapStruct in Java? | Baeldung