javaweb icon indicating copy to clipboard operation
javaweb copied to clipboard

MapStruct

Open www1350 opened this issue 7 years ago • 0 comments

在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>

www1350 avatar May 16 '17 11:05 www1350