Java高性能实体类转换工具MapStruct的使用教程详解
作者:EvenBoy
MapStruct 是一个代码生成器,它基于约定优于配置的方法,极大地简化了 Java bean 类型之间的映射实现,本文主要介绍了MapStruct的具体使用以及如何进行实体类转换,感兴趣的可以了解下
MapStruct
它是什么?
MapStruct 是一个代码生成器,它基于约定优于配置的方法,极大地简化了 Java bean 类型之间的映射实现。
生成的映射代码使用普通的方法调用,因此速度快、类型安全且易于理解。
为什么?
多层应用程序通常需要在不同的对象模型(例如实体和 DTO)之间进行映射。编写这样的映射代码是一项乏味且容易出错的任务。MapStruct 旨在通过尽可能地自动化来简化这项工作。
与其他映射框架相比,MapStruct 在编译时生成 bean 映射,这确保了高性能,允许快速的开发人员反馈和彻底的错误检查。
如何?
MapStruct 是一个注解处理器,它插入到 Java 编译器中,可用于命令行构建(Maven、Gradle 等)以及您首选的 IDE。
MapStruct 使用合理的默认值,但在配置或实现特殊行为时会采取措施。
使用场景
1、数据库中的字段和你对接的A部门、B部门的入参字段不一致的情况。
2、涉及到一些入参和出参值的转换 比如:性别、日期等。
使用教程
1、引入pom.xml
<!--mapStruct依赖--> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.3.1.Final</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.3.1.Final</version> <scope>provided</scope> </dependency>
2、入参(每个部门的入参可能不太一样)
package com.lezu.springboot.common.dto.param; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @author LianJiaYu * @date 2022/9/1 14:09 */ @Data public class UserInfoParam { @ApiModelProperty(value = "用户账号") private String account; @ApiModelProperty(value = "性别") private String gender; @ApiModelProperty(value = "密码") private String password; @ApiModelProperty(value = "出生日期") private Long birthday; @ApiModelProperty(value = "验证码captchaId") private String captchaId; @ApiModelProperty(value = "昵称") private String name; @ApiModelProperty(value = "验证码") private String code; }
3、对应数据库中的字段
package com.lezu.springboot.common.dto.in; import com.lezu.springboot.common.Page; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.util.Date; /** * @Author LianJiaYu * @Date 2021/4/4 22:06 * @Version 1.0 */ @Data @AllArgsConstructor @NoArgsConstructor public class InUserInfoDto extends Page implements Serializable { private static final long serialVersionUID = 5755742614532104337L; @ApiModelProperty(value = "用户账号") @NotNull(message = "用户名不能为空") private String username; @ApiModelProperty(value = "性别") private Integer gender; @ApiModelProperty(value = "密码") @NotNull(message = "密码不能为空") private String password; @ApiModelProperty(value = "出生日期") private Date birthday; @ApiModelProperty(value = "验证码captchaId") private String captchaId; @ApiModelProperty(value = "昵称") private String name; @ApiModelProperty(value = "验证码") private String code; @ApiModelProperty(value = "默认状态") private String defaultStatus; }
4、定义工厂
package com.lezu.springboot.common.dto.Interface; import com.lezu.springboot.common.ListResult; import com.lezu.springboot.common.conversion.DataConversionWorker; import com.lezu.springboot.common.conversion.EnumConversionWorker; import com.lezu.springboot.common.dto.in.InUserInfoDto; import com.lezu.springboot.common.dto.out.OutUserInfoDto; import com.lezu.springboot.common.dto.param.UserInfoParam; import com.lezu.springboot.common.dto.result.UserInfoResult; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; /** * @author LianJiaYu * @date 2022/9/1 14:04 */ @Mapper(uses = {DataConversionWorker.class, EnumConversionWorker.class}) public interface UserConvert { UserConvert INSTANCE = Mappers.getMapper(UserConvert.class); //入参转换 @Mappings({ @Mapping(source = "account", target = "username"), @Mapping(source = "gender", target = "gender", qualifiedByName = "setGenderToInteger"), @Mapping(source = "birthday", target = "birthday", qualifiedByName = "getBirthdayToDate"), @Mapping(target = "defaultStatus", defaultValue = "success"), }) InUserInfoDto userInfoConvert(UserInfoParam param); //出参转换 @Mappings({ @Mapping(source = "username", target = "account"), @Mapping(source = "gender", target = "gender", qualifiedByName = "setGenderToString"), @Mapping(source = "birthday", target = "birthday", qualifiedByName = "getBirthdayToLong"), }) UserInfoResult userInfoResultConvert(OutUserInfoDto dto); ListResult<UserInfoResult> listUserInfoResultConvert(ListResult<OutUserInfoDto> list); }
5、定义时间戳转换日期和日期转时间戳方法
package com.lezu.springboot.common.conversion; import cn.hutool.core.date.DateUtil; import org.mapstruct.Named; import java.util.Date; /** * @author LianJiaYu * @date 2022/9/2 15:08 */ //@Component public class DataConversionWorker { @Named("getBirthdayToDate") public Date getBirthdayToDate(Long birthday) { if (birthday == null) { return null; } return DateUtil.date(birthday); } @Named("getBirthdayToLong") public Long getBirthdayToLong(Date birthday) { if (birthday == null) { return null; } return birthday.getTime(); } }
6、定义性别转换方法
package com.lezu.springboot.common.conversion; import com.lezu.springboot.enums.UserGenderEnum; import org.mapstruct.Named; import org.springframework.stereotype.Component; /** * @author LianJiaYu * @date 2022/9/2 15:08 */ //@Component public class EnumConversionWorker { @Named("setGenderToInteger") public Integer setGenderToInteger(String type) { return UserGenderEnum.getByType(type).getCode(); } @Named("setGenderToString") public Integer setGenderToString(Integer code) { return UserGenderEnum.getByCode(code).getCode(); } }
7、性别转换枚举
package com.lezu.springboot.enums; /** * @author LianJiaYu * @date 2022/9/16 10:10 */ public enum UserGenderEnum { FEMALE(0, "female"), MALE(1, "male"), UNKNOWN(2, "unknown"), ; private Integer code; private String type; UserGenderEnum(Integer code, String type) { this.code = code; this.type = type; } public Integer getCode() { return code; } public String getType() { return type; } public static UserGenderEnum getByCode(Integer code) { for (UserGenderEnum v : UserGenderEnum.values()) { if (v.getCode() == code) { return v; } } return UNKNOWN; } public static UserGenderEnum getByType(String type) { for (UserGenderEnum v : UserGenderEnum.values()) { if (v.getType().equals(type)) { return v; } } return UNKNOWN; } }
8、编写Controller代码进行测试
package com.lezu.springboot.controller; import com.alibaba.fastjson.JSON; import com.lezu.springboot.common.ListResult; import com.lezu.springboot.common.dto.Interface.UserConvert; import com.lezu.springboot.common.dto.in.InUserInfoDto; import com.lezu.springboot.common.dto.param.UserInfoParam; import com.lezu.springboot.common.dto.result.UserInfoResult; import com.lezu.springboot.enums.ResultEnum; import com.lezu.springboot.service.UserInfoHandleService; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Objects; /** * 高性能实体类转换工具MapStruct * 类型转换工具 * @author LianJiaYu * @date 2022/9/1 13:57 */ @RestController @RequestMapping("/mapstruct") @Slf4j public class MapstructController { @Autowired private UserInfoHandleService userInfoHandleService; @ApiOperation("类型转换") @PostMapping("/login") public ListResult<UserInfoResult> login(UserInfoParam params) { ListResult listResult = new ListResult(); if (Objects.isNull(params)) { return listResult.build(ResultEnum.PARAM_ERROR.getCode(), ResultEnum.PARAM_ERROR.getMsg()); } //入参-日志 log.info("params:" + JSON.toJSONString(params)); //入参-参数转换 InUserInfoDto inDto = UserConvert.INSTANCE.userInfoConvert(params); log.info("inDto:" + JSON.toJSONString(inDto)); //出参-参数转换 listResult = UserConvert.INSTANCE.outDtoToResult(userInfoHandleService.listByPage(inDto)); log.info("listResult:" + JSON.toJSONString(listResult)); return listResult; } }
Service层
@Override public ListResult listByPage(InUserInfoDto inDto) { ListResult listResult = new ListResult(); LambdaQueryWrapper<UserInfo> wrapper = Wrappers.lambdaQuery(); if (StrUtil.isNotBlank(inDto.getUsername())) { wrapper.like(UserInfo::getUsername, inDto.getUsername()); } int pageNum = inDto.getPageNum(); int pageSize = inDto.getPageSize() == 0 ? 10 : inDto.getPageSize(); IPage<UserInfo> page = new Page<>(pageNum, pageSize); userInfoService.page(page, wrapper); List<OutUserInfoDto> list = page.getRecords().stream().map(v -> { OutUserInfoDto dto = new OutUserInfoDto(); BeanUtils.copyProperties(v, dto); return dto; }).collect(Collectors.toList()); return listResult.ok(list, page.getTotal()); }
OutUserInfo实体类
package com.lezu.springboot.common.dto.out; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableLogic; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; /** * @Author LianJiaYu * @Date 2021/4/4 22:06 * @Version 1.0 */ @Data @AllArgsConstructor @NoArgsConstructor public class OutUserInfoDto implements Serializable { private static final long serialVersionUID = 6248490570574329534L; @ApiModelProperty(value = "主键id") @TableId(value = "id", type = IdType.AUTO) private Integer id; @ApiModelProperty(value = "用户账号") private String username; @ApiModelProperty(value = "性别") private String gender; @ApiModelProperty(value = "密码") private String password; @ApiModelProperty(value = "权限") private Integer power; @ApiModelProperty(value = "昵称") private String name; }
以上就是Java高性能实体类转换工具MapStruct的使用教程详解的详细内容,更多关于Java MapStruct实体类转换的资料请关注脚本之家其它相关文章!