侧边栏壁纸
  • 累计撰写 49 篇文章
  • 累计创建 23 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Java框架之 MapStruct-Plus 代码生成器

阿砖
2024-06-22 / 0 评论 / 0 点赞 / 167 阅读 / 9913 字

简介

MapStruct PlusMapStruct 的增强工具,在 MapStruct 的基础上,实现了自动生成 Mapper 接口的功能,并强化了部分功能,使 Java 类型转换更加便捷、优雅。MapStruct Plus 可以实现代码的深拷贝

准备

我这里用的是 Maven 作为我的项目构建工具,先给项目添加 MapStruct Plus 的坐标和相应的解释器

<properties>
	<mapstruct-plus.version>1.4.2</mapstruct-plus.version>
	<lombok.version>1.18.32</lombok.version>
</properties>

<dependencies>
	<dependency>
		<groupId>io.github.linpeilie</groupId>
		<artifactId>mapstruct-plus</artifactId>
		<version>${mapstruct-plus.version}</version>
	</dependency>

	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<version>${lombok.version}</version>
	</dependency>

	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.13.2</version>
	</dependency>
</dependencies>

<build>
	<plugins>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-compiler-plugin</artifactId>
			<version>3.8.1</version>
			<configuration>
				<source>1.8</source>
				<target>1.8</target>
				<annotationProcessorPaths>
					<path>
						<groupId>org.projectlombok</groupId>
						<artifactId>lombok</artifactId>
						<version>${lombok.version}</version>
					</path>
					<!-- 因为使用了 lombok 所以要在下面增加相应的解释器 -->
					<path>
						<groupId>org.projectlombok</groupId>
						<artifactId>lombok-mapstruct-binding</artifactId>
						<version>0.2.0</version>
					</path>
					<path>
						<groupId>io.github.linpeilie</groupId>
						<artifactId>mapstruct-plus-processor</artifactId>
						<version>${mapstruct-plus.version}</version>
					</path>
				</annotationProcessorPaths>
			</configuration>
		</plugin>
	</plugins>
</build>

创建一个配置文件 MapperConfiguration.java

import io.github.linpeilie.annotations.ComponentModelConfig;

@ComponentModelConfig(componentModel = "default")
public class MapperConfiguration {

}

创建几个实体类用来测试 MapStruct Plus 自动生成映射消息

  • Dept.java

import java.time.LocalDateTime;

import io.github.linpeilie.annotations.AutoMapping;
import lombok.Data;

/**
 * 部门
 */
@Data
public class Dept {
	private Integer id;
	
	private String deptName;

	/**
	 * 排序
	 */
	private Integer sort;

	/**
	 * 部门负责人
	 */
	private String leaderName;
	/**
	 * 部门负责人邮箱
	 */
	private String email;
	
	/**
	 * 状态 true 能用 false 不能用
	 */
	private Boolean status;

	private LocalDateTime craeteDate;

	private LocalDateTime updateDate;
}
  • Role.java

import java.time.LocalDateTime;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 角色
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Role {
	
	private Integer id;
	
	private String roleKey;

	private String roleName;

	/**
	 * 状态 true 能用 false 不能用
	 */
	private Boolean status;

	private LocalDateTime craeteDate;

	private LocalDateTime updateDate;
}
  • User.java

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

import com.runbrick.app.converter.StringToListStringConverter;
import com.runbrick.app.vo.UserVO;

import io.github.linpeilie.annotations.AutoMapper;
import io.github.linpeilie.annotations.AutoMapping;
import lombok.Data;

@Data
@AutoMapper(target = UserVO.class, uses = { StringToListStringConverter.class })
public class User {

	/**
	 * 用户身份信息
	 */
	@AutoMapping(target = "userCode")
	private Integer id;

	private String userName;

	@AutoMapping(defaultValue = "noNickName")
	private String nickName;

	private Integer sex;

	/**
	 * 角色列表
	 */
	private List<Role> roles;

	/**
	 * 部门层级 eg: 1,23,120
	 */
	@AutoMapping(qualifiedByName = "StringToList")
	private String deptTree;

	/**
	 * 所属部门
	 */
	private Dept dept;

	/**
	 * 登录时间
	 */
	@AutoMapping(dateFormat = "yyyy-MM-dd")
	private LocalDateTime loginDate;

	/**
	 * 状态 true 能用 false 不能用
	 */
	private Boolean status;

	@AutoMapping(dateFormat = "yyyy-MM-dd HH:mm:ss")
	private LocalDateTime craeteDate;

	@AutoMapping(dateFormat = "yyyy-MM-dd HH:mm:ss")
	private LocalDateTime updateDate;
	/**
	 * 余额
	 */
	@AutoMapping(numberFormat = "$0.00")
	private BigDecimal wallet;
}

  • UserVO.java

import java.util.ArrayList;
import java.util.List;

import com.runbrick.app.domain.Role;

import lombok.Data;

/**
 * 用户视图类
 */
@Data
public class UserVO {
	/**
	 * @see User.class id
	 */
	private Integer userCode;

	private String userName;

	private String nickName;

	private ArrayList<Role> roles;

	/**
	 * 部门名称
	 */
	private String deptName;

	/**
	 * 部门层级
	 */
	private List<String> deptTree;

	/**
	 * 状态 true 能用 false 不能用
	 */
	private Boolean status;

	private String craeteDate;

	private String updateDate;

	/**
	 * 登录时间
	 */
	private String loginDate;

	/**
	 * 余额
	 */
	private String wallet;
	
}

创建一个工具类 DataGenerationUtil.java 用来创建上面的实体数据

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import com.runbrick.app.domain.Dept;
import com.runbrick.app.domain.Role;
import com.runbrick.app.domain.User;

/**
 * 数据生成类
 */
public class DataGenerationUtil {

	public static User generationUser(Dept dept, ArrayList<Role> roles) {
		LocalDateTime now = LocalDateTime.now();
		User user = new User();
		user.setId(10001);
		user.setUserName("zhangsan");
		user.setSex(1);
		user.setRoles(roles);
		user.setDept(dept);
		user.setDeptTree("1,20,1001");
		user.setStatus(true);
		user.setCraeteDate(now);
		user.setLoginDate(now.minusDays(20));
		user.setUpdateDate(now.minusDays(10));
		user.setWallet(new BigDecimal("120.30"));
		return user;
	}

	public static ArrayList<Role> generationRoles() {
		LocalDateTime now = LocalDateTime.now();
		ArrayList<Role> roles = new ArrayList<Role>();
		roles.add(new Role(1001, "ADMIN-ROLE", "管理员", true, now, now.minusDays(10)));
		roles.add(new Role(1002, "USER-ROLE", "普通用户", true, now, now.minusDays(10)));
		roles.add(new Role(1003, "MENU-ADMIN-ROLE", "菜单管理员", true, now, now.minusDays(10)));

		return roles;
	}

	public static Dept generationDept() {
		LocalDateTime now = LocalDateTime.now();
		Dept dept = new Dept();
		dept.setId(1001);
		dept.setDeptName("生产部门");
		dept.setSort(1);
		dept.setLeaderName("侃大山");
		dept.setEmail("xxx@qq.com");
		dept.setStatus(true);
		dept.setCraeteDate(now);
		dept.setUpdateDate(now.minusDays(10));
		return dept;
	}
}

创建一个转换类用来转换部门层级

import java.util.Arrays;
import java.util.List;

import org.mapstruct.Named;

public class StringToListStringConverter {

	/**
	 * 字符串转数组
	 * 
	 * @param str 要转换的字符串,只支持用 "," 转换
	 * @return
	 */
	@Named("StringToList")
	public List<String> stringToList(String str) {
		
		if (!str.isEmpty() && str.length() > 0) {
			return Arrays.asList(str.split(","));
		}
		
		return null;
	}
}

创建一个测试方法用来测试上面的实体


import java.util.ArrayList;

import org.junit.Test;

import com.runbrick.app.domain.Dept;
import com.runbrick.app.domain.Role;
import com.runbrick.app.domain.User;
import com.runbrick.app.util.DataGenerationUtil;
import com.runbrick.app.vo.UserVO;

import io.github.linpeilie.Converter;

public class MapStructApplication {
	private static Converter converter = new Converter();

	@Test
	public void testGeneration1() {
		ArrayList<Role> generationRoles = DataGenerationUtil.generationRoles();
		Dept generationDept = DataGenerationUtil.generationDept();
		User generationUser = DataGenerationUtil.generationUser(generationDept, generationRoles);
		
		// 创建转换
		UserVO convert = converter.convert(generationUser, new UserVO());
		System.out.println(convert);
	}

}

执行结果:

UserVO(userCode=10001, userName=zhangsan, nickName=noNickName, roles=[Role(id=1001, roleKey=ADMIN-ROLE, roleName=管理员, status=true, craeteDate=2024-06-22T19:44:38.790, updateDate=2024-06-12T19:44:38.790), Role(id=1002, roleKey=USER-ROLE, roleName=普通用户, status=true, craeteDate=2024-06-22T19:44:38.790, updateDate=2024-06-12T19:44:38.790), Role(id=1003, roleKey=MENU-ADMIN-ROLE, roleName=菜单管理员, status=true, craeteDate=2024-06-22T19:44:38.790, updateDate=2024-06-12T19:44:38.790)], deptName=null, deptTree=[1, 20, 1001], status=true, craeteDate=2024-06-22 19:44:38, updateDate=2024-06-12 19:44:38, loginDate=2024-06-02, wallet=$120.30)

测试的时候发现,好像将 List<Entity> 中的某个元素转换另一个实体中的一个字符串实体并不能通过 指定转换方法 实现,不过普通的转换还是可以的。

0

评论区