【问题标题】:Force MapStruct to use custom method instead of dto value强制 MapStruct 使用自定义方法而不是 dto 值
【发布时间】:2019-01-21 09:04:34
【问题描述】:

我有一个要映射的 UserDTO 和 User 实体。创建新用户时,某些字段(例如:passwordmodifiedBy)必须通过某种自定义方法生成(例如:password 是随机生成和编码的,但modifiedBy 用户名是从安全服务中检索的) .为此,我将一些服务自动连接到映射器中。他们中的许多人返回String,而 MapStruct 无法理解在每种情况下使用哪一个,而只是使用它在所有接受 String 作为输入的东西上找到的第一个。

@Mapper(componentModel = "spring", uses = PasswordEncoder.class)
public interface UserMapper {

@Mapping(target = "password", qualifiedByName = "PASS")
User mapUser(UserDto dto);

@Named("PASS")
default String getPass(PasswordEncoder passwordEncoder){
    return passwordEncoder.encode(some_random_generator);
    }
}

这生成的代码只使用来自PasswordEncoder 的方法,在任何接受StringgetPass(...) 方法的setter 中根本不使用。 但是我需要它才能在 password 字段上使用我的 getPass(...) 方法。

【问题讨论】:

    标签: java spring-boot mapstruct


    【解决方案1】:

    目前无法将使用的映射器或服务传递给默认方法。有mapstruct/mapstruct#1637 为此开放。你也不能真正做到@Mapper( uses = PasswordEncoder.class ),因为这会导致所有StringString 都通过PasswordEncoder 映射。您可以做的是创建自己的自定义PasswordEncoderMapper 并在其上使用@Named,这样您就可以控制了。

    这可能看起来像这样:

    @Qualifier // org.mapstruct.Qualifier
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.CLASS)
    public @interface EncodedMapping {
    }
    
    public class PasswordEncoderMapper {
    
        protected final PasswordEncoder passwordEncoder;
    
        public PasswordEncoderMapper(PasswordEncoder passwordEncoder) {
            this.passwordEncoder = passwordEncoder;
        }
    
        @EncodedMapping
        public String encode(String value) {
            return passwordEncoder.encode(value);
        }
    }
    
    @Mapper(componentModel = "spring", uses = PasswordEncoderMapper.class)
    public interface UserMapper {
    
        @Mapping(target = "password", qualifiedBy = EncodedMapping.class)
        User mapUser(UserDto dto);
    }
    

    关于modifiedBy 属性。您应该将其作为@ObjectFactory 的一部分或使用表达式来完成。

    使用表达式可以如下所示:

    @Mapper(componentModel = "spring", uses = PasswordEncoderMapper.class, imports = SecurityUtils.class)
    public interface UserMapper {
    
        @Mapping(target = "password", qualifiedBy = EncodedMapping.class)
        @Mapping(target = "modifiedBy", expression = "java(SecurityUtils.getCurrentUserId())")
        User mapUser(UserDto dto);
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-24
      • 2016-08-09
      • 2016-02-06
      • 1970-01-01
      • 2021-01-15
      相关资源
      最近更新 更多