diff --git a/.dumirc.ts b/.dumirc.ts deleted file mode 100644 index 2f205ea..0000000 --- a/.dumirc.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineConfig } from 'dumi'; - -export default defineConfig({ - themeConfig: { - name: 'mapstruct-plus', - logo: false, - prefersColor: { default: 'auto' }, - github: 'https://github.com/linpeilie', - footer: false - }, - base: '/', - publicPath: '/', - sitemap: { hostname: 'https://mapstruct.plus' } -}); diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 0000000..c597126 --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,49 @@ + +name: 部署文档 + +on: + push: + branches: + # 确保这是你正在使用的分支名称 + - docs + # 手动触发部署 + workflow_dispatch: + +jobs: + deploy-gh-pages: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + # 如果你文档需要 Git 子模块,取消注释下一行 + # submodules: true + + + + - name: 设置 Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: npm + + - name: 安装依赖 + run: npm ci + + - name: 构建文档 + env: + NODE_OPTIONS: --max_old_space_size=8192 + run: |- + npm run docs:build + > docs/.vuepress/dist/.nojekyll + + - name: 部署文档 + uses: JamesIves/github-pages-deploy-action@v4 + with: + # 这是文档部署到的分支名称 + branch: gh-pages + folder: docs/.vuepress/dist + env: + # @see https://docs.github.com/cn/actions/reference/authentication-in-a-workflow#about-the-github_token-secret + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml deleted file mode 100644 index ffcff72..0000000 --- a/.github/workflows/gh-pages.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: github pages - -on: - push: - branches: - - main # default branch - -jobs: - deploy: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - run: npm install - # 文档编译命令,如果是 react 模板需要修改为 npm run docs:build - - run: npm run build - - name: Publish github pages - run: | - git config --global user.email "linpeilie@users.noreply.com" - git config --global user.name "linpeilie" - git remote set-url origin https://git:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git - npm run deploy -u "github-actions-bot " - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index cd6d409..947508e 100644 --- a/.gitignore +++ b/.gitignore @@ -45,4 +45,10 @@ package-lock.json dist .dumi/tmp -.dumi/tmp-production \ No newline at end of file +.dumi/tmp-production + + +node_modules/ +docs/.vuepress/.cache/ +docs/.vuepress/.temp/ +docs/.vuepress/dist/ \ No newline at end of file diff --git a/docs/.vuepress/config.ts b/docs/.vuepress/config.ts new file mode 100644 index 0000000..e92324b --- /dev/null +++ b/docs/.vuepress/config.ts @@ -0,0 +1,41 @@ +import {defineUserConfig} from "vuepress"; +import {shikiPlugin} from "@vuepress/plugin-shiki"; +import {searchPlugin} from "@vuepress/plugin-search"; +import theme from "./theme.js"; + +export default defineUserConfig({ + base: "/", + + head: [['script', {}, ` + + + `]], + + locales: { + "/": { + lang: "zh-CN", + title: "MapstructPlus", + description: "MapstructPlus指南", + }, + }, + + theme, + + plugins: [ + shikiPlugin({ + // theme: 'github-dark-dimmed' + theme: 'material-theme-darker' + }), + searchPlugin({ + isSearchable: (page) => page.path !== '/' + }) + ] +}); diff --git a/docs/.vuepress/navbar/index.ts b/docs/.vuepress/navbar/index.ts new file mode 100644 index 0000000..47f112e --- /dev/null +++ b/docs/.vuepress/navbar/index.ts @@ -0,0 +1 @@ +export * from "./zh.js"; diff --git a/docs/.vuepress/navbar/zh.ts b/docs/.vuepress/navbar/zh.ts new file mode 100644 index 0000000..7b04285 --- /dev/null +++ b/docs/.vuepress/navbar/zh.ts @@ -0,0 +1,8 @@ +import { navbar } from "vuepress-theme-hope"; + +export const zhNavbar = navbar([ + "/", + { text: "指南", icon: "discover", link: "/guide/class-convert" }, + { text: "更新日志", icon: "discover", link: "/release/log" } +]); + diff --git a/docs/.vuepress/public/assets/contact-me.png b/docs/.vuepress/public/assets/contact-me.png new file mode 100644 index 0000000..aa17cf8 Binary files /dev/null and b/docs/.vuepress/public/assets/contact-me.png differ diff --git a/docs/.vuepress/public/assets/icon/apple-icon-152.png b/docs/.vuepress/public/assets/icon/apple-icon-152.png new file mode 100644 index 0000000..434fcc3 Binary files /dev/null and b/docs/.vuepress/public/assets/icon/apple-icon-152.png differ diff --git a/docs/.vuepress/public/assets/icon/chrome-192.png b/docs/.vuepress/public/assets/icon/chrome-192.png new file mode 100644 index 0000000..6645f52 Binary files /dev/null and b/docs/.vuepress/public/assets/icon/chrome-192.png differ diff --git a/docs/.vuepress/public/assets/icon/chrome-512.png b/docs/.vuepress/public/assets/icon/chrome-512.png new file mode 100644 index 0000000..a146f00 Binary files /dev/null and b/docs/.vuepress/public/assets/icon/chrome-512.png differ diff --git a/docs/.vuepress/public/assets/icon/chrome-mask-192.png b/docs/.vuepress/public/assets/icon/chrome-mask-192.png new file mode 100644 index 0000000..530977a Binary files /dev/null and b/docs/.vuepress/public/assets/icon/chrome-mask-192.png differ diff --git a/docs/.vuepress/public/assets/icon/chrome-mask-512.png b/docs/.vuepress/public/assets/icon/chrome-mask-512.png new file mode 100644 index 0000000..a4f90ae Binary files /dev/null and b/docs/.vuepress/public/assets/icon/chrome-mask-512.png differ diff --git a/docs/.vuepress/public/assets/icon/guide-maskable.png b/docs/.vuepress/public/assets/icon/guide-maskable.png new file mode 100644 index 0000000..75449b6 Binary files /dev/null and b/docs/.vuepress/public/assets/icon/guide-maskable.png differ diff --git a/docs/.vuepress/public/assets/icon/ms-icon-144.png b/docs/.vuepress/public/assets/icon/ms-icon-144.png new file mode 100644 index 0000000..2464124 Binary files /dev/null and b/docs/.vuepress/public/assets/icon/ms-icon-144.png differ diff --git a/docs/.vuepress/public/favicon-bak.ico b/docs/.vuepress/public/favicon-bak.ico new file mode 100644 index 0000000..b411f79 Binary files /dev/null and b/docs/.vuepress/public/favicon-bak.ico differ diff --git a/docs/.vuepress/public/logo-bak.png b/docs/.vuepress/public/logo-bak.png new file mode 100644 index 0000000..ccd732e Binary files /dev/null and b/docs/.vuepress/public/logo-bak.png differ diff --git a/docs/.vuepress/public/logo-bak.svg b/docs/.vuepress/public/logo-bak.svg new file mode 100644 index 0000000..364d184 --- /dev/null +++ b/docs/.vuepress/public/logo-bak.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/sidebar/index.ts b/docs/.vuepress/sidebar/index.ts new file mode 100644 index 0000000..47f112e --- /dev/null +++ b/docs/.vuepress/sidebar/index.ts @@ -0,0 +1 @@ +export * from "./zh.js"; diff --git a/docs/.vuepress/sidebar/zh.ts b/docs/.vuepress/sidebar/zh.ts new file mode 100644 index 0000000..57c3390 --- /dev/null +++ b/docs/.vuepress/sidebar/zh.ts @@ -0,0 +1,23 @@ +import {sidebar} from "vuepress-theme-hope"; + +export const zhSidebar = sidebar({ + "/": [ + { + text: '介绍', + prefix: 'introduction/', + link: 'introduction/', + children: 'structure' + }, + { + text: "指南", + icon: "note", + prefix: "guide/", + children: "structure", + }, + { + text: '更新日志', + prefix: 'release/', + children: 'structure' + } + ], +}); diff --git a/docs/.vuepress/styles/config.scss b/docs/.vuepress/styles/config.scss new file mode 100644 index 0000000..f91061d --- /dev/null +++ b/docs/.vuepress/styles/config.scss @@ -0,0 +1,3 @@ +// you can change config here +$colors: #c0392b, #d35400, #f39c12, #27ae60, #16a085, #2980b9, #8e44ad, #2c3e50, + #7f8c8d !default; diff --git a/docs/.vuepress/styles/index.scss b/docs/.vuepress/styles/index.scss new file mode 100644 index 0000000..a2028eb --- /dev/null +++ b/docs/.vuepress/styles/index.scss @@ -0,0 +1,8 @@ +// place your custom styles here +@media (min-width: 1440px) { + .feature-item { + flex-basis: calc(33% - 3rem); + padding-top: 1.5rem; + padding-bottom: 1.5rem; + } +} diff --git a/docs/.vuepress/styles/palette.scss b/docs/.vuepress/styles/palette.scss new file mode 100644 index 0000000..356a428 --- /dev/null +++ b/docs/.vuepress/styles/palette.scss @@ -0,0 +1,2 @@ +// you can change colors here +$theme-color: #096dd9; diff --git a/docs/.vuepress/theme.ts b/docs/.vuepress/theme.ts new file mode 100644 index 0000000..60301a3 --- /dev/null +++ b/docs/.vuepress/theme.ts @@ -0,0 +1,91 @@ +import { hopeTheme } from "vuepress-theme-hope"; +import { zhNavbar } from "./navbar"; +import { zhSidebar } from "./sidebar"; + +export default hopeTheme({ + hostname: "https://mapstruct.plus", + // 是否显示打印按钮 + print: false, + + author: { + name: "linpeilie", + url: "https://github.com/linpeilie", + }, + + iconAssets: "iconfont", + + // logo: "/logo.svg", + + repo: "linpeilie/mapstruct", + docsDir: 'docs', + docsBranch: 'docs', + + locales: { + "/": { + // navbar + navbar: zhNavbar, + + // sidebar + sidebar: zhSidebar, + + // footer: "默认页脚", + + displayFooter: true, + + // page meta + metaLocales: { + editLink: "在 GitHub 上编辑此页", + }, + }, + }, + + plugins: { + copyCode: { + showInMobile: false + }, + // all features are enabled for demo, only preserve features you need here + mdEnhance: { + align: true, + attrs: true, + chart: true, + codetabs: true, + container: true, + demo: true, + echarts: false, + figure: true, + flowchart: false, + gfm: true, + imgLazyload: true, + imgMark: true, + imgSize: true, + include: true, + katex: true, + mark: true, + mermaid: true, + playground: { + presets: ["ts", "vue"], + }, + presentation: { + plugins: ["highlight", "math", "search", "notes", "zoom"], + }, + stylize: [ + { + matcher: "Recommended", + replacer: ({ tag }) => { + if (tag === "em") + return { + tag: "Badge", + attrs: { type: "tip" }, + content: "Recommended", + }; + }, + }, + ], + sub: true, + sup: true, + tabs: true, + vPre: true, + vuePlayground: true, + } + }, +}); diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..e75bbab --- /dev/null +++ b/docs/README.md @@ -0,0 +1,91 @@ +--- +home: true +icon: home +title: 主页 +heroText: MapstructPlus +tagline: 可能是最简单最强大的Java Bean转换工具 +actions: + - text: 快速开始 💡 + link: /introduction/quick-start/ + type: primary + +features: + - title: 快速 + icon: launch + details: Java 类之间的转换,仅需要增加一个注解,减少了乏味且容易出错的开发任务 + + - title: 效率 + icon: light + details: 基于注解处理器,所有生成工作都在编译期完成 + + - title: 转换 + icon: change + details: 属性转换基于类中的 getter/setter 方法 + + - title: 兼容 + icon: any + details: 支持JDK8~17、SpringBoot2~3 + + - title: 多类转换 + icon: structure + details: 支持单个类配置多个类型转换 + + - title: Map转对象 + icon: type + details: 更强大的Map转对象功能 + +copyright: false +--- + +## 最新版本 + +- maven + +```xml + + io.github.linpeilie + mapstruct-plus-spring-boot-starter + 1.1.6 + +``` + +- gradle + +```groovy +implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.1.6' +``` + +## 更新日志 + +### 1.1.6 + +- 支持在添加 `AutoMapper` 的类中,配置目标类到当前类的转换规则,适配多种场景下的使用; +- `AutoMapper` 增加注解,提供可以配置是否生成转换接口的功能; +- `AutoMapping` 的 `target` 属性默认可以不填,不填则取当前字段 +- 升级 mapstruct 版本为 1.5.3.FINAL + +…… + +## 代码仓库 + +- [Github](https://github.com/linpeilie/mapstruct-plus) +- [Gitee](https://gitee.com/linpeilie/mapstruct-plus) + +## 参与贡献 + +- 贡献代码:欢迎提交 Issue 或 Pull Requests +- 维护文档:项目目录下的 docs 目录,欢迎参与翻译与修订 + +## 推荐文章 + +- [彻底干掉 BeanUtils,最优雅的 Mapstruct 增强工具全新出炉](https://juejin.cn/post/7204307381688909882) + +## 友情链接 + +- [RuoYi-Vue-Plus](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) +- [RuoYi-Cloud-Plus](https://gitee.com/JavaLionLi/RuoYi-Cloud-Plus/wikis/pages) + +## 联系我 + +![Wechat --- Clue8a796d01](/assets/contact-me.png =346x403) + diff --git a/docs/changelog/index.md b/docs/changelog/index.md deleted file mode 100644 index 56b1bb6..0000000 --- a/docs/changelog/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -nav: 更新日志 -title: 简介 -order: 1 ---- - -# 更新日志 - -## **1.1.3** -> `2022-02-26` - -- 适配 SpringBoot3 - -## 1.1.1 -> `2022-02-06` - -- 增加 `Map` 转对象的功能 -- 增加单个类对多类转换的功能 \ No newline at end of file diff --git a/docs/guide/FAQ.md b/docs/guide/FAQ.md deleted file mode 100644 index a915199..0000000 --- a/docs/guide/FAQ.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: 常见问题 -order: 8 ---- - -# 与 `lombok` 整合 - -与 Mapstruct 整合 lombok 的方式一致。 - -- lombok 1.18.16 之前: - -```xml - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - - - org.projectlombok - lombok - ${lombok.version} - - - io.github.linpeilie - mapstruct-plus-processor - ${mapstruct-plus.version} - - - - - - -``` - -- lombok 1.18.16 之后: - -```xml - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - - - org.projectlombok - lombok - ${lombok.version} - - - io.github.linpeilie - mapstruct-plus-processor - ${mapstruct-plus.version} - - - org.projectlombok - lombok-mapstruct-binding - 0.2.0 - - - - - - -``` \ No newline at end of file diff --git a/docs/guide/annotations.md b/docs/guide/annotations.md deleted file mode 100644 index 87af25b..0000000 --- a/docs/guide/annotations.md +++ /dev/null @@ -1,317 +0,0 @@ ---- -title: 注解 -order: 5 ---- - -# 注解 - -## @AutoMapper - -`@AutoMapper` 定义**标识需要生成类转换接口** -需要在实体类上面定义 - -### **`target`** - -- 类型:`Class` - -**指定需要转换的目标类** - -**该属性表明会生成被注解的类,转换为目标类的接口** - -示例:: -如下配置,默认会生成 `Car` 转为 `CarDto` 的逻辑,如果没有配置 `CarDto` 转 `Car` -细节的话,还会根据默认的规则,生成相反的转换逻辑。具体细节,参考[转换接口生成约定](/guide/mapper-generate-appoint) - -```java - -@AutoMapper(target = CarDto.class) -public class Car { - // ... -} -``` - -### `uses` - -- 类型:`Class[]` - -**使用自定义类转换器** - -**该属性可以将自定义映射器,传递给生成的转换接口使用。常用于在进行一些属性转换时,针对一些特定目标类型进行自定义的映射** - -示例场景: - -项目中会有字符串用 `,` 分隔,在一些类中,需要根据逗号拆分为字符串集合。针对于这种场景,可以有两种方式:首先可以指定字段映射时的表达式,但需要对每种该情况的字段,都添加表达式,复杂且容易出错。 - -第二,就可以自定义一个类型转换器,通过 `uses` 来使用 - -```java -public interface StringToListString { - default List stringToListString(String str) { - return StrUtil.split(str); - } -} - -@AutoMapper(target = User.class, uses = StringToListStringConverter.class) -public class UserDto { - - private String username; - private int age; - private boolean young; - @AutoMapping(target = "educationList") - private String educations; - // ...... -} -``` - -测试: - -```java - -@SpringBootTest -public class QuickStartTest { - - @Autowired - private Converter converter; - - @Test - public void ueseTest() { - UserDto userDto = new UserDto(); - userDto.setEducations("1,2,3"); - - final User user = converter.convert(userDto, User.class); - System.out.println(user.getEducationList()); // [1, 2, 3] - - assert user.getEducationList().size() == 3; - } -} -``` - -## @AutoMappers - -`@AutoMappers` 定义标识需要生成多个类的转换接口 -需要在实体类上面定义 -当同时需要转换多个类时,不同类之间的属性配置,需要结合 `@AutoMappings` 来使用 - -例如,如下配置,同时会生成 `User <---> UserDto` 和 `User <---> UserVO` 之间的映射 - -```java -@AutoMappers({ - @AutoMapper(target = UserDto.class), - @AutoMapper(target = UserVO.class) -}) -public class User { - // ... -} -``` - -## @AutoMapMapper - -`@AutoMapMapper` 标识需要生成 `Map` 转为当前对象的转换接口 -需要在实体类上定义 - -其中,`value` 支持的类型如下: -- String -- BigDecimal -- BigInteger -- Integer -- Long -- Double -- Number -- Boolean -- Date -- LocalDateTime -- LocalDate -- LocalTime -- URI -- URL -- Calendar -- Currency -- 自定义类(自定义类也需要增加 `@AutoMapMapper` 注解) - -其中,类型的转换,交由 [hutool](https://hutool.cn) 包中的 `Convert` 接口实现,如果要转换的类已经是目标类型,则直接执行强转,否则,根据类型进行一定的适配转换。 - -例如: - -定义两个对象,`MapModelA` 和 `MapModelB`: - -- `MapModelA` -```java -@AutoMapMapper -@Data -public class MapModelA { - - private String str; - private int i1; - private Long l2; - private MapModelB mapModelB; - -} -``` - -- `MapModelB` -```java -@AutoMapMapper -@Data -public class MapModelB { - - private Date date; - -} -``` - -测试: - -```java -@SpringBootTest -public class QuickStartTest { - - @Autowired - private Converter converter; - - @Test - public void test() { - Map mapModel1 = new HashMap<>(); - mapModel1.put("str", "1jkf1ijkj3f"); - mapModel1.put("i1", 111); - mapModel1.put("l2", 11231); - - Map mapModel2 = new HashMap<>(); - mapModel2.put("date", DateUtil.parse("2023-02-23 01:03:23")); - - mapModel1.put("mapModelB", mapModel2); - - final MapModelA mapModelA = converter.convert(mapModel1, MapModelA.class); - System.out.println(mapModelA); // MapModelA(str=1jkf1ijkj3f, i1=111, l2=11231, mapModelB=MapModelB(date=2023-02-23 01:03:23)) - } -} -``` - -## @AutoMapping - -`@AutoMapping` 用于**字段**上面,**配置特定属性映射时的规则**,该注解会在生成时,转换为 Mapstruct 中的 `@Mapping` 注解 - -### `targetClass` - -**应用于的目标类** -用于多类转换时,区分当前规则,只应用于哪个类型之间的转换。 -当指定了多个类转换时,如果该注解没有配置 `targetClass`,则当前配置的规则应用于所有的类型转换中。 - -例如: -```java -@AutoMappers({ - @AutoMapper(target = UserDto.class), - @AutoMapper(target = UserVO.class) -}) -public class User { - - @AutoMapping(targetClass = UserDto.class, target = "educations", expression = "java(java.lang.String.join(\",\", source.getEducationList()))") - private List educationList; - - @AutoMappings({ - @AutoMapping(targetClass = UserDto.class, target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss"), - @AutoMapping(targetClass = UserVO.class, target = "birthday", ignore = true) - }) - private Date birthday; - - @AutoMapping(target = "money", numberFormat = "$0.00") - private double money; - -} -``` - -### `target` - -- 类型:`String` - -**目标字段,指定该注解的配置,应用于目标类中的哪个字段** - -示例: - -```java - -@AutoMapper(target = Goods.class) -public class GoodsDto { - - @AutoMapping(target = "price", numberFormat = "$#.00") - private int price; - // ... -} -``` - -### dateFormat - -- 类型:`String` - -**在字段映射时,进行时间格式化,应用于 Date 类型转为 String 类型** - -例如: - -```java -@AutoMapper(target = Goods.class) -public class GoodsDto { - - @AutoMapping(target = "takeDownTime", dateFormat = "yyyy-MM-dd HH:mm:ss") - private Date takeDownTime; - -} -``` - -### numberFormat - -- 类型:`String` - -**在字段映射时,进行数字格式化,应用于数字类型转换为 String 类型,可以指定 `java.text.DecimalFormat` 所支持的格式化字符串** - -例如: - -```java -@AutoMapper(target = Goods.class) -public class GoodsDto { - - @AutoMapping(target = "price", numberFormat = "$#.00") - private int price; - -} -``` - -### expression - -- 类型:`String` - -**类型,这个比较强大,其字符串实际上是一行可执行的 Java 代码,需要写在 `java()` 括号内** - -例如,用该属性,实现前面的列表转字符串: - -```java -@AutoMapper(target = UserDto.class) -public class User { - - @AutoMapping(target = "educations", expression = "java(java.lang.String.join(\",\", source.getEducationList()))") - private List educationList; - -} -``` - -## @AutoMappings - -`@AutoMappings` 定义该字段在不同类之间的转换规则,一般和 `@AutoMappers` 结合使用。 - -例如: -下面的配置,当 `User` to `UserDto` 时,需要进行时间格式化转换;当 `User` to `UserVO` 时,忽略该字段。 - -```java -@AutoMappers({ - @AutoMapper(target = UserDto.class), - @AutoMapper(target = UserVO.class) -}) -public class User { - - @AutoMappings({ - @AutoMapping(targetClass = UserDto.class, target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss"), - @AutoMapping(targetClass = UserVO.class, target = "birthday", ignore = true) - }) - private Date birthday; - -} -``` - diff --git a/docs/guide/class-convert.md b/docs/guide/class-convert.md new file mode 100644 index 0000000..c8dbaae --- /dev/null +++ b/docs/guide/class-convert.md @@ -0,0 +1,383 @@ +--- +title: 两个类之间的转换 +icon: creative +order: 1 +category: +- 指南 +description: MapstructPlus两个类之间的转换及配置 +--- + +## 简单转换 + +**要实现两个类之间的转换,只需要在其中一个类上增加注解 `@AutoMapper` ,配置 `target` 属性,指定目标类即可**。 + +例如: + +```java +@AutoMapper(target = CarDto.class) +public class Car { + // ... +} +``` +该例子表示,会生成 `Car` 转换为 `CarDto` 的接口 `CarToCarDtoMapper` 及实现类 `CarToCarDtoMapperImpl`。在生成的转换代码中,源类型(`Car`)的所有可读属性将被复制到目标属性类型(`CarDto`)的相应属性中。 + +当一个属性与它的目标实体对应物具有相同的名称时,将会被隐式映射。 + +除此之外,MapstructPlus 会根据当前的默认规则,生成 `CarDto` 转换为 `Car` 的接口 `CarDtoToCarMapper` 及实现类 `CarDtoToCarMapperImpl`。如果不想生成该转换逻辑的话,可以通过注解的 `reverseConvertGenerate` 属性来配置。 + +## 自定义对象的属性自动转换 + +当要转换的类中,存在自定义类时,会自动寻找该类型的转换方法。 + +例如,分别有两组对象模型:汽车(`Car`)和座椅(`SeatConfiguration`),其中 `Car` 依赖于 `SeatConfiguration`。 + +分别对应对象如下: + +- 汽车模型 + +::: code-tabs#java + +@tab Car + +```java +@AutoMapper(target = CarDto.class) +@Data +public class Car { + private SeatConfiguration seatConfiguration; +} +``` + +@tab CarDto + +```java +@Data +public class CarDto { + private SeatConfigurationDto seatConfiguration; +} +``` + +::: + +- 座椅模型 + +::: code-tabs#java + +@tab SeatConfiguration + +```java +@Data +@AutoMapper(target = SeatConfigurationDto.class) +public class SeatConfiguration { + // fields +} +``` + +@tab SeatConfigurationDto + +```java +@Data +public class SeatConfigurationDto { + // fields +} +``` + +::: + +在上面的例子中,首先会生成 `CarToCarDtoMapper` 和 `SeatConfigurationToSeatConfigurationDtoMapper` 两个转换接口,并且在转换 `Car` 时,会自动使用 `SeatConfigurationToSeatConfigurationDtoMapper` 来对其中的座椅属性来进行转换。 + +## 引入自定义类型转换器 + +当不同类型的属性,想要按照自定义的规则进行转换时,可以有两种办法: + +1. 通过 `@AutoMapping` 中配置的 `expression` 表达式配置 +2. 自定义一个类型转换器,通过 `@AutoMapper` 的 `uses` 属性来引入 + +方式一可以参考下面的[表达式](#表达式)章节。 + +这里基于方式二,实现将 `String` 类型的属性,根据逗号分隔,转换为 `List` 类型的属性: + +首先,定义一个类型转换器 —— `StringToListString`: + +```java +@Component +public class StringToListString { + public List stringToListString(String str) { + return StrUtil.split(str); + } +} +``` + +::: warning +- 类型转换器提供的类型转换方法,可以定义为 `static` 或 `nonstatic`的。 +- 如果是基于 `SpringBoot` 的方式使用该框架,则类型转换器需要定义为 Spring 的一个 Bean。 +::: + +下一步,使用该类型转换器: + +```java +@AutoMapper(target = User.class, uses = StringToListStringConverter.class) +public class UserDto { + + private String username; + private int age; + private boolean young; + @AutoMapping(target = "educationList") + private String educations; + // ...... +} +``` + +测试: + +```java +@SpringBootTest +public class QuickStartTest { + + @Autowired + private Converter converter; + + @Test + public void ueseTest() { + UserDto userDto = new UserDto(); + userDto.setEducations("1,2,3"); + + final User user = converter.convert(userDto, User.class); + System.out.println(user.getEducationList()); // [1, 2, 3] + + assert user.getEducationList().size() == 3; + } +} +``` + +## 自定义属性转换 + +当两个类中属性存在不一致的场景时,例如名称、类型等不一致,可以进行自定义转换,通过在属性上面添加 `@AutoMapping`,来配置映射规则。 + +### 不同属性名称映射 + +`@AutoMapping` 注解中,提供了 `target` 属性,可以配置当前属性与目标类中 `target` 属性之间映射。 + +例如,`Car` 转换为 `CatDto` 时,`seatConfiguration` 属性与 `seat` 属性相对应: + +```java +@AutoMapper(target = CarDto.class) +@Data +public class Car { + @AutoMapping(target = "seat") + private SeatConfiguration seatConfiguration; +} +``` + +`@AutoMapping` 注解中还提供 `source` 方法,该配置默认取当前属性的名称,之所以可以配置,是为了适应一种场景,当前类的某个属性,其内部的属性,转换为目标中的属性字段,则可以通过当前属性来配置。 + +例如: + +::: code-tabs#java + +@tab Goods + +```java +@Data +@AutoMapper(target = GoodsVo.class, reverseConvertGenerate = false) +public class Goods { + + @AutoMapping(source = "sku.price", target = "price") + private Sku sku; + +} +``` + +@tab GoodsVo + +```java +@Data +public class GoodsVo { + + private Integer price; + +} +``` + +::: + +### 指定时间格式转换 + +当时间类型(例如:`Date`、`LocalDateTime`、`LocalDate` 等等)需要和 `String` 通过指定时间格式进行转换时,可以通过 `@AutoMapping` 中的 `dateFormat` 来配置: + +例如: + +::: code-tabs#java + +@tab Order + +```java +@Data +@AutoMapper(target = OrderEntity.class) +public class Order { + + @AutoMapping(dateFormat = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime orderTime; + + @AutoMapping(dateFormat = "yyyy_MM_dd HH:mm:ss") + private Date createTime; + + @AutoMapping(target = "orderDate", dateFormat = "yyyy-MM-dd") + private String date; + +} +``` + +@tab OrderEntity + +```java +@Data +@AutoMapper(target = Order.class) +public class OrderEntity { + + @AutoMapping(dateFormat = "yyyy-MM-dd HH:mm:ss") + private String orderTime; + + @AutoMapping(dateFormat = "yyyy_MM_dd HH:mm:ss") + private String createTime; + + @AutoMapping(target = "date", dateFormat = "yyyy-MM-dd") + private LocalDate orderDate; + +} +``` + +::: + +### 指定数字格式转换 + +当数字类型(例如:`int`/`Integer` 等数字基本类型及包装类、`BigDecimal`)和 `String` 之间的转换需要指定数字格式,可以通过 `@AutoMapping` 的 `numberFormat` 来配置。 + +> 该格式需要 `java.text.DecimalFormat` 所支持 + +例如: + +::: code-tabs#java + +@tab Order + +```java +@Data +@AutoMapper(target = OrderEntity.class) +public class Order { + + @AutoMapping(numberFormat = "$0.00") + private BigDecimal orderPrice; + + @AutoMapping(numberFormat = "$0.00") + private Integer goodsNum; + +} +``` + +@tab OrderEntity + +```java +@Data +@AutoMapper(target = Order.class) +public class OrderEntity { + + @AutoMapping(numberFormat = "$0.00") + private String orderPrice; + + @AutoMapping(numberFormat = "$0.00") + private String goodsNum; + +} +``` + +::: + +### 忽略指定属性的转换 + +当在进行转换时,需要忽略指定属性的转换,可以通过 `@AutoMapping` 的 `ignore` 来配置。 + +例如: + +```java +@AutoMapper(target = CarDto.class) +@Data +public class Car { + + @AutoMapping(target = "wheels", ignore = true) + private Wheels wheels; + +} +``` + +### 属性转换时的默认值 + +`@AutoMapping` 中的 `defaultValue` 可以指定在转换属性时,当属性为 `null` 时,转换到目标类中的默认值。 + +例如: + +```java +@Data +@AutoMapper(target = DefaultVo.class) +public class DefaultDto { + + @AutoMapping(defaultValue = "18") + private Integer i; + + @AutoMapping(defaultValue = "1.32") + private Double d; + + @AutoMapping(defaultValue = "true") + private Boolean b; + +} +``` + +### 表达式 + +在执行属性转换时,可以通过指定执行一段 Java 代码来进行转换操作,例如,对源对象中的某个属性进行转换后返回。 + +需要注意的是,在生成时,会直接将表达式插入到转换逻辑中,并不会验证其语法。 + +例如,将源对象中的 `List` 属性,通过 `,` 拼接为字符串: + +```java +@AutoMapper(target = UserDto.class) +public class User { + + @AutoMapping(target = "educations", expression = "java(java.lang.String.join(\",\", source.getEducationList()))") + private List educationList; + +} +``` + +## 反向属性映射配置 + +::: info +**在该文中,所有提到的源类指通过 `@AutoMapper` 注解的类;目标类指的是 `@AutoMapper` 中 `target` 属性指定的类型。** +::: + +前面提到,当在一个类上面添加 `@AutoMapper` 注解时,默认情况下,除了会生成源类到目标类的转换接口,还会生成目标类到源类的转换接口和实现类,这里需要注意的是,默认情况下生成的该转换接口,并没有任何自定义配置,即使在源类中配置了 `@AutoMapping` 注解。 + +这里要实现目标类到源类的自定义转换配置,可以有两种方式: + +1. 在目标类上面添加 `@AutoMapper` 注解。这是最建议的方式,当转换双方都有添加该注解时,便不会生成默认的转换接口,即按照自定义的规则进行生成。 +2. 当目标类访问不到源类,或者项目规范不允许在目标类上面添加该种注解时,可以将自定义配置全部添加在源类中。这就是下面要介绍的**反向属性映射配置**。 + +框架中提供了 `@ReverseAutoMapping` 注解,该注解就是为了配置目标类到源类的自定义转换规则。 + +::: warning +这里需要注意的是,防止配置冲突,一旦添加 `@ReverseAutoMapping` 注解,在目标类中,便不能添加任何自定义转换注解 +::: + +**`@ReverseAutoMapping` 注解表示的含义,是目标类到源类转换时,需要指定的自定义转换规则,其中可以配置的属性,与 `@AutoMapping` 注解一致。** + +这里有两个属性需要注意,分别是 `source` 和 `target`。 + +**这里的 `source` 指的是目标类中的属性,`target` 指的是源类中的属性。** + +可能会有人这里有疑问,为什么这里的配置像是反的?如果没有,可以直接跳过。 + +框架设计的时候,所有的属性转换配置,都是基于要转换的类型,该类转换为目标类,想要应用的效果。这里的 `source` 也应该是来源类中的属性。 + +如果还是不理解,这里可以认为,该注解就是本该应用在目标类中的 `@AutoMapping` 注解,原封不动拷贝到当前类,再修改注解名称即可。 + diff --git a/docs/guide/config.md b/docs/guide/config.md deleted file mode 100644 index c4d3e57..0000000 --- a/docs/guide/config.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: 配置 -order: 4 ---- - -# 配置 - -由于 Mapstruct Plus 是注解处理器,主要工作是在编译阶段完成的,只能通过注解的方式,来进行项目配置。 - -且需要注意的是,**所有的配置类,都必须与需要进行对象转换的类,在同一个模块包中,且只能定义一个**。 - -目前提供了两个配置类: - -- `ComponentModelConfig` -- `MapperConfig` - -## ComponentModelConfig - -`ComponentModelConfig` **定义获取 Mapper 接口对象的注入方式**,只有一个属性 `componentModel`。 -可以在与要转换对象同模块包下的任意类或者接口上使用。 - -目前 Mapstruct plus 中支持两种:`default` 和 `spring`。 - -当使用非 Spring 模式时,必须定义该配置,`componentModel=default`。 - -## MapperConfig - -`MapperConfig` 注解定义 **Mapper 接口生成的规则**,目前只支持配置生成接口的包名 -可以在与要转换对象同模块包下的任意类或接口上使用。 - -### mapperPackage - -指定生成的 Mapper 包名。 - -当没有指定该目录时,会在指定 `AutoMapper` 注解的类同级目录下,生成 Mapper 接口 diff --git a/docs/guide/converter-api.md b/docs/guide/converter-api.md index 09e5528..b816df7 100644 --- a/docs/guide/converter-api.md +++ b/docs/guide/converter-api.md @@ -1,25 +1,30 @@ --- -title: 类型转换API -order: 6 +title: 类转换 API +icon: creative +order: 4 +category: +- 指南 +description: Mapstruct Converter接口API --- -# 类型转换 API +## Converter -在 Mapstruct Plus 中,类型转换对外提供了一个接口:`Converter` +前面的章节,都是介绍,在实体类上面配置转换逻辑,它们主要应用在编译阶段。在实际应用时,框架提供了 `Converter` 类,来执行具体的转换逻辑。 -> `Converter` 类实际根据源类型和目标类型,寻找相应的 `Mapper` 接口,然后交由 `Mapper` 接口来转换。 -> 其内部做了缓存处理,所以,建议全局只定义一个 `Converter` 对象。 +针对类型转换该类提供了如下方法: -其中提供了三个方法: +- **` T convert(S source, Class targetType)`** -- `T convert(S source, Class targetType)` - 将 `S` 类型的对象,转换为 `targetType` 类型的对象并返回 +传入需要转换的对象(`source`)与目标类型(`targetType`),最终返回目标类型的实例对象。 -- `T convert(S source, T target)` - 将 `S` 类型的对象,按照配置的映射字段规则,给 `target` 类型的对象赋值,并返回 `target` 对象 +- **` T convert(S source, T target)`** -- `List convert(List source, Class targetType)` - 将 `S` 类型的集合,转换为 `targetType` 类型的集合并返回 +传入需要转换对象(`source`)与目标对象(`target`),最终将 `source` 中的属性,转换到 `target` 对象中,该方法与上面的区别在于,该方法返回的是传入的 `target` 对象,上面的方法返回的是一个新的对象。 -- ` T convert(Map map, Class target)` - 将 `Map` 转换为 `target` 类型的集合并返回 \ No newline at end of file +- **` List convert(List source, Class targetType)`** + +该方法会将一个源类型(`source`)的集合转换为目标类型(`targetType`)的集合 + +- **` T convert(Map map, Class target)`** + +该方法会将一个 `Map` 转换为目标类型的实例对象。 \ No newline at end of file diff --git a/docs/guide/faq.md b/docs/guide/faq.md new file mode 100644 index 0000000..a2dd3f2 --- /dev/null +++ b/docs/guide/faq.md @@ -0,0 +1,79 @@ +--- +title: 常见问题 +icon: creative +order: 5 +category: +- 指南 +description: MapstructPlus常见问题 +--- + +## 与 `lombok` 整合 + +与 Mapstruct 整合 lombok 的方式一致。 + +### lombok 1.18.16 之前: + +```xml + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + org.projectlombok + lombok + ${lombok.version} + + + io.github.linpeilie + mapstruct-plus-processor + ${mapstruct-plus.version} + + + + + + +``` + +### lombok 1.18.16 及以后: + +```xml + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + org.projectlombok + lombok + ${lombok.version} + + + io.github.linpeilie + mapstruct-plus-processor + ${mapstruct-plus.version} + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + + + + + + +``` \ No newline at end of file diff --git a/docs/guide/map-to-class.md b/docs/guide/map-to-class.md new file mode 100644 index 0000000..958830e --- /dev/null +++ b/docs/guide/map-to-class.md @@ -0,0 +1,101 @@ +--- +title: Map 转对象 +icon: creative +order: 2 +category: +- 指南 +description: MapstructPlus Map转为对象 +--- + +MapstructPlus 提供了更加强大的 `Map` 转对象的功能。 + +## 使用 + +**当想要自动生成 `Map` 转为目标类的接口及实现类时,只需要在目标类上添加 `@AutoMapMapper` 注解**。 + +## 支持的 value 类型 + +- `String` +- `BigDecimal` +- `BigInteger` +- `Integer` +- `Long` +- `Double` +- `Boolean` +- `Date` +- `LocalDateTime` +- `LocalDate` +- `LocalTime` +- `URI` +- `URL` +- `Calendar` +- `Currency` +- `自定义类(自定义类也需要增加 @AutoMapMapper 注解)` + +## 转换逻辑 + +**针对目标类中的一个属性,首先会判断 `Map` 中是否存在该键,如果存在的话,首先判断类型,如果相同类型,直接强转,如果不同类型,则会基于 [Hutool](https://hutool.cn/docs/#/core/%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2/%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%E5%B7%A5%E5%85%B7%E7%B1%BB-Convert) 提供的类型转换工具尝试转换为目标类型**。 + +**且同时支持内部嵌套 `Map` 属性转为内部嵌套的自定义类型属性**。 + +## 示例 + +- 定义两个对象:`MapModelA` 和 `MapModelB` + +::: code-tabs#java + +@tab MapModelA + +```java +@AutoMapMapper +@Data +public class MapModelA { + + private String str; + private int i1; + private Long l2; + private MapModelB mapModelB; + +} +``` + +@tab MapModelB + +```java +@AutoMapMapper +@Data +public class MapModelB { + + private Date date; + +} +``` + +::: + +- 转换测试 + +```java +@SpringBootTest +public class QuickStartTest { + + @Autowired + private Converter converter; + + @Test + public void test() { + Map mapModel1 = new HashMap<>(); + mapModel1.put("str", "1jkf1ijkj3f"); + mapModel1.put("i1", 111); + mapModel1.put("l2", 11231); + + Map mapModel2 = new HashMap<>(); + mapModel2.put("date", DateUtil.parse("2023-02-23 01:03:23")); + + mapModel1.put("mapModelB", mapModel2); + + final MapModelA mapModelA = converter.convert(mapModel1, MapModelA.class); + System.out.println(mapModelA); // MapModelA(str=1jkf1ijkj3f, i1=111, l2=11231, mapModelB=MapModelB(date=2023-02-23 01:03:23)) + } +} +``` diff --git a/docs/guide/mapper-generate-appoint.md b/docs/guide/mapper-generate-appoint.md deleted file mode 100644 index c533a26..0000000 --- a/docs/guide/mapper-generate-appoint.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: Mapper 接口生成约定 -order: 7 ---- - -# Mapper 接口生成约定 - -## Mapper 接口包名 - -`Mapper` 接口包名按照如下规则获取: - -1. 转换对象所在模块中,配置的 `@sMapperConfig` 中指定的 `mapperPackage` 属性 -2. 如果没有指定,则会取 `@AutoMapper` 类的包名 - -## Mapper 接口命名 - -`Mapper` 接口命名规则如下:`源类名` + `To` + `目标类名` + `Mapper` - -例如,在 `User` 类上指定 `@AutoMapper(target = UserDto.class)`,则生成的 `Mapper` 接口类名为:`UserToUserDtoMapper` - -## 自动生成相反类型转换及 `@AutoMapping` 继承 - -假如,在 `User` 类上指定 `@AutoMapper(target = UserDto.class)`,同时如果没有在 `UserDto` 上标注 `@AutoMapper(target = User.class)` 的话,除了会生成 `UserToUserDtoMapper` 接口,默认也会生成 `UserDtoToUserMapper` 接口。 - -即,**同时会生成两个类的相互转换接口**。所以[快速开始](/guide/quick_start)中才可以由 `UserDto` 转为 `User` 对象。 - -但是,具体属性上面的 `@AutoMapping` 注解,不能够完全继承。 - -例如,`User` 中的 `Date` 类型的属性,在 `@AutoMapping` 中指定了 `dateFormat` 时间格式,当反过来时,却不能这样子用,因为 `dateFormat` 只能应用于 String 类型。 - -由于这个原因,默认情况下生成反向转换 `Mapper`,`@AutoMapping` 的部分属性是不能够继承的。 - -目前,反向转换 `Mapper` 中,支持继承的 `@AutoMapping` 属性有如下: - -- `target`:目标属性为当前源对象的标注 `@AutoMapping` 的属性 -- `ignore`:忽略当前属性的转换 - -例如: - -定义 `User` 类如下: - -```java -@AutoMapper(target = UserDto.class) -public class User { - - private String username; - private int age; - private boolean young; - - @AutoMapping(target = "educations", ignore = true) - private List educationList; - - @AutoMapping(target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss") - private Date birthday; - - @AutoMapping(target = "assets", numberFormat = "$0.00") - private double assets; - -} -``` - -当在 `User` 类上没有定义 `@AutoMapper` 注解时,会按照默认规则进行生成。 - -相当于: - -```java -@AutoMapper(target = User.class) -public class UserDto { - - private String username; - private int age; - private boolean young; - - @AutoMapping(target = "educationList", ignore = true) - private List educations; - - @AutoMapping(target = "birthday") - private Date birthday; - - @AutoMapping(target = "assets") - private double assets; - -} -``` diff --git a/docs/guide/multiple-class-convert.md b/docs/guide/multiple-class-convert.md new file mode 100644 index 0000000..6e73ca3 --- /dev/null +++ b/docs/guide/multiple-class-convert.md @@ -0,0 +1,73 @@ +--- +title: 一个类与多个类之间转换 +icon: creative +order: 3 +category: +- 指南 +description: MapstructPlus一个类与多个类之间转换 +--- + +MapstructPlus 除了支持一个类与单个目标类型进行转换,还支持一个类与多个目标类型进行转换。 + +## 配置多个类转换 + +当想要配置一个类与多个类进行转换时,可以通过 `@AutoMappers` 来配置,该注解支持配置多个 `@AutoMapper` + +例如: + +```java +@Data +@AutoMappers({ + @AutoMapper(target = UserDto.class), + @AutoMapper(target = UserVO.class) +}) +public class User { + // fields +} +``` + +## 配置指定类转换的规则 + +当配置多个类转换时,可能会有不同的类,同一属性转换规则不同的场景。 + +针对这个问题,首先可以使用 `@AutoMappings` 指定多个转换规则,并且在使用 `@AutoMapping` 注解时,配置 `targetClass` 属性,指定当前规则的应用目标转换类。 + +如果在配置 `@AutoMapping` 注解时,没有指定 `targetClass` 时,则当前规则,会应用于与所有类转换。 + +例如: + +```java +@Data +@AutoMappers({ + @AutoMapper(target = UserDto.class), + @AutoMapper(target = UserVO.class) +}) +public class User { + + private String username; + + private int age; + private boolean young; + + @AutoMapping(targetClass = UserDto.class, target = "educations", expression = "java(java.lang.String.join(\",\", source.getEducationList()))") + private List educationList; + + @AutoMappings({ + @AutoMapping(targetClass = UserDto.class, dateFormat = "yyyy-MM-dd HH:mm:ss"), + @AutoMapping(targetClass = UserVO.class, ignore = true) + }) + private Date birthday; + + @AutoMapping(targetClass = UserDto.class, numberFormat = "$0.00") + private double assets; + + @AutoMapping(numberFormat = "$0.00") + private double money; + + @AutoMappings({ + @AutoMapping(targetClass = UserVO.class, target = "voField") + }) + private String voField; + +} +``` \ No newline at end of file diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 45bbd0d..0000000 --- a/docs/index.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: A static site based on dumi -hero: - title: mapstruct plus - description: 简单、强大的 Java Bean 转换工具 - actions: - - text: 快速开始 - link: /guide/quick-start -features: - - title: 快速开发 - emoji: 🚀 - description: Java 实体类之间的转换,仅需要一个注解,减少了乏味且容易出错的开发任务 - - title: 效率 - emoji: 🌈 - description: 基于注解处理器,所有生成工作在编译阶段完成;生成的代码基于原有 getter/setter 方法,不会影响原有性能 - - title: 目标 - emoji: 💡 - description: 做最简单、最强大的类转换工具 ---- diff --git a/docs/guide/index.md b/docs/introduction/README.md similarity index 75% rename from docs/guide/index.md rename to docs/introduction/README.md index ea9acd3..e930862 100644 --- a/docs/guide/index.md +++ b/docs/introduction/README.md @@ -1,11 +1,14 @@ --- -nav: 指南 title: 简介 -order: -1 +icon: creative +order: 1 +category: +- 介绍 +tag: +- 简介 +description: MapstructPlus简介,MapstructPlus是什么 --- -# 简介 - > 首先,先了解一下 Mapstruct: > [Mapstruct](https://mapstruct.org) 是一个代码生成器,通过定义类转换的接口,自动实现属性转换的具体逻辑。主要为了简化 Java 类型之间转换的实现。 @@ -15,13 +18,12 @@ Mapstruct Plus 是 Mapstruct 的增强工具,在 Mapstruct 的基础上,实 Mapstruct Plus 内嵌 Mapstruct,和 Mapstruct 完全兼容,如果之前已经使用 Mapstruct,可以无缝替换依赖。 -# 代码托管 +## 代码托管 - [Gitee](https://gitee.com/linpeilie/mapstruct-plus) - [Github](https://github.com/linpeilie/mapstruct-plus) -# 联系我 +## 参与贡献 -> vx : Clue8a796d01 - -联系我 \ No newline at end of file +- 贡献代码:欢迎提交 Issue 或 Pull Requests +- 维护文档:项目目录下的 docs 目录,欢迎参与翻译与修订 diff --git a/docs/guide/install.md b/docs/introduction/install.md similarity index 75% rename from docs/guide/install.md rename to docs/introduction/install.md index debad88..738aac3 100644 --- a/docs/guide/install.md +++ b/docs/introduction/install.md @@ -1,13 +1,17 @@ --- title: 安装 -order: 3 +icon: creative +order: 2 +category: +- 介绍 +tag: +- 安装 +description: MapstructPlus依赖安装 --- - -# 安装 - +::: warning 由于其已经内嵌 Mapstruct,为了防止不同版本之间的差异,请不要再引入 Mapstruct 相关依赖 - +::: ## 非 SpringBoot 环境 @@ -15,7 +19,7 @@ order: 3 ```xml - 1.1.3 + 最新版本 @@ -31,8 +35,8 @@ order: 3 maven-compiler-plugin 3.8.1 - 1.8 - 1.8 + 1.8 + 1.8 io.github.linpeilie @@ -50,9 +54,9 @@ order: 3 ```groovy dependencies { - implementation 'io.github.linpeilie:mapstruct-plus:1.1.3' + implementation 'io.github.linpeilie:mapstruct-plus:最新版本' - annotationProcessor 'io.github.linpeilie:mapstruct-plus-processor:1.1.3' + annotationProcessor 'io.github.linpeilie:mapstruct-plus-processor:最新版本' } ``` @@ -62,7 +66,7 @@ dependencies { ```xml - 1.1.3 + 最新版本 @@ -78,8 +82,8 @@ dependencies { maven-compiler-plugin 3.8.1 - 1.8 - 1.8 + 1.8 + 1.8 io.github.linpeilie @@ -97,8 +101,8 @@ dependencies { ```groovy dependencies { - implementation 'io.github.linpeilie:mapstruct-plus-spring-boot-starter:1.1.3' + implementation 'io.github.linpeilie:mapstruct-plus-spring-boot-starter:最新版本' - annotationProcessor 'io.github.linpeilie:mapstruct-plus-processor:1.1.3' + annotationProcessor 'io.github.linpeilie:mapstruct-plus-processor:最新版本' } -``` \ No newline at end of file +``` diff --git a/docs/guide/quick-start.md b/docs/introduction/quick-start.md similarity index 95% rename from docs/guide/quick-start.md rename to docs/introduction/quick-start.md index fefb5a9..663c7de 100644 --- a/docs/guide/quick-start.md +++ b/docs/introduction/quick-start.md @@ -1,10 +1,14 @@ --- title: 快速开始 -order: 2 +icon: creative +order: 3 +category: +- 介绍 +tag: +- 快速开始 +description: MapstructPlus快速开始教程 --- -# 快速开始 - 下面演示如何使用 MapStruct Plus 来映射两个对象。 假设有两个类 `UserDto` 和 `User`,分别表示数据层对象和业务层对象: @@ -41,7 +45,7 @@ public class User { ```xml - 1.1.3 + 最新版本 @@ -137,7 +141,7 @@ public class QuickStart { ```xml - 1.1.3 + 最新版本 diff --git a/docs/release/log.md b/docs/release/log.md new file mode 100644 index 0000000..af7c93b --- /dev/null +++ b/docs/release/log.md @@ -0,0 +1,32 @@ +--- +title: 更新日志 +icon: creative +order: 1 +category: +- 更新日志 +--- + +## 1.1.6 + +- 支持在添加 `AutoMapper` 的类中,配置目标类到当前类的转换规则,适配多种场景下的使用; +- `AutoMapper` 增加注解,提供可以配置是否生成转换接口的功能; +- `AutoMapping` 的 target 属性默认可以不填,不填则取当前字段 +- 升级 mapstruct 版本为 1.5.3.FINAL + +## 1.1.5 + +- `AutoMapping` 增加 `source` 和 `defaultValue` 属性支持 + +## 1.1.4 + +- 增加反向转换配置功能 +- 解决树状结构转换bug + +## 1.1.3 + +- 适配 SpringBoot3 + +## 1.1.1 + +- 增加 Map 转对象的功能 +- 增加单个对象与多个对象转换并配置的功能 \ No newline at end of file diff --git a/package.json b/package.json index 9dfa86d..d222aeb 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,23 @@ { "name": "mapstruct-plus", - "version": "0.0.1", - "description": "mapstruct-plus document", + "version": "2.0.0", + "description": "mapstruct-plus-document", "license": "MIT", + "type": "module", "scripts": { - "build": "dumi build", - "predeploy": "cp CNAME ./dist", - "deploy": "gh-pages -d dist", - "dev": "dumi dev", - "prepare": "dumi setup", - "start": "npm run dev" + "dev": "vuepress dev docs", + "build": "vuepress build docs", + "docs:build": "vuepress build docs", + "docs:clean-dev": "vuepress dev docs --clean-cache", + "docs:dev": "vuepress dev docs", + "docs:update-package": "npx vp-update" }, "devDependencies": { - "dumi": "^2.0.2", - "dumi-theme-antd-style": "^0.10.5", - "gh-pages": "^5.0.0" - }, - "authors": [ - "linpeilie@qq.com" - ] + "@vuepress/client": "2.0.0-beta.61", + "@vuepress/plugin-search": "^2.0.0-beta.61", + "@vuepress/plugin-shiki": "^2.0.0-beta.61", + "vue": "^3.2.47", + "vuepress": "2.0.0-beta.61", + "vuepress-theme-hope": "2.0.0-beta.185" + } } diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 3ea66c2..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "skipLibCheck": true, - "esModuleInterop": true, - "baseUrl": "./", - "paths": { - "@@/*": [".dumi/tmp/*"] - } - }, - "include": [".dumi/**/*", ".dumirc.ts"] -}