javaweb
javaweb copied to clipboard
MapStruct
在mvc层经常会遇到这样的一种情况,是否使用DTO(数据传输对象),还是直接使用model返回?其实这都可以,前者叫封闭领域模型风格,后者叫开放领域模型风格。因为前者可以排除一些不需要返回的字段但是需要进行拷贝,后者就不需要经过处理。另外,都会遭遇到一种情况:如性别在后台是通过0和1,但是需要返回前端男或者女。这种情况可以使用数据字典做一个良好的处理,这个这里不谈。 MapStruct可以很好的处理封闭领域模型风格的model到DTO的拷贝。 https://github.com/mapstruct/mapstruct
public class CycleAvoidingMappingContext {
private Map<Object, Object> knownInstances = new IdentityHashMap<Object, Object>();
@BeforeMapping
public <T> T getMappedInstance(Object source, @TargetType Class<T> targetType) {
return (T) knownInstances.get( source );
}
@BeforeMapping
public void storeMappedInstance(Object source, @MappingTarget Object target) {
knownInstances.put( source, target );
}
public class Car {
private String make;
private int numberOfSeats;
private CarType type;
private List<Car> team;
//constructor, getters, setters etc.
}
public class CarDto {
private String make;
private int seatCount;
private String type;
private List<CarDto> team;
//constructor, getters, setters etc.
}
@Mapper
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
@Mappings( {
@Mapping(source = "numberOfSeats", target = "seatCount")
} )
CarDto carToCarDto(Car car, @Context CycleAvoidingMappingContext context);
@InheritInverseConfiguration
Car fromCar(CarDto carDto, @Context CycleAvoidingMappingContext context);
}
@Test
public void shouldMapCarToDto() {
//given
Car car = new Car( "Morris", 5, CarType.SEDAN );
//when
CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
//then
assertThat( carDto ).isNotNull();
assertThat( carDto.getMake() ).isEqualTo( "Morris" );
assertThat( carDto.getSeatCount() ).isEqualTo( 5 );
assertThat( carDto.getType() ).isEqualTo( "SEDAN" );
}
使用CDI组件,将会标记为 @ApplicationScoped
@Mapper(componentModel = "cdi")
public interface CarMapper {
CarDto carToCarDto(Car car);
}
@Inject
private CarMapper mapper
@Mapper
public interface CarMapper {
@Mapping(source = "price", numberFormat = "$#.00")
CarDto carToCarDto(Car car);
@IterableMapping(numberFormat = "$#.00")
List<String> prices(List<Integer> prices);
}
@Mapper
public interface AddressMapper {
@Mappings({
@Mapping(source = "person.description", target = "description"),
@Mapping(source = "address.houseNo", target = "houseNumber")
})
DeliveryAddressDto personAndAddressToDeliveryAddressDto(Person person, Address
address);
}
更复杂一点:
@Mapper(componentModel = "spring",uses = MappingUtil.class)
public abstract class ClueViewMapper {
@BeforeMapping
protected void flushEntity(ClueSearchView clueSearchView){
//对clueSearchView预处理
}
@Mappings({
@Mapping(source = "model_code",target = "modelName",qualifiedBy = MappingUtil.ModelName.class),
@Mapping(source = "belonged_seller_id",target = "belongedSellerId"),
@Mapping(target = "lastFollowText",ignore = true),
})
public abstract ClueView map(ClueSearchView clueSearchView);
public abstract List<ClueView> map(List<ClueSearchView> clueSearchView);
}
@Mapper(componentModel = "spring")
public class MappingUtil {
@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface ModelName {
}
@ModelName
public String getModelName(String modelCode){
...
}
}
使用
@Autowired
private ClueViewMapper clueViewMapper;
...
clueView = clueViewMapper.map(searchView);
JDK1.7以及以下
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
<version>1.1.0.Final</version>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source> <!-- or higher, depending on your project -->
<target>1.8</target> <!-- or higher, depending on your project -->
<encoding>${project.encoding}</encoding>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.1.0.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
JDK1.8版本
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
<version>1.1.0.Final</version>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source> <!-- or higher, depending on your project -->
<target>1.8</target> <!-- or higher, depending on your project -->
<encoding>${project.encoding}</encoding>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.1.0.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
JDK1.8+lombok
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
<scope>provided</scope>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.encoding}</encoding>
</configuration>
</plugin>