强制MapStruct使用自定义方法而不是dto值

时间:2019-01-21 09:04:34

标签: java spring-boot mapstruct

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

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的设置方法中的方法的代码,而根本不使用String方法。 但是,我只需要在getPass(...)字段上使用我的getPass(...)方法。

1 个答案:

答案 0 :(得分: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);
}