MapStruct快速入门使用

1.MapStruct快速入门使用

官网地址:http://mapstruct.org/

MapStruct是一个代码生成器,它基于约定优于配置的方法极大地简化了Java bean类型之间映射的实现。
所以映射指的就是从一个实体变化成一个实体。例如我们在实际开发中,DAO层的实体和一些数据传输对象
(DTO),大部分属性都是相同的,只有少部分的不同,通过mapStruct,可以让不同实体之间的转换变的
简单。
2.引入Maven坐标

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

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

<build>
	<plugins>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-compiler-plugin</artifactId>
			<version>3.8.1</version>
			<configuration>
				<source>1.8</source> <!-- depending on your project -->
				<target>1.8</target> <!-- depending on your project -->
				<annotationProcessorPaths>
					<path>
						<groupId>org.mapstruct</groupId>
						<artifactId>mapstruct-processor</artifactId>
						<version>${org.mapstruct.version}</version>
					</path>
					<!-- other annotation processors -->
				</annotationProcessorPaths>
			</configuration>
		</plugin>
	</plugins>
</build>
3.定义两个实体

public class User {
	
	private String userName;
	
	private Integer age;
	
	private String mailbox;
	
	private String hobby;
    //GET SET ...
}

public class UserDto {

	private String userName;
	
	private String age;
	
	private String mail;
	
	private String hobbyDto;
    //GET SET ...
}

如果我们想要把User对象转换成UserDto对象,就会发现其中age类型不同,并且mailbox与mail和
hobby与hobbyDto名称不同。那么我们需要借助第三方工具或者手动编码完成,在这里我们使用
MapStruct
4.Mapper接口

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;

import com.example.demo.dto.UserDto;
import com.example.demo.entity.User;

@Mapper
public interface UserToUserDtoMapper {
	
	//声明成员变量INSTANCE,从而让客户端可以访问Mapper接口的实现。
	UserToUserDtoMapper INSTANCE = Mappers.getMapper( UserToUserDtoMapper.class );
	
    @Mappings({
    	@Mapping(source = "mailbox",target = "mail"),
    	@Mapping(source = "hobby",target = "hobbyDto")
    })
	UserDto userToUserDto(User user);
}


1、@Mapper注解标记这个接口作为一个映射接口,并且是编译时MapStruct处理器的入口。

2、真正实现映射的方法需要源对象作为参数,并返回目标对象。映射方法的名字是随意的。对于在源
对象和目标对象中,属性名字不同的情况,可以通过@Mapping注解来配置这些名字。

3、MapStruct会自动转换不同类型,比如其中的Integer age和String age。

4、接口中会声明一个成员变量INSTANCE,从而让客户端可以访问Mapper接口的实现。



5.编译

MapStruct是以Java编译器插件的形式来处理注解,生成mapper接口的实现。因此在使用之前我们必须手
工的编译(IDE的自动编译功能不会使用到MapStruct这个插件功能)。

执行maven命令:mvn compile

可以看到在target目录来多个一个类UserToUserDtoMapperImpl.class



package com.example.demo.mapper;

import com.example.demo.dto.UserDto;
import com.example.demo.entity.User;
import javax.annotation.Generated;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2021-04-01T17:53:12+0800",
    comments = "version: 1.4.1.Final, compiler: javac, environment: Java 1.8.0_265 (AdoptOpenJDK)"
)
public class UserToUserDtoMapperImpl implements UserToUserDtoMapper {

    @Override
    public UserDto userToUserDto(User user) {
        if ( user == null ) {
            return null;
        }

        UserDto userDto = new UserDto();

        userDto.setMail( user.getMailbox() );
        userDto.setHobbyDto( user.getHobby() );
        userDto.setUserName( user.getUserName() );
        if ( user.getAge() != null ) {
            userDto.setAge( String.valueOf( user.getAge() ) );
        }

        return userDto;
    }
}

我们发现MapStruct生成的Mapper代理类底层还是才是的原始set方法完成赋值的,并且自动处理
了类型转换。
6.测试使用

@Test
void mapStructTest() {
	User user = new User();
	user.setUserName("张三");
	user.setAge(24);
	user.setHobby("打篮球");
	user.setMailbox("xxxx@test.com");
	UserDto userDto = UserToUserDtoMapper.INSTANCE.userToUserDto(user);
	logger.info("User转换UserDto===》"+userDto.toString());
}

输出:
User转换UserDto===》UserDto [userName=张三, age=24, mail=xxxx@test.com, hobbyDto=打
篮球]

2.@Mapper注解详解

1、@Mapper注解的componentModel属性

componentModel属性用于指定自动生成的接口实现类的组件类型。这个属性支持四个值:

default: 这是默认的情况,mapstruct不使用任何组件类型, 可以通过Mappers.getMapper(Class)
方式获取自动生成的实例对象。

cdi: the generated mapper is an application-scoped CDI bean and can be retrieved 
via @Inject

spring: 生成的实现类上面会自动添加一个@Component注解,可以通过Spring的 @Autowired方式进
行注入

jsr330: 生成的实现类上会添加@javax.inject.Named 和@Singleton注解,可以通过 @Inject注解
获取。

2.我们以spring组件方式进行验证

@Mapper(componentModel = "spring")
public interface UserToUserDtoMapper {
	
	//声明成员变量INSTANCE,从而让客户端可以访问Mapper接口的实现。
	UserToUserDtoMapper INSTANCE = Mappers.getMapper( UserToUserDtoMapper.class );
	
    @Mappings({
    	@Mapping(source = "mailbox",target = "mail"),
    	@Mapping(source = "hobby",target = "hobbyDto")
    })
	UserDto userToUserDto(User user);
}
3.需要注意的是,当指定组件模型为Spring的时候,我们在classpath下一定要引入spring的jar包,否则
MapStruct在编译的时候会报错。

现在再次执行"mvn compile",通过IDE反编译功能查看自动生成的Mapper实现类源码。

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2021-04-01T18:24:08+0800",
    comments = "version: 1.4.1.Final, compiler: javac, environment: Java 1.8.0_265 (AdoptOpenJDK)"
)
@Component
public class UserToUserDtoMapperImpl implements UserToUserDtoMapper {

    @Override
    public UserDto userToUserDto(User user) {
        if ( user == null ) {
            return null;
        }

        UserDto userDto = new UserDto();

        userDto.setMail( user.getMailbox() );
        userDto.setHobbyDto( user.getHobby() );
        userDto.setUserName( user.getUserName() );
        if ( user.getAge() != null ) {
            userDto.setAge( String.valueOf( user.getAge() ) );
        }

        return userDto;
    }
}
4.测试@Autowired注入

@RunWith(SpringRunner.class) 
@SpringBootTest
class SpringAopApplicationTests {
	
	Logger logger = LoggerFactory.getLogger(SpringAopApplicationTests.class);
		
	@Autowired
	UserToUserDtoMapper userToUserDtoMapper;

	@Test
	void mapStructTest() {
		User user = new User();
		user.setUserName("张三");
		user.setAge(24);
		user.setHobby("打篮球");
		user.setMailbox("xxxx@test.com");
		UserDto userDto = userToUserDtoMapper.userToUserDto(user);
		logger.info("User转换UserDto===》"+userDto.toString());
	}

}

输出:
User转换UserDto===》UserDto [userName=张三, age=24, mail=xxxx@test.com, hobbyDto=打
篮球]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值