Java 8 @lombok和mapstruct的访问器(fluent=true)

Java 8 @lombok和mapstruct的访问器(fluent=true),java-8,lombok,mapstruct,Java 8,Lombok,Mapstruct,我有一个下游服务,我想将其bean映射到我的bean。但是使用mapstruct似乎有问题 来自下游服务的Pojo(其定义我无法更改) 我想把它转换成PojoB @Setter @Getter @ToString public class PojoB { private String stringB; private int integer; } 映射器接口 @Mapper public interface PojoMapper { PojoMapper INSTAN

我有一个下游服务,我想将其bean映射到我的bean。但是使用mapstruct似乎有问题

来自下游服务的Pojo(其定义我无法更改)

我想把它转换成PojoB

@Setter
@Getter
@ToString
public class PojoB {
    private String stringB;
    private int integer;
}
映射器接口

@Mapper
public interface PojoMapper {

    PojoMapper INSTANCE = Mappers.getMapper(PojoMapper.class);
    @Mapping(source = "stringA", target = "stringB")
    PojoB pojoAToPojoB(PojoA pojoA);
}
这会失败,因为它找不到getter,因为从getter中删除前缀,然后, 我知道mapstruct生成映射器接口的实现,并使用bean规范(即get和set前缀)


有没有办法克服这个问题?

如注释中所述,这可以通过编写一个自定义的
accessornamigstrategy
来实现,该策略将以流畅的访问器形式返回方法的名称

我已经编写了一个自定义生成器访问器(也可以应用于您的案例),您可以找到它

除此之外,还有一个针对MapStruct的开放PR,它增加了对构建器的支持,同时还增加了对流畅链接访问器的支持

您的定制策略(如PR中建议的)可以如下所示:

public class FluentAccessorNamingStrategy extends DefaultAccessorNamingStrategy {

    @Override
    public boolean isSetterMethod(ExecutableElement method) {
        String methodName = method.getSimpleName().toString();

        return methodName.startsWith( "set" ) && methodName.length() > 3 || isBuilderSetter( method );
    }

    protected boolean isBuilderSetter(ExecutableElement method) {
        return method.getParameters().size() == 1 &&
            !JAVA_JAVAX_PACKAGE.matcher( method.getEnclosingElement().asType().toString() ).matches() &&
            method.getReturnType().toString().equals( method.getEnclosingElement().asType().toString() );
    }

    @Override
    public String getPropertyName(ExecutableElement getterOrSetterMethod) {
        String methodName = getterOrSetterMethod.getSimpleName().toString();
        if ( methodName.startsWith( "is" ) || methodName.startsWith( "get" ) || methodName.startsWith( "set" ) ) {
            return Introspector.decapitalize( methodName.substring( methodName.startsWith( "is" ) ? 2 : 3 ) );
        }
        else if ( isBuilderSetter( getterOrSetterMethod ) ) {
            return methodName;
        }
        return Introspector.decapitalize( methodName.substring( methodName.startsWith( "is" ) ? 2 : 3 ) );
    }
}
注:这对流利的接受者有效,你需要做一些额外的事情来让它对流利的接受者有效。基于返回类型的
meethod.getEnclosuringElement()
,您需要获取属性的
访问器
注释检查并返回方法的名称,否则需要使用默认值


免责声明:我是MapStruct团队的成员之一

您需要手动指定mappings@DarrenForsythe请详细说明一下。手动,你的意思是,我必须写一个方法来来回转换对象吗?事实上,刚刚发现Mapstruct可以处理你的确切示例,文档说它可以,但它不能。我也有同样的问题,但我一直无法解决。我也需要帮助。我没有时间实现这一点,因为我陷入了另一个问题(),现在我正在重新考虑是否应该使用mapstruct,因为它给我带来了Lombok方面的困难,我肯定会检查这一点,并标记为正确,如果这一点有效。mapstruct与Lombok一起工作,您需要检查您的设置是否正确。如果使用的是
annotationProcessorPaths
,则需要在其中同时指定MapStruct和Lombok。确保您使用的是两个框架的最新版本和maven编译器插件的最新版本
public class FluentAccessorNamingStrategy extends DefaultAccessorNamingStrategy {

    @Override
    public boolean isSetterMethod(ExecutableElement method) {
        String methodName = method.getSimpleName().toString();

        return methodName.startsWith( "set" ) && methodName.length() > 3 || isBuilderSetter( method );
    }

    protected boolean isBuilderSetter(ExecutableElement method) {
        return method.getParameters().size() == 1 &&
            !JAVA_JAVAX_PACKAGE.matcher( method.getEnclosingElement().asType().toString() ).matches() &&
            method.getReturnType().toString().equals( method.getEnclosingElement().asType().toString() );
    }

    @Override
    public String getPropertyName(ExecutableElement getterOrSetterMethod) {
        String methodName = getterOrSetterMethod.getSimpleName().toString();
        if ( methodName.startsWith( "is" ) || methodName.startsWith( "get" ) || methodName.startsWith( "set" ) ) {
            return Introspector.decapitalize( methodName.substring( methodName.startsWith( "is" ) ? 2 : 3 ) );
        }
        else if ( isBuilderSetter( getterOrSetterMethod ) ) {
            return methodName;
        }
        return Introspector.decapitalize( methodName.substring( methodName.startsWith( "is" ) ? 2 : 3 ) );
    }
}