diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/io/github/linpeilie/BaseCycleAvoidingMapper.java b/ruoyi-common/ruoyi-common-core/src/main/java/io/github/linpeilie/BaseCycleAvoidingMapper.java new file mode 100644 index 000000000..d18d67fd4 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/io/github/linpeilie/BaseCycleAvoidingMapper.java @@ -0,0 +1,66 @@ +package io.github.linpeilie; + +import org.mapstruct.Context; +import org.mapstruct.MappingTarget; + +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public interface BaseCycleAvoidingMapper extends BaseMapper { + + T convert(S source, @Context CycleAvoidingMappingContext context); + + default T convert(S source, @Context CycleAvoidingMappingContext context, Consumer beanConsumer) { + T bean = convert(source,context); + if (Objects.nonNull(bean) && Objects.nonNull(beanConsumer)) { + beanConsumer.accept(bean); + } + return bean; + } + + T convert(S source, @MappingTarget T target, @Context CycleAvoidingMappingContext context); + + default T convert(S source, @MappingTarget T target, @Context CycleAvoidingMappingContext context, Consumer beanConsumer) { + T bean = convert(source,target,context); + if (Objects.nonNull(bean) && Objects.nonNull(beanConsumer)) { + beanConsumer.accept(bean); + } + return bean; + } + + default List convert(List sourceList, @Context CycleAvoidingMappingContext context) { + return sourceList.stream() + .map(item -> convert(item, context)) + .collect(Collectors.toList()); + } + + default List convert(List sourceList, @Context CycleAvoidingMappingContext context, Consumer beanConsumer) { + // 如果 beanConsumer 本来就为 null,则不再调用带 Consumer 参数的 convert 方法,避免在循环中进行不必要的非空判断 + if (Objects.nonNull(beanConsumer)) { + return sourceList.stream() + .map(source -> convert(source, beanConsumer)) + .collect(Collectors.toList()); + } + return sourceList.stream() + .map(item -> convert(item, context)) + .collect(Collectors.toList()); + } + + @Override + default T convert(S source) { + return convert(source, new CycleAvoidingMappingContext()); + } + + @Override + default T convert(S source, @MappingTarget T target) { + return convert(source, new CycleAvoidingMappingContext()); + } + + @Override + default List convert(List sourceList) { + return convert(sourceList, new CycleAvoidingMappingContext()); + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/io/github/linpeilie/BaseMapMapper.java b/ruoyi-common/ruoyi-common-core/src/main/java/io/github/linpeilie/BaseMapMapper.java new file mode 100644 index 000000000..2c2511ae3 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/io/github/linpeilie/BaseMapMapper.java @@ -0,0 +1,19 @@ +package io.github.linpeilie; + +import java.util.Map; +import java.util.Objects; +import java.util.function.Consumer; + +public interface BaseMapMapper { + + T convert(Map map); + + default T convert(Map map, Consumer beanConsumer) { + T bean = convert(map); + if (Objects.nonNull(bean) && Objects.nonNull(beanConsumer)) { + beanConsumer.accept(bean); + } + return bean; + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/io/github/linpeilie/BaseMapper.java b/ruoyi-common/ruoyi-common-core/src/main/java/io/github/linpeilie/BaseMapper.java new file mode 100644 index 000000000..3172bea71 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/io/github/linpeilie/BaseMapper.java @@ -0,0 +1,53 @@ +package io.github.linpeilie; + +import io.github.linpeilie.utils.CollectionUtils; +import org.mapstruct.MappingTarget; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public interface BaseMapper { + + T convert(S source); + + default T convert(S source, Consumer beanConsumer) { + T bean = convert(source); + if (Objects.nonNull(bean) && Objects.nonNull(beanConsumer)) { + beanConsumer.accept(bean); + } + return bean; + } + + T convert(S source, @MappingTarget T target); + + default T convert(S source, @MappingTarget T target, Consumer beanConsumer) { + T bean = convert(source,target); + if (Objects.nonNull(bean) && Objects.nonNull(beanConsumer)) { + beanConsumer.accept(bean); + } + return bean; + } + + default List convert(List sourceList) { + return convert(sourceList, null); + } + + default List convert(List sourceList, Consumer beanConsumer) { + if (CollectionUtils.isEmpty(sourceList)) { + return new ArrayList<>(); + } + // 如果 beanConsumer 本来就为 null,则不再调用带 Consumer 参数的 convert 方法,避免在循环中进行不必要的非空判断 + if (Objects.nonNull(beanConsumer)) { + return sourceList.stream() + .map(source -> convert(source, beanConsumer)) + .collect(Collectors.toList()); + } + return sourceList.stream() + .map(this::convert) + .collect(Collectors.toList()); + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/io/github/linpeilie/Converter.java b/ruoyi-common/ruoyi-common-core/src/main/java/io/github/linpeilie/Converter.java new file mode 100644 index 000000000..aa7b86145 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/io/github/linpeilie/Converter.java @@ -0,0 +1,130 @@ +package io.github.linpeilie; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Consumer; + +public class Converter { + + private final ConverterFactory converterFactory; + + public Converter() { + this.converterFactory = new DefaultConverterFactory(); + } + + public Converter(final ConverterFactory converterFactory) { + this.converterFactory = converterFactory; + } + + public T convert(S source, Class targetType) { + return convert(source, targetType, (Consumer) null); + } + + @SuppressWarnings("unchecked") + public T convert(S source, Class targetType, Consumer beanConsumer) { + if (source == null) { + return null; + } + BaseMapper mapper = (BaseMapper) converterFactory.getMapper(source.getClass(), targetType); + if (mapper != null) { + return mapper.convert(source, beanConsumer); + } + throw new ConvertException( + "cannot find converter from " + source.getClass().getSimpleName() + " to " + targetType.getSimpleName()); + } + + public T convert(S source, T target) { + return convert(source, target, null); + } + + @SuppressWarnings("unchecked") + public T convert(S source, T target, Consumer beanConsumer) { + if (source == null) { + return null; + } + if (target == null) { + return null; + } + Class sourceClass = source.getClass(); + BaseMapper mapper = (BaseMapper) converterFactory.getMapper(sourceClass, target.getClass()); + if (mapper != null) { + return mapper.convert(source, target, beanConsumer); + } + throw new ConvertException("cannot find converter from " + sourceClass.getSimpleName() + " to " + + target.getClass().getSimpleName()); + } + + public List convert(List sourceList, Class targetType) { + return convert(sourceList, targetType, (Consumer) null); + } + + @SuppressWarnings("unchecked") + public List convert(List sourceList, Class targetType, Consumer beanConsumer) { + if (sourceList == null || sourceList.isEmpty()) { + return new ArrayList<>(); + } + Class sourceType = sourceList.getFirst().getClass(); + BaseMapper mapper = (BaseMapper) converterFactory.getMapper(sourceType, targetType); + if (mapper != null) { + return mapper.convert(sourceList, beanConsumer); + } + throw new ConvertException("cannot find converter from " + sourceType.getSimpleName() + " to " + + targetType.getSimpleName()); + } + + public T convert(S source, Class target, CycleAvoidingMappingContext context) { + return convert(source, target, context, null); + } + + @SuppressWarnings("unchecked") + public T convert(S source, Class targetType, CycleAvoidingMappingContext context, Consumer beanConsumer) { + if (source == null) { + return null; + } + BaseCycleAvoidingMapper mapper = (BaseCycleAvoidingMapper) converterFactory.getCycleAvoidingMapper(source.getClass(), targetType); + if (mapper != null) { + return mapper.convert(source, context, beanConsumer); + } + throw new ConvertException("cannot find converter from " + source.getClass().getSimpleName() + " to " + + targetType.getSimpleName()); + } + + public List convert(List sourceList, Class targetType, CycleAvoidingMappingContext context) { + return convert(sourceList, targetType, context, null); + } + + @SuppressWarnings("unchecked") + public List convert(List sourceList, Class targetType, CycleAvoidingMappingContext context, Consumer beanConsumer) { + if (sourceList == null || sourceList.isEmpty()) { + return new ArrayList<>(); + } + Class sourceType = sourceList.getFirst().getClass(); + BaseCycleAvoidingMapper mapper = (BaseCycleAvoidingMapper) converterFactory.getCycleAvoidingMapper(sourceType, targetType); + if (mapper != null) { + return mapper.convert(sourceList, context, beanConsumer); + } + throw new ConvertException("cannot find converter from " + sourceType.getSimpleName() + " to " + targetType.getSimpleName()); + } + + public T convert(Map map, Class targetType) { + return convert(map, targetType, (Consumer) null); + } + + public T convert(Map map, Class targetType, Consumer beanConsumer) { + if (map == null || map.isEmpty()) { + return null; + } + if (map.values().stream().allMatch(Objects::isNull)) { + return null; + } + final BaseMapMapper mapper = converterFactory.getMapMapper(targetType); + if (mapper != null) { + return mapper.convert(map, beanConsumer); + } + throw new ConvertException("cannot find converter from " + map.getClass().getName() + " to " + + targetType.getSimpleName()); + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/MapstructUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/MapstructUtils.java index b6acff7b8..07357d819 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/MapstructUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/MapstructUtils.java @@ -9,12 +9,12 @@ import lombok.NoArgsConstructor; import java.util.List; import java.util.Map; +import java.util.function.Consumer; /** * Mapstruct 工具类 *

参考文档:mapstruct-plus

* - * * @author Michelle.Chung */ @NoArgsConstructor(access = AccessLevel.PRIVATE) @@ -23,54 +23,90 @@ public class MapstructUtils { private final static Converter CONVERTER = SpringUtils.getBean(Converter.class); /** - * 将 T 类型对象,转换为 desc 类型的对象并返回 + * 将 T 类型对象,转换为 target 类型的对象并返回 * - * @param source 数据来源实体 - * @param desc 描述对象 转换后的对象 - * @return desc + * @param source 数据来源实体 + * @param targetType 目标类型 转换后的对象类型 + * @return target */ - public static V convert(T source, Class desc) { - if (ObjectUtil.isNull(source)) { + public static V convert(T source, Class targetType) { + if (ObjectUtil.hasNull(source, targetType)) { return null; } - if (ObjectUtil.isNull(desc)) { - return null; - } - return CONVERTER.convert(source, desc); + return CONVERTER.convert(source, targetType); } /** - * 将 T 类型对象,按照配置的映射字段规则,给 desc 类型的对象赋值并返回 desc 对象 + * 将 T 类型对象,转换为 target 类型的对象并返回 * - * @param source 数据来源实体 - * @param desc 转换后的对象 - * @return desc + * @param source 数据来源实体 + * @param targetType 目标类型 转换后的对象类型 + * @param beanConsumer bean消费者 对象转换后进行一些属性设置 + * @return target */ - public static V convert(T source, V desc) { - if (ObjectUtil.isNull(source)) { + public static V convert(T source, Class targetType, Consumer beanConsumer) { + if (ObjectUtil.hasNull(source, targetType)) { return null; } - if (ObjectUtil.isNull(desc)) { - return null; - } - return CONVERTER.convert(source, desc); + return CONVERTER.convert(source, targetType, beanConsumer); } /** - * 将 T 类型的集合,转换为 desc 类型的集合并返回 + * 将 T 类型对象,按照配置的映射字段规则,给 target 类型的对象赋值并返回 target 对象 + * + * @param source 数据来源实体 + * @param target 目标对象 转换后的对象 + * @return target + */ + public static V convert(T source, V target) { + if (ObjectUtil.hasNull(source)) { + return null; + } + return CONVERTER.convert(source, target); + } + + /** + * 将 T 类型对象,转换为 target 类型的对象并返回 + * + * @param source 数据来源实体 + * @param target 目标对象 转换后的对象 + * @param beanConsumer bean消费者 对象转换后进行一些属性设置 + * @return target + */ + public static V convert(T source, V target, Consumer beanConsumer) { + if (ObjectUtil.hasNull(source)) { + return null; + } + return CONVERTER.convert(source, target, beanConsumer); + } + + /** + * 将 T 类型的集合,转换为 target 类型的集合并返回 * * @param sourceList 数据来源实体列表 - * @param desc 描述对象 转换后的对象 - * @return desc + * @param targetType 目标类型 转换后的对象类型 + * @return targetType */ - public static List convert(List sourceList, Class desc) { - if (ObjectUtil.isNull(sourceList)) { - return null; - } + public static List convert(List sourceList, Class targetType) { if (CollUtil.isEmpty(sourceList)) { return CollUtil.newArrayList(); } - return CONVERTER.convert(sourceList, desc); + return CONVERTER.convert(sourceList, targetType); + } + + /** + * 将 T 类型的集合,转换为 target 类型的集合并返回 + * + * @param sourceList 数据来源实体列表 + * @param targetType 目标类型 转换后的对象类型 + * @param beanConsumer bean消费者 对象转换后进行一些属性设置 + * @return targetType + */ + public static List convert(List sourceList, Class targetType, Consumer beanConsumer) { + if (CollUtil.isEmpty(sourceList)) { + return CollUtil.newArrayList(); + } + return CONVERTER.convert(sourceList, targetType, beanConsumer); } /** @@ -81,13 +117,25 @@ public class MapstructUtils { * @return bean对象 */ public static T convert(Map map, Class beanClass) { - if (MapUtil.isEmpty(map)) { - return null; - } - if (ObjectUtil.isNull(beanClass)) { + if (MapUtil.isEmpty(map) || ObjectUtil.isNull(beanClass)) { return null; } return CONVERTER.convert(map, beanClass); } -} + /** + * 将 Map 转换为 beanClass 类型的集合并返回 + * + * @param map 数据来源 + * @param beanClass bean类 + * @param beanConsumer bean消费者 对象转换后进行一些属性设置 + * @return bean对象 + */ + public static T convert(Map map, Class beanClass, Consumer beanConsumer) { + if (MapUtil.isEmpty(map) || ObjectUtil.isNull(beanClass)) { + return null; + } + return CONVERTER.convert(map, beanClass, beanConsumer); + } + +} \ No newline at end of file