spring boot DTO转为为json,Date类型格式化

博客介绍Java开发要点,一是在DTO中添加@JSONField,二是在@FeignClient服务间调用时使用public,有助于开发者避免相关问题,提升开发效率。

1.在DTO 加@JSONField

    @JSONField(format = "yyyy-MM-dd")
    private Date endTime;

2.另外如果为@FeignClient 服务间调用请使用public 喔

    @JSONField(format = "yyyy-MM-dd")
    public Date endTime;
<think>在Spring Boot中,优雅地处理DTO与Entity之间的转换通常采用以下几种方式: 1. 手动编写转换方法(简单直接,但代码冗余) 2. 使用工具库(如MapStruct、ModelMapper等)实现自动转换 3. 使用Spring的Converter或转换服务 其中,MapStruct因其编译时生成转换代码(无反射,高性能)和强类型检查而被广泛推荐。 以下将重点介绍使用MapStruct的实现方案: 步骤1:添加MapStruct依赖(Maven) 步骤2:定义Mapper接口 步骤3:在Service中注入并使用Mapper 示例代码: 1. 添加依赖(pom.xml): ```xml <properties> <mapstruct.version>1.5.5.Final</mapstruct.version> </properties> <dependencies> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>${mapstruct.version}</version> </dependency> <!-- 注解处理器,用于生成实现类 --> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>${mapstruct.version}</version> <scope>provided</scope> </dependency> </dependencies> ``` 2. 定义DTO和Entity(示例): ```java // Entity public class NursingPlan { private Long id; private String planName; private String content; private LocalDateTime createTime; // 其他字段、getter和setter } // DTO public class NursingPlanDto { private String planName; private String content; // 其他字段、getter和setter } ``` 3. 创建Mapper接口: ```java import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; @Mapper(componentModel = "spring") // 使用Spring组件模型,这样可以通过@Autowired注入 public interface NursingPlanMapper { // 如果字段名不一致,可以使用@Mapping注解 @Mapping(target = "createTime", ignore = true) // 忽略createTime,因为通常由系统生成 NursingPlan toEntity(NursingPlanDto dto); // 如果需要反向转换 NursingPlanDto toDto(NursingPlan entity); } ``` 4. 在Service中使用: ```java @Service public class NursingPlanServiceImpl implements NursingPlanService { private final NursingPlanMapper nursingPlanMapper; // MapStruct生成的实现 private final NursingPlanRepository repository; // 假设使用JPA public NursingPlanServiceImpl(NursingPlanMapper nursingPlanMapper, NursingPlanRepository repository) { this.nursingPlanMapper = nursingPlanMapper; this.repository = repository; } @Override @Transactional public void createNursingPlan(NursingPlanDto dto) { NursingPlan entity = nursingPlanMapper.toEntity(dto); entity.setCreateTime(LocalDateTime.now()); // 设置创建时间 repository.save(entity); } } ``` 5. 如果字段名不一致或需要特殊处理,可以在Mapper接口中通过@Mapping注解配置: ```java @Mapper(componentModel = "spring") public interface NursingPlanMapper { @Mapping(source = "planName", target = "name") // 当源和目标字段名不同时 @Mapping(target = "id", ignore = true) // 插入时忽略id(自增) NursingPlan toEntity(NursingPlanDto dto); // 反向转换 @Mapping(source = "name", target = "planName") NursingPlanDto toDto(NursingPlan entity); } ``` 6. 对于复杂转换(如嵌套对象),MapStruct同样支持: ```java public class NursingPlan { private Patient patient; // 另一个实体 } public class NursingPlanDto { private Long patientId; // 前端只传了患者ID } // Mapper中 @Mapper(componentModel = "spring") public interface NursingPlanMapper { @Mapping(source = "patientId", target = "patient.id") // 将patientId赋值给patient对象的id NursingPlan toEntity(NursingPlanDto dto); } ``` 7. 如果转换逻辑非常复杂,还可以使用@AfterMapping自定义方法: ```java @Mapper(componentModel = "spring", uses = {PatientRepository.class}) public abstract class NursingPlanMapper { @Autowired protected PatientRepository patientRepository; @Mapping(target = "patient", ignore = true) // 忽略,由下面方法处理 public abstract NursingPlan toEntity(NursingPlanDto dto); @AfterMapping protected void afterToEntity(NursingPlanDto dto, @MappingTarget NursingPlan entity) { // 根据patientId查询Patient对象并设置 Patient patient = patientRepository.findById(dto.getPatientId()) .orElseThrow(() -> new EntityNotFoundException("Patient not found")); entity.setPatient(patient); } } ``` 注意:这里使用了抽象类,因为需要注入Repository。同时,在@Mapper注解中指定了uses,但这里由于我们直接注入了,所以也可以不用uses。 优点: - 编译时生成转换代码,无反射,性能高 - 类型安全,容易重构 - 支持复杂映射和自定义方法 其他方式: - 使用ModelMapper(基于反射,简单但性能稍差,且容易在字段名不一致时出错) - 手动转换:适用于字段少、逻辑简单的情况 根据项目规模和性能要求选择合适的方式。对于大型项目,推荐MapStruct。 §§相关问题§§: 1. MapStruct 如何处理不同字段名称的映射? 2. 除了 MapStruct,还有哪些常用的 Java 对象映射工具? 3. 在 Spring Boot 中如何配置全局的转换服务(Converter)? 4. 使用 MapStruct 时如何实现集合类型转换?</think>在 Spring Boot 中优雅地处理 DTO 与 Entity 的转换,推荐以下几种专业方案: ### 最佳实践方案:使用 MapStruct(编译时代码生成) #### 1. 添加依赖 ```xml <!-- pom.xml --> <dependencies> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.5.5.Final</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.5.5.Final</version> <scope>provided</scope> </dependency> </dependencies> ``` #### 2. 创建映射接口 ```java @Mapper(componentModel = "spring", uses = {DateMapper.class, CustomConverter.class}) // 组件模型和自定义转换器 public interface NursingPlanMapper { @Mapping(source = "patientId", target = "patient.id") // 嵌套属性映射 @Mapping(target = "createdAt", ignore = true) // 忽略自动生成的字段 @Mapping(source = "planType", target = "type", qualifiedByName = "planTypeConverter") NursingPlan toEntity(NursingPlanDto dto); @InheritInverseConfiguration(name = "toEntity") NursingPlanDto toDto(NursingPlan entity); // 集合类型转换 List<NursingPlanDto> toDtoList(List<NursingPlan> entities); // 自定义转换方法 @Named("planTypeConverter") default PlanType convertPlanType(String type) { return PlanType.valueOf(type.toUpperCase()); } } // 日期转换器(单独类) @Mapper public interface DateMapper { default LocalDateTime toLocalDateTime(Date date) { return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); } } ``` #### 3. Service 层使用 ```java @Service @RequiredArgsConstructor public class NursingPlanService { private final NursingPlanMapper mapper; private final NursingPlanRepository repository; @Transactional public NursingPlanDto createPlan(NursingPlanDto dto) { NursingPlan entity = mapper.toEntity(dto); entity.setCreatedAt(LocalDateTime.now()); // 设置自动生成字段 NursingPlan saved = repository.save(entity); return mapper.toDto(saved); } public List<NursingPlanDto> getAllPlans() { return mapper.toDtoList(repository.findAll()); } } ``` ### 备选方案:其他转换方式对比 | 方案 | 优点 | 缺点 | 适用场景 | |------|------|------|----------| | **MapStruct** | 编译时生成代码,零运行时开销,类型安全 | 需要额外注解配置 | 高性能场景,大型项目 | | **ModelMapper** | 自动匹配字段,配置简单 | 反射性能开销,复杂映射配置难 | 快速原型开发 | | **手动转换** | 完全可控,无依赖 | 代码冗余,维护困难 | 简单DTO转换 | | **Jackson Mixins** | 序列化时转换,无额外代码 | 仅适用于JSON序列化 | API响应格式化 | ### 关键优化技巧 1. **嵌套属性映射** ```java @Mapping(source = "patientInfo.name", target = "patientName") ``` 2. **条件映射** ```java @Mapping(target = "status", conditionExpression = "java(dto.isEmergency())", expression = "java(PlanStatus.URGENT)") ``` 3. **集合映射优化** ```java @Mapping(target = "items", ignore = true) // 避免N+1查询问题 NursingPlanDto toDto(NursingPlan entity); ``` 4. **自定义转换器** ```java @Mapper(uses = {EncryptionConverter.class}) public interface NursingPlanMapper { // 自动使用EncryptionConverter进行加解密 } public class EncryptionConverter { public String encrypt(String input) { return AESUtils.encrypt(input); } } ``` ### 最佳实践建议 1. **领域隔离原则** - DTO 只包含展示层需要的字段 - Entity 包含所有持久层字段 2. **版本控制** ```java // V1 DTO public class NursingPlanDtoV1 { // 初始字段 } // V2 DTO public class NursingPlanDtoV2 { // 新增/修改字段 } ``` 3. **性能监控** ```java @Aspect @Component public class MappingMonitor { @Around("execution(* com.example.mapper.*.*(..))") public Object logMappingTime(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); Object result = joinPoint.proceed(); log.info("Mapping {} took {}ms", joinPoint.getSignature(), System.currentTimeMillis() - start); return result; } } ``` 4. **空值处理策略** ```java @Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) public interface NursingPlanMapper { // 忽略空值的更新操作 } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值