1:实体对象的转换
①:使用到的jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--hutool jar-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.0.7</version>
</dependency>
<!--dozer jar-->
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.4.0</version>
</dependency>
<!-- mapStruct 对象转换 -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.2.0.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.2.0.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
②:工具类
package com.itsource.enjoy.util;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.itsource.enjoy.domain.entity.Score;
import com.itsource.enjoy.domain.entity.Student;
import com.itsource.enjoy.domain.vo.ScoreVo;
import com.itsource.enjoy.domain.vo.StudentVo;
import org.dozer.DozerBeanMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.cglib.beans.BeanCopier;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* 对象属性赋值的多种方式
*/
public class BeanCopyTemplateUtils {
/**
* apache的BeanUtil.copyProperties 可以实现,但是性能差而且容易出异常,很多规范严禁使用这种途径
* 大多数情况下 MapStruct 性能最高。类似于lombok ,Mapstruct都是在编译期进行实现,所以一般不存在运行时性能问题,mapStruct 最终调用的是setter和getter 方法,而非反射。这也是其性能比较好的原因之一
* get set 的方式进行转换的方式很简单,但是有一个很验证的问题就是会导致代码过于臃肿,会出现大量的属性值赋值,大量的get set方法充斥着业务逻辑
* BeanCopier是cglib包下的一个类,默认的情况下,它会进行同名,同类型属性的copier,如果类型不同,或者名称不同的化,会报错,我们可以通过实现自定义Convert的形式进行类型转换
*
* @param args
*/
public static void main(String[] args) {
//将studentVo中的属性赋值给student
StudentVo studentVo = new StudentVo()
.setName("小花")
.setAge(18)
.setType("1")
.setSex(false)
.setBirthDay(DateUtil.date())
.setScores(new ArrayList<Score>() {{
add(new Score().setSubjectType("语文").setSubjectScore(131.0));
add(new Score().setSubjectType("英语").setSubjectScore(111.0));
}});
// //方式一:使用hutool中的convert (属性相同的情况下不论是集合还是属性都能赋值,不同的属性需要手动赋值)
Student student1 = Convert.convert(Student.class, studentVo)
.setStatus(studentVo.getType());
// //打印结果 Student(name=小花, age=18, sex=false, birthDay=2021-11-15 10:49:23, scores=[Score(subjectScore=131.0, subjectType=语文), Score(subjectScore=111.0, subjectType=英语)], status=1)
// //方式二:使用Spring的BeanUtils (属性相同的情况下不论是集合还是属性都能赋值,不同的属性需要手动映射) 源对象, 目标对象
Student student2 = new Student();
BeanUtils.copyProperties(studentVo,student2.setStatus(studentVo.getType()));
// //Student(name=小花, age=18, sex=false, birthDay=2021-11-15 11:26:37, scores=[Score(subjectScore=131.0, subjectType=语文, hasExam=null), Score(subjectScore=111.0, subjectType=英语, hasExam=null)], status=1)
//方式三: 使用 hutool中的JSONUtil 将对象转为json字符串然后再转对象
final Student student3 = JSONUtil.toBean(JSONUtil.toJsonStr(studentVo), Student.class);
//Student(name=小花, age=18, sex=false, birthDay=Mon Nov 15 12:10:20 CST 2021, scores=[Score(subjectScore=131.0, subjectType=语文, hasExam=null), Score(subjectScore=111.0, subjectType=英语, hasExam=null)], status=null)
//方式四 使用dozer,推土机 会打印很多日志
DozerBeanMapper beanMapper = new DozerBeanMapper();
Student student4 = new Student();
beanMapper.map(studentVo,student4);
//Student(name=小花, age=18, sex=false, birthDay=Mon Nov 15 13:25:22 CST 2021, scores=[Score(subjectScore=131.0, subjectType=语文, hasExam=null), Score(subjectScore=111.0, subjectType=英语, hasExam=null)], status=null)
//方式五 BeanCopier(不建议使用) Spring的cglib包下
Student student5 = new Student();
BeanCopier copier = BeanCopier.create(StudentVo.class, Student.class, false);
copier.copy(studentVo, student5, null);
//方式六:MapStruct 附上部分代码
//方式七:直接getter、setter方法
Student student7 = new Student()
.setName(studentVo.getName())
.setAge(studentVo.getAge())
.setScores(studentVo.getScores());
//延伸集合赋值
List<Score> scores = new ArrayList<Score>() {{
add(new Score().setSubjectType("语文").setSubjectScore(131.0).setHasExam(true));
add(new Score().setSubjectType("英语").setSubjectScore(111.0).setHasExam(false));
}};
//也能实现转成list集合
//Collection<?> scoreVos = Convert.toCollection(List.class, ScoreVo.class, scores);
List<ScoreVo> scoreVos = Convert.toList(ScoreVo.class, scores);
//属性名称不一样 [ScoreVo(subjectScore=131.0, subjectType=语文, enableExam=null), ScoreVo(subjectScore=111.0, subjectType=英语, enableExam=null)]
scoreVos.forEach(scoreVo -> {
scores.forEach(score -> {
if(Objects.equals(scoreVo.getSubjectType(),score.getSubjectType())){
scoreVo.setEnableExam(score.getHasExam());
}
});
});
//属性名称不一样 手动赋值 [ScoreVo(subjectScore=131.0, subjectType=语文, enableExam=true), ScoreVo(subjectScore=111.0, subjectType=英语, enableExam=false)]
System.err.println(scoreVos);
}
}
③:使用到的实体
package com.itsource.enjoy.domain.entity;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
import java.util.List;
/**
* 学生类
*/
@Accessors(chain = true)
@Data
public class Student {
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 性别
*/
private Boolean sex;
/**
* 生日
*/
private Date birthDay;
/**
* 成绩集合
*/
private List<Score> scores;
/**
* 状态类型
*/
private String status;
}
package com.itsource.enjoy.domain.vo;
import com.itsource.enjoy.domain.entity.Score;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
import java.util.List;
@Accessors(chain = true)
@Data
public class StudentVo {
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 性别
*/
private Boolean sex;
/**
* 生日
*/
private Date birthDay;
/**
* 成绩集合
*/
private List<Score> scores;
/**
* 状态类型
*/
private String type;
}
package com.itsource.enjoy.domain.entity;
import lombok.Data;
import lombok.experimental.Accessors;
/**
-
成绩
*/
@Accessors(chain = true)
@Data
public class Score {/**
- 学科分数
*/
private Double subjectScore;
/**
- 学科类型
*/
private String subjectType;
/**
- 是否必考
*/
private Boolean hasExam;
- 学科分数
}
package com.itsource.enjoy.domain.vo;
import lombok.Data;
import lombok.experimental.Accessors;
/**
-
成绩
*/
@Accessors(chain = true)
@Data
public class ScoreVo {/**
- 学科分数
*/
private Double subjectScore;
/**
- 学科类型
*/
private String subjectType;
/**
- 是否必考
*/
private Boolean enableExam;
- 学科分数
}
④:方式6的补充
package com.itsource.enjoy.util;
import com.itsource.enjoy.domain.entity.Student;
import com.itsource.enjoy.domain.vo.StudentVo;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.springframework.stereotype.Component;
@Component
@Mapper(componentModel = "spring")
public interface UtilStruct {
@Mappings({
@Mapping(target = "name",source = "name"),
@Mapping(target = "age",source = "age"),
@Mapping(source = "sex",target = "sex"),
@Mapping(target = "birthDay",source = "birthDay"),
@Mapping(source = "scores",target = "scores"),
@Mapping(source = "type",target = "status")
})
Student convertToStudent(StudentVo studentVo);
}
package com.itsource.enjoy.controller;
import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.itsource.enjoy.common.ResponseRawBody;
import com.itsource.enjoy.domain.dto.MessageParamDto;
import com.itsource.enjoy.domain.entity.Score;
import com.itsource.enjoy.domain.entity.Student;
import com.itsource.enjoy.domain.vo.MessageResultVo;
import com.itsource.enjoy.domain.vo.StudentVo;
import com.itsource.enjoy.util.UtilStruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 测试MapStruct
*/
@Validated
@RequestMapping("/message")
@RestController
public class MessageProvideController {
@Autowired
private UtilStruct utilStruct;
@ResponseRawBody
@GetMapping("/test")
public Student queryInfo(){
StudentVo studentVo = new StudentVo()
.setName("小花")
.setAge(18)
.setType("1")
.setSex(false)
.setBirthDay(DateUtil.date())
.setScores(new ArrayList<Score>() {{
add(new Score().setSubjectType("语文").setSubjectScore(131.0));
add(new Score().setSubjectType("英语").setSubjectScore(111.0));
}});
Student student = utilStruct.convertToStudent(studentVo);
System.err.println(student);
//Student(name=小花, age=18, sex=false, birthDay=2021-11-15 14:37:29, scores=[Score(subjectScore=131.0, subjectType=语文, hasExam=null), Score(subjectScore=111.0, subjectType=英语, hasExam=null)], status=1)
return student;
}
}