【问题标题】:Use a MapStruct mapper to programmatically set a custom value to the DTO depending on the application's environment根据应用程序的环境,使用 MapStruct 映射器以编程方式为 DTO 设置自定义值
【发布时间】:2021-01-15 14:36:35
【问题描述】:

我有一个 MarkdownService,它执行以下操作:

  1. 开启交易

  2. 从存储库中获取 Markdown 实体

 Markdown markdown = markdownRepository
      .findById(markdownId)
      .orElseThrow(EntityNotFoundException::new);
  1. 检索原始文件名并与markdownId一起根据业务规则创建新文件名。
String originalFilename = storageService.getOriginalFilename(file);

String filename = Markdown.normalizeMdPath(markdownId + "-" + originalFilename);
  1. 将文件保存到磁盘的特定路径,/articles/markdowns
 storageService.store(
      file,
      this.uploadMarkdownsPath,
      filename
    );
  1. 更新实体仅使用文件名,而不是完整路径
    markdown.setMdPath(filename);
  1. 使用 ma​​pstruct 将 Markdown 实体映射到其对应的 MarkdownDto
    MarkdownDto dto = MarkdownMapper.INSTANCE.toMarkdownDto(markdown);
  1. 现在,由于应用程序在本地运行,因此获取上传的 Markdown 文件的完整路径并更新 DTO,将其返回给控制器。
 String fullPath = ServletUriComponentsBuilder
      .fromCurrentContextPath()
      .path("/markdown/download/")
      .path(dto.getMdPath())
      .toUriString();

    dto.setMdPath(fullPath);

    return dto;

现在,该应用程序也将在 AWS Fargate 中以特定域名在生产环境中运行,并且实际降价将存储在云中,甚至不会存储在文件系统中。

我的问题是,我可以根据 Spring 环境变量以某种方式修改 Mapstruct 映射器以在 DTO 级别设置 markdown 文件的完整路径吗?我会避免在每个返回 markdown DTO 的控制器方法上执行此手动映射。

@Mapper
public interface MarkdownMapper {
  MarkdownMapper INSTANCE = Mappers.getMapper(MarkdownMapper.class);

  MarkdownDto toMarkdownDto(Markdown markdown);
}

有没有更好的方法来处理这个问题?也许是完全不同的解决方案?

这里是完整的代码:

  @Transactional
  public MarkdownDto uploadMarkdownFile(Long markdownId, MultipartFile file) throws FileNotFoundException {
    Markdown markdown = markdownRepository
      .findById(markdownId)
      .orElseThrow(EntityNotFoundException::new);

    String originalFilename = storageService.getOriginalFilename(file);

    String filename = Markdown.normalizeMdPath(markdownId + "-" + originalFilename);

    storageService.store(
      file,
      this.uploadMarkdownsPath,
      filename
    );

    markdown.setMdPath(filename);

    MarkdownDto dto = MarkdownMapper.INSTANCE.toMarkdownDto(markdown);

    String fullPath = ServletUriComponentsBuilder
      .fromCurrentContextPath()
      .path("/markdown/download/")
      .path(dto.getMdPath())
      .toUriString();

    dto.setMdPath(fullPath);

    return dto;
  }

谢谢!

【问题讨论】:

    标签: spring-boot dto mapstruct


    【解决方案1】:

    您可以将上下文注入映射器调用并定义@AfterMapping。

    @Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.ERROR)
    public interface UserPOMapper {
        UserDTO toUserDTO(UserPO userPo);
        
        @Mapping(target = "id", ignore = true)
        UserPO fromUserDTO(UserDTO userDto);
        
        @AfterMapping
        default void after(@MappingTarget UserDTO.UserDTOBuilder u, @Context String url) {
            u.firstName(url);
        }
        
        UserDTO toUserDTOWithDetails(UserPO userPO, @Context String url);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-05
      • 2018-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-14
      相关资源
      最近更新 更多