美文网首页
Java对象转换框架(selma、mapstruct)

Java对象转换框架(selma、mapstruct)

作者: TinyThing | 来源:发表于2020-12-25 14:14 被阅读0次

0x0 背景

项目中经常会进行对象转换,以往常使用Spring框架的BeanUtils,但是这个工具基于反射,性能较差;因此有些通过编译时生成转换类的工具出现了,例如:Selma和mapstruct等。

0x1 Selma教程

官网:http://www.selma-java.org/
maven依赖:

        <!-- scope provided because the processor is only needed at compile time-->
        <dependency>
            <groupId>fr.xebia.extras</groupId>
            <artifactId>selma-processor</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- This is the only real dependency you will have in your binaries -->
        <dependency>
            <groupId>fr.xebia.extras</groupId>
            <artifactId>selma</artifactId>
            <version>1.0</version>
        </dependency>

使用demo:

//定义一个pojo类User
@Data
@Accessors(chain = true)
public class User {
    private Long id;
    private String username;
    private Integer age;
    private String address;
    private String email;
}

//定义对应的dto,注意,二者有个别字段不同
@Data
public class UserDto {
    private Long id;
    private String username;
    private Integer age;
    private String address;
    private String nickname;
}

定义一个工具类接口
注意这里的IgnoreMissing.ALL是指忽略转换时不一致的字段
例如user有email,而userDto没有该字段

@Mapper(withIgnoreMissing = IgnoreMissing.ALL)
public interface ConvertUtils {
    ConvertUtils INSTANCE = Selma.builder(ConvertUtils.class).build();

    UserDto convertToUserDto(User user);
    User convertToUser(UserDto userDto);
}

接下来编译后会发现,selma帮我们生成了一个实现类,如下:


public final class ConvertUtilsSelmaGeneratedClass implements ConvertUtils {
    public final UserDto convertToUserDto(User inUser) {
        UserDto out = null;
        if (inUser != null) {
            out = new UserDto();
            out.setAddress(inUser.getAddress());
            out.setAge(inUser.getAge());
            out.setId(inUser.getId());
            out.setUsername(inUser.getUsername());
        }

        return out;
    }

    public final User convertToUser(UserDto inUserDto) {
        User out = null;
        if (inUserDto != null) {
            out = new User();
            out.setAddress(inUserDto.getAddress());
            out.setAge(inUserDto.getAge());
            out.setId(inUserDto.getId());
            out.setUsername(inUserDto.getUsername());
        }

        return out;
    }

    public ConvertUtilsSelmaGeneratedClass() {
    }
}

使用方法:

    public static void main(String[] args) {
        User user = new User().setUsername("AAA")
                .setId(3423423L)
                .setAge(23)
                .setEmail("sdfsdf@qew.com")
                .setAddress("asdfasdfasdfasd");

        UserDto userDto = ConvertUtils.INSTANCE.convertToUserDto(user);
        System.out.println(userDto);

        System.out.println(ConvertUtils.INSTANCE.convertToUser(userDto));
    }

对于某些字段需要转换的情况,可以使用类似如下的注解:

    @Maps(withCustomFields = {
            @Field({"Proposal.passenger.age", "ProposalDto.passengerAge"}), 
            @Field({"passenger.card", "passengerCard"}),
            @Field({"Proposal.passenger.date", "ProposalDto.passengerDate"})
    })
    ProposalDto asProposalDto(Proposal proposal);

0x3 MapStruct教程

同selma类似,maven依赖如下:

        <org.mapstruct.version>1.4.1.Final</org.mapstruct.version>


        <!-- mapstruct -->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${org.mapstruct.version}</version>
            <!-- IntelliJ does not pick up the processor if it is not in the dependencies.
             There is already an open issue for IntelliJ see https://youtrack.jetbrains.com/issue/IDEA-150621
            -->
            <scope>provided</scope>
        </dependency>

和selma相同,mapstruct需要定义一个接口:

@Mapper
public interface MapStructConverter {

    MapStructConverter MAPPER = Mappers.getMapper(MapStructConverter.class);

    UserDto convertToUserDto(User user);
    User convertToUser(UserDto userDto);
}

编译后,会生成一个实现类,如下:

public class MapStructConverterImpl implements MapStructConverter {
    public MapStructConverterImpl() {
    }

    public UserDto convertToUserDto(User user) {
        if (user == null) {
            return null;
        } else {
            UserDto userDto = new UserDto();
            userDto.setId(user.getId());
            userDto.setUsername(user.getUsername());
            userDto.setAge(user.getAge());
            userDto.setAddress(user.getAddress());
            return userDto;
        }
    }

    public User convertToUser(UserDto userDto) {
        if (userDto == null) {
            return null;
        } else {
            User user = new User();
            user.setId(userDto.getId());
            user.setUsername(userDto.getUsername());
            user.setAge(userDto.getAge());
            user.setAddress(userDto.getAddress());
            return user;
        }
    }
}

类似的,如果需要自定义字段映射,采用如下方法:

    @Mapping(source = "orders", target = "orderItems")
    @Mapping(source = "customerName", target = "name")
    Customer toCustomer(CustomerDto customerDto);

相关文章

网友评论

      本文标题:Java对象转换框架(selma、mapstruct)

      本文链接:https://www.haomeiwen.com/subject/tdobnktx.html