如何在将 DTO 发送到客户端之前添加自定义逻辑?
how to add custom logic before sending DTO to client side?
这可能是一个非常简单的问题,但在解决给定问题时我很迷茫。
我有一个名为 MediaResource 的实体,它有 id、imageName 等字段,另一方面,有一个 MediaResourceDTO,它有 imageName、byte[] resourceFile 等
想法是从数据库中获取图像名称,在将 MediaResourceDTO 发送到客户端之前,我想将图像文件加载到 MediaResourceDTO 中。
我不知道如何从 MapStruct 实现这个。
我看过几个@Before 和@After 的例子,但我不明白它的用例。
这是我的源代码:
MediaResourceMapper
@Mapper(componentModel = "spring", uses = {VehicleMapper.class, })
public interface MediaResourceMapper {
MediaResourceDTO mediaResourceToMediaResourceDTO(MediaResource mediaResource);
List<MediaResourceDTO> mediaResourcesToMediaResourceDTOs(List<MediaResource> mediaResources);
MediaResource mediaResourceDTOToMediaResource(MediaResourceDTO mediaResourceDTO);
List<MediaResource> mediaResourceDTOsToMediaResources(List<MediaResourceDTO> mediaResourceDTOs);
default MediaResource mediaResourceFromId(Long id) {
if (id == null) {
return null;
}
MediaResource mediaResource = new MediaResource();
mediaResource.setId(id);
return mediaResource;
}
}
媒体资源实体
@Entity
@Table(name = "media_resource")
public class MediaResource implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "field_name")
private String fieldName;
@Column(name = "original_media_file_name")
private String originalMediaFileName;
@Column(name = "encrypted_media_file_name")
private String encryptedMediaFileName;
@Column(name = "resource_file_content_type", nullable = false)
private String resourceFileContentType;
}
MediaResourceDTO
public class MediaResourceDTO implements Serializable {
private Long id;
private String fieldName;
private String originalMediaFileName;
private String encryptedMediaFileName;
@NotNull
@Size(max = 20000000)
@Lob
private byte[] resourceFile;
private String resourceFileContentType;
//Some getter and setters
}
谢谢。
您可以 customize your mappings 通过提供装饰器。为此,您创建自己的 class 来实现映射器的接口并覆盖所需的映射方法:
public abstract class MediaResourceMapperDecorator implements MediaResourceMapper {
private final MediaResourceMapper delegate;
public MediaResourceMapperDecorator(MediaResourceMapper delegate) {
this.delegate = delegate;
}
@Override
MediaResourceDTO mediaResourceToMediaResourceDTO(MediaResource mediaResource) {
// Let MapStruct do the basic mapping:
final MediaResourceDTO dto = this.delegate.mediaResourceToMediaResourceDTO( mediaResource );
// Then load and add the file to the DTO:
dto.setResourceFile( loadMyFile( mediaResource.getOriginalMediaFileName() );
return dto;
}
}
然后你在映射器上使用 @DecoratedWith
注释来引用你的装饰器:
@Mapper(componentModel = "spring", uses = {VehicleMapper.class, })
@DecoratedWith(MediaResourceMapperDecorator.class)
public interface MediaResourceMapper {
...
您也可以通过告诉 MapStruct 它需要哪个服务来做到这一点,这样它就可以将 filename
映射到 resourceFile
,String
到 byte[]
。
您的服务API:
public interface FileLoader {
// @Named or some custom annotation annotated with @Qualifier can be
// used in order to make sure that this will only be applied to the specified mapping
@Named("fileMapper")
byte[] loadFile(String filename);
}
您的 Mapper 看起来像:
@Mapper(componentModel = "spring", uses = {VehicleMapper.class, FileLoader.class })
public interface MediaResourceMapper {
@Mapping(source = "originalMediaFileName", target = "resoruceFile", qualifiedByName = "fileMapper") // or qualifiedBy = CustomAnnotation.class
MediaResourceDTO mediaResourceToMediaResourceDTO(MediaResource mediaResource);
//The rest is the same
}
与装饰器相比,我个人更喜欢这种方法,因为您只有一个地方可以定义映射,而 MapStruct 将处理其余部分。
可以在参考文档中找到有关基于限定符的映射的更多信息here。
这可能是一个非常简单的问题,但在解决给定问题时我很迷茫。
我有一个名为 MediaResource 的实体,它有 id、imageName 等字段,另一方面,有一个 MediaResourceDTO,它有 imageName、byte[] resourceFile 等
想法是从数据库中获取图像名称,在将 MediaResourceDTO 发送到客户端之前,我想将图像文件加载到 MediaResourceDTO 中。
我不知道如何从 MapStruct 实现这个。
我看过几个@Before 和@After 的例子,但我不明白它的用例。
这是我的源代码: MediaResourceMapper
@Mapper(componentModel = "spring", uses = {VehicleMapper.class, })
public interface MediaResourceMapper {
MediaResourceDTO mediaResourceToMediaResourceDTO(MediaResource mediaResource);
List<MediaResourceDTO> mediaResourcesToMediaResourceDTOs(List<MediaResource> mediaResources);
MediaResource mediaResourceDTOToMediaResource(MediaResourceDTO mediaResourceDTO);
List<MediaResource> mediaResourceDTOsToMediaResources(List<MediaResourceDTO> mediaResourceDTOs);
default MediaResource mediaResourceFromId(Long id) {
if (id == null) {
return null;
}
MediaResource mediaResource = new MediaResource();
mediaResource.setId(id);
return mediaResource;
}
}
媒体资源实体
@Entity
@Table(name = "media_resource")
public class MediaResource implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "field_name")
private String fieldName;
@Column(name = "original_media_file_name")
private String originalMediaFileName;
@Column(name = "encrypted_media_file_name")
private String encryptedMediaFileName;
@Column(name = "resource_file_content_type", nullable = false)
private String resourceFileContentType;
}
MediaResourceDTO
public class MediaResourceDTO implements Serializable {
private Long id;
private String fieldName;
private String originalMediaFileName;
private String encryptedMediaFileName;
@NotNull
@Size(max = 20000000)
@Lob
private byte[] resourceFile;
private String resourceFileContentType;
//Some getter and setters
}
谢谢。
您可以 customize your mappings 通过提供装饰器。为此,您创建自己的 class 来实现映射器的接口并覆盖所需的映射方法:
public abstract class MediaResourceMapperDecorator implements MediaResourceMapper {
private final MediaResourceMapper delegate;
public MediaResourceMapperDecorator(MediaResourceMapper delegate) {
this.delegate = delegate;
}
@Override
MediaResourceDTO mediaResourceToMediaResourceDTO(MediaResource mediaResource) {
// Let MapStruct do the basic mapping:
final MediaResourceDTO dto = this.delegate.mediaResourceToMediaResourceDTO( mediaResource );
// Then load and add the file to the DTO:
dto.setResourceFile( loadMyFile( mediaResource.getOriginalMediaFileName() );
return dto;
}
}
然后你在映射器上使用 @DecoratedWith
注释来引用你的装饰器:
@Mapper(componentModel = "spring", uses = {VehicleMapper.class, })
@DecoratedWith(MediaResourceMapperDecorator.class)
public interface MediaResourceMapper {
...
您也可以通过告诉 MapStruct 它需要哪个服务来做到这一点,这样它就可以将 filename
映射到 resourceFile
,String
到 byte[]
。
您的服务API:
public interface FileLoader {
// @Named or some custom annotation annotated with @Qualifier can be
// used in order to make sure that this will only be applied to the specified mapping
@Named("fileMapper")
byte[] loadFile(String filename);
}
您的 Mapper 看起来像:
@Mapper(componentModel = "spring", uses = {VehicleMapper.class, FileLoader.class })
public interface MediaResourceMapper {
@Mapping(source = "originalMediaFileName", target = "resoruceFile", qualifiedByName = "fileMapper") // or qualifiedBy = CustomAnnotation.class
MediaResourceDTO mediaResourceToMediaResourceDTO(MediaResource mediaResource);
//The rest is the same
}
与装饰器相比,我个人更喜欢这种方法,因为您只有一个地方可以定义映射,而 MapStruct 将处理其余部分。
可以在参考文档中找到有关基于限定符的映射的更多信息here。