强制 MapStruct 使用自定义方法而不是 dto 值
Force MapStruct to use custom method instead of dto value
我有一个要映射的 UserDTO 和用户实体。创建新用户时,某些字段(例如:password
、modifiedBy
)必须通过某种自定义方法生成(例如:password
是随机生成和编码的,但 modifiedBy
用户名是从安全服务中检索到的)。为此,我将一些服务自动连接到映射器中。其中许多 return 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);
}
}
这生成的代码仅在接受 String
的任何 setter 中使用来自 PasswordEncoder
的方法,根本不使用 getPass(...)
方法。
但是我需要它来仅在 password
字段上使用我的 getPass(...)
方法。
目前无法将使用的映射器或服务传递给默认方法。有 mapstruct/mapstruct#1637 开放。此外,您不能真正执行 @Mapper( uses = PasswordEncoder.class )
,因为这会导致所有 String
到 String
都通过 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);
}
我有一个要映射的 UserDTO 和用户实体。创建新用户时,某些字段(例如:password
、modifiedBy
)必须通过某种自定义方法生成(例如:password
是随机生成和编码的,但 modifiedBy
用户名是从安全服务中检索到的)。为此,我将一些服务自动连接到映射器中。其中许多 return 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);
}
}
这生成的代码仅在接受 String
的任何 setter 中使用来自 PasswordEncoder
的方法,根本不使用 getPass(...)
方法。
但是我需要它来仅在 password
字段上使用我的 getPass(...)
方法。
目前无法将使用的映射器或服务传递给默认方法。有 mapstruct/mapstruct#1637 开放。此外,您不能真正执行 @Mapper( uses = PasswordEncoder.class )
,因为这会导致所有 String
到 String
都通过 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);
}