From 182bc024daab34b619336594242017e38b55c56f Mon Sep 17 00:00:00 2001 From: linpeilie Date: Thu, 14 Mar 2024 20:25:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 131 +++++++++++++++++- example/pom.xml | 2 +- .../linpeilie/mapper/TreeNodeAwareMapper.java | 19 +++ .../io/github/linpeilie/model/Product.java | 1 + .../io/github/linpeilie/model/TreeNode.java | 18 +++ .../github/linpeilie/model/TreeNodeDto.java | 15 ++ .../AbstractAdapterMapperGenerator.java | 2 +- .../linpeilie/processor/ContextConstants.java | 5 + .../generator/AutoMapperGenerator.java | 2 + .../io/github/linpeilie/utils/ArrayUtil.java | 23 +++ pom.xml | 2 +- 11 files changed, 215 insertions(+), 5 deletions(-) create mode 100644 example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/mapper/TreeNodeAwareMapper.java create mode 100644 example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/TreeNode.java create mode 100644 example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/TreeNodeDto.java create mode 100644 mapstruct-plus/src/main/java/io/github/linpeilie/utils/ArrayUtil.java diff --git a/README.md b/README.md index 41fa218..34f15fb 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,135 @@ # mapstruct-plus +## What is MapStruct Plus + +MapStruct Plus is an enhancement to the MapStruct framework. It only does the enhancement, does not make the modification, and can automatically generate the transformation operation between two classes through an annotation, omitting the operation of defining the interface of MapStruct, makes Java type conversion easy and elegant. + +Goal: To be the simplest and most powerful type conversion tool + +**If this project helps you, hope to click a Star to encourage it!** + +## Link + +- [Document](https://mapstruct.plus) + +## Other open source projects + +- **EasyRelation**:[GitHub](https://github.com/linpeilie/easy-relation) | [Gitee](https://gitee.com/easii/easy-relation) | [Document](https://easy-relation.easii.cn) + +## Quick start + + +The following shows how to convert two objects using MapStructPlus. + +Suppose there are two classes, `UserDto` and `User`, representing the data-layer object and business-layer object, respectively: + +- `UserDto` + +```java +public class UserDto { + private String username; + private int age; + private boolean young; + + // getter、setter、toString、equals、hashCode +} +``` + +- `User` + +```java +public class User { + private String username; + private int age; + private boolean young; + + // getter、setter、toString、equals、hashCode +} +``` + +Introducing `mapstruct-plus-spring-boot-starter` dependencies: + +```xml + + latest version + + + + io.github.linpeilie + mapstruct-plus-spring-boot-starter + ${mapstruct-plus.version} + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + io.github.linpeilie + mapstruct-plus-processor + ${mapstruct-plus.version} + + + + + + +``` + +Test + +```java +@SpringBootTest +public class QuickStartTest { + + @Autowired + private Converter converter; + + @Test + public void test() { + User user = new User(); + user.setUsername("jack"); + user.setAge(23); + user.setYoung(false); + + UserDto userDto = converter.convert(user, UserDto.class); + System.out.println(userDto); // UserDto{username='jack', age=23, young=false} + + assert user.getUsername().equals(userDto.getUsername()); + assert user.getAge() == userDto.getAge(); + assert user.isYoung() == userDto.isYoung(); + + User newUser = converter.convert(userDto, User.class); + + System.out.println(newUser); // User{username='jack', age=23, young=false} + + assert user.getUsername().equals(newUser.getUsername()); + assert user.getAge() == newUser.getAge(); + assert user.isYoung() == newUser.isYoung(); + } + +} +``` + +## Summary + +With the introduction of dependencies, the steps to using MapStructPlus are very simple. + +1. Add an `AutoMapper` annotation to the class you want to convert +2. Get the `Converter` instance and call the convert method. + +-------- + + ## 这是什么? -Mapstruct Plus 是对 Mapstruct 框架的一个增强,只做增强,不做修改,可以通过一个注解,自动生成两个类之间的转换操作,省略了 Mapstruct 定义接口的操作,使 Java 类型转换更加便捷、优雅。 +MapStruct Plus 是对 MapStruct 框架的一个增强,只做增强,不做修改,可以通过一个注解,自动生成两个类之间的转换操作,省略了 Mapstruct 定义接口的操作,使 Java 类型转换更加便捷、优雅。 目标:做最简单、最强大的类型转换工具 @@ -61,7 +188,7 @@ public class User { ```xml - 1.3.4 + 1.4.0 diff --git a/example/pom.xml b/example/pom.xml index 4c9dbbd..40528de 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -18,7 +18,7 @@ UTF-8 1.5.1.Final - 1.3.7-SNAPSHOTS + 1.4.0 1.18.22 5.8.26 diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/mapper/TreeNodeAwareMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/mapper/TreeNodeAwareMapper.java new file mode 100644 index 0000000..5beab40 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/mapper/TreeNodeAwareMapper.java @@ -0,0 +1,19 @@ +package io.github.linpeilie.mapper; + +import io.github.linpeilie.model.TreeNode; +import java.util.List; +import org.mapstruct.Condition; +import org.mapstruct.Named; +import org.springframework.boot.context.properties.bind.Name; +import org.springframework.stereotype.Component; + +@Component +public class TreeNodeAwareMapper { + + @Condition + @Named("limitLeastTwo") + public boolean limitLeastTwo(List treeNodeList) { + return treeNodeList != null && treeNodeList.size() >= 2; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/Product.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/Product.java index fcd4eec..2c92172 100644 --- a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/Product.java +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/Product.java @@ -1,6 +1,7 @@ package io.github.linpeilie.model; import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; import java.util.List; import lombok.Data; import lombok.EqualsAndHashCode; diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/TreeNode.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/TreeNode.java new file mode 100644 index 0000000..71a2140 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/TreeNode.java @@ -0,0 +1,18 @@ +package io.github.linpeilie.model; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.mapper.TreeNodeAwareMapper; +import java.util.List; +import lombok.Data; + +@Data +@AutoMapper(target = TreeNodeDto.class, cycleAvoiding = true, uses = TreeNodeAwareMapper.class) +public class TreeNode { + + private TreeNode parent; + + @AutoMapping(conditionQualifiedByName = "limitLeastTwo") + private List children; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/TreeNodeDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/TreeNodeDto.java new file mode 100644 index 0000000..72fe752 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/TreeNodeDto.java @@ -0,0 +1,15 @@ +package io.github.linpeilie.model; + +import io.github.linpeilie.annotations.AutoMapper; +import java.util.List; +import lombok.Data; + +@Data +@AutoMapper(target = TreeNode.class, cycleAvoiding = true) +public class TreeNodeDto { + + private TreeNodeDto parent; + + private List children; + +} diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AbstractAdapterMapperGenerator.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AbstractAdapterMapperGenerator.java index 5715448..21b45ad 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AbstractAdapterMapperGenerator.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AbstractAdapterMapperGenerator.java @@ -189,7 +189,7 @@ public abstract class AbstractAdapterMapperGenerator { // default impl List defaultMethods = buildDefaultProxyMethod(adapterMethodMetadata, - ClassName.get("io.github.linpeilie.annotations", "DoIgnore")); + ClassName.get(ContextConstants.DoIgnore.packageName, ContextConstants.DoIgnore.className)); List methodSpecs = new ArrayList<>(defaultMethods); ParameterSpec parameterSpec = diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ContextConstants.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ContextConstants.java index 7d9eb4f..4c6fcc0 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ContextConstants.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ContextConstants.java @@ -104,4 +104,9 @@ public interface ContextConstants { String className = "MapObjectConvert"; } + interface DoIgnore { + String packageName = "io.github.linpeilie.annotations"; + String className = "DoIgnore"; + } + } diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java index b0dab69..2902e4a 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java @@ -11,6 +11,7 @@ import com.squareup.javapoet.TypeSpec; import io.github.linpeilie.processor.ContextConstants; import io.github.linpeilie.processor.metadata.AutoMapperMetadata; import io.github.linpeilie.processor.metadata.AutoMappingMetadata; +import io.github.linpeilie.utils.ArrayUtil; import io.github.linpeilie.utils.CollectionUtils; import io.github.linpeilie.utils.StrUtil; import java.io.IOException; @@ -114,6 +115,7 @@ public class AutoMapperGenerator { final MethodSpec.Builder methodSpecBuilder = MethodSpec.methodBuilder(methodName) .addParameters(parameterSpecs) .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) + .addAnnotation(ClassName.get(ContextConstants.DoIgnore.packageName, ContextConstants.DoIgnore.className)) .returns(target); if (CollectionUtils.isNotEmpty(autoMappingMetadataList)) { methodSpecBuilder.addAnnotations(buildMappingAnnotations(autoMappingMetadataList)); diff --git a/mapstruct-plus/src/main/java/io/github/linpeilie/utils/ArrayUtil.java b/mapstruct-plus/src/main/java/io/github/linpeilie/utils/ArrayUtil.java new file mode 100644 index 0000000..524ed57 --- /dev/null +++ b/mapstruct-plus/src/main/java/io/github/linpeilie/utils/ArrayUtil.java @@ -0,0 +1,23 @@ +package io.github.linpeilie.utils; + +import java.util.Arrays; +import java.util.stream.Collectors; + +public class ArrayUtil { + + public static boolean isNotEmpty(T[] arr) { + return arr != null && arr.length > 0; + } + + public static String join(T[] arr, CharSequence delimiter) { + return join(arr, delimiter, "", ""); + } + + public static String join(T[] arr, CharSequence delimiter, String prefix, String suffix) { + if (arr == null) { + return null; + } + return Arrays.stream(arr).map(str -> prefix + str + suffix).collect(Collectors.joining(delimiter)); + } + +} diff --git a/pom.xml b/pom.xml index c6c0fb1..ca1de3a 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ - 1.3.7-SNAPSHOTS + 1.4.0 8 8 UTF-8