代码之家  ›  专栏  ›  技术社区  ›  Zmur

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

  •  0
  • Zmur  · 技术社区  · 6 年前

    我有一个要映射的userdto和user实体。创建新用户时,某些字段(例如: password , modifiedBy )必须由某些自定义方法生成(例如: 密码 是随机生成和编码的,但是 被修改 用户名从安全服务中检索)。为此,我将一些服务自动连接到映射器中。很多人回来了 String 而mapstruct无法理解在每种情况下使用哪一个,只使用在接受的所有内容上找到的第一个 作为输入。

    @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 在任何接受 getPass(...) 方法根本没有使用。 但是我需要它来使用我的 GETPASS(…) 方法对 密码 仅字段。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Filip    6 年前

    当前无法将使用的映射器或服务传递给默认方法。有 mapstruct/mapstruct#1637 打开它。你也不能真的这么做 @Mapper( uses = PasswordEncoder.class ) 因为这会导致所有 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);
    }