如何在MapStruct属性映射时转换日期属性的格式?
MapStruct实现不同格式日期属性映射的解决方案
嘿,这个场景我之前做项目的时候刚好碰到过,用MapStruct处理不同格式的日期转换其实有几种实用的方案,我给你一步步拆解清楚:
方法一:自定义日期转换器(最灵活)
如果你的日期格式比较特殊,或者需要复用转换逻辑,自定义转换器是最优选择。
- 先写一个转换器类,封装日期转换逻辑:
import org.mapstruct.Named; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class DateConverter { // 匹配源日期格式:2018-05-18T18:43:33.623+0200 private static final SimpleDateFormat SOURCE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); // 目标日期格式:2018-05-18 private static final SimpleDateFormat TARGET_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); // 把Date类型转成目标格式的字符串 @Named("dateToYmdString") public String convertDateToYmd(Date sourceDate) { if (sourceDate == null) { return null; } return TARGET_DATE_FORMAT.format(sourceDate); } // 如果源类的日期是字符串类型,加这个方法解析成Date @Named("stringToDate") public Date convertStringToDate(String sourceDateStr) throws ParseException { if (sourceDateStr == null || sourceDateStr.isBlank()) { return null; } return SOURCE_DATE_FORMAT.parse(sourceDateStr); } }
- 在你的MapStruct Mapper接口里引入这个转换器,指定转换方法:
import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; @Mapper(uses = DateConverter.class) public interface MyObjectMapper { MyObjectMapper INSTANCE = Mappers.getMapper(MyObjectMapper.class); @Mapping(source = "sourceDate", target = "targetDate", qualifiedByName = "dateToYmdString") TargetClass convertSourceToTarget(SourceClass source); }
注意:如果源类的日期是字符串类型,把qualifiedByName改成stringToDate即可,根据实际字段类型调整。
方法二:直接使用表达式(快速实现)
如果转换逻辑很简单,不想单独写转换器,可以直接在@Mapping里用Java表达式:
import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.text.SimpleDateFormat; @Mapper public interface MyObjectMapper { MyObjectMapper INSTANCE = Mappers.getMapper(MyObjectMapper.class); @Mapping(target = "targetDate", expression = "java(new SimpleDateFormat(\"yyyy-MM-dd\").format(source.getSourceDate()))") TargetClass convertSourceToTarget(SourceClass source); }
不过这种方式要注意异常处理,最好封装成工具类避免表达式太臃肿:
// 先写个工具类 import java.text.SimpleDateFormat; import java.util.Date; public class DateUtils { private static final SimpleDateFormat TARGET_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); public static String formatToYmd(Date date) { if (date == null) { return null; } try { return TARGET_FORMAT.format(date); } catch (Exception e) { // 这里可以加日志或者自定义异常处理 return null; } } }
然后表达式改成:
@Mapping(target = "targetDate", expression = "java(DateUtils.formatToYmd(source.getSourceDate()))")
方法三:结合Java 8+时间API(推荐)
如果你的项目用Java 8及以上,强烈推荐用LocalDateTime、LocalDate这些新时间类,MapStruct对它们的支持非常友好,而且线程安全:
假设源类的日期是字符串类型(格式2018-05-18T18:43:33.623+0200),目标类是LocalDate或者yyyy-MM-dd格式的字符串:
import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.time.LocalDate; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; @Mapper public interface MyObjectMapper { MyObjectMapper INSTANCE = Mappers.getMapper(MyObjectMapper.class); // 匹配源日期格式的格式化器 DateTimeFormatter SOURCE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); // 自定义转换方法,把源字符串转成LocalDate default LocalDate convertToLocalDate(String sourceDateStr) { if (sourceDateStr == null) { return null; } OffsetDateTime offsetDateTime = OffsetDateTime.parse(sourceDateStr, SOURCE_FORMATTER); return offsetDateTime.toLocalDate(); } // 如果目标是字符串格式,用这个方法 default String convertToYmdString(String sourceDateStr) { if (sourceDateStr == null) { return null; } OffsetDateTime offsetDateTime = OffsetDateTime.parse(sourceDateStr, SOURCE_FORMATTER); return offsetDateTime.toLocalDate().format(DateTimeFormatter.ISO_LOCAL_DATE); } // 根据目标字段类型选择对应的转换方法 @Mapping(source = "sourceDate", target = "targetDate") TargetClass convertSourceToTarget(SourceClass source); }
额外注意事项
- 所有转换逻辑都要处理null值,避免空指针异常
- 如果用Java 8之前的
Date类,SimpleDateFormat不是线程安全的,建议在方法内部创建实例,或者用ThreadLocal封装 - 确保你的项目已经配置了MapStruct的注解处理器(比如Maven/Gradle里的依赖配置),否则不会自动生成实现类
内容的提问来源于stack exchange,提问作者du-it
相关产品推荐
相关产品推荐

