网站管理后台文章排序,如何做360网站优化,wordpress 卡蜜,游戏币网站建设成本Gitee 仓库
https://gitee.com/Lin_DH/system
介绍
现状
为了让应用程序的代码更易于维护#xff0c;通常会将项目进行分层。在《阿里巴巴 Java 开发手册》中#xff0c;推荐分层如下图所示#xff1a; 每层都有对应的领域模型#xff0c;即不同类型的 Bean。
DO通常会将项目进行分层。在《阿里巴巴 Java 开发手册》中推荐分层如下图所示 每层都有对应的领域模型即不同类型的 Bean。
DOData Object与数据库表结构一一对应通过 DAO 层向上传输数据源对象。DTOData Transfer Object数据传输对象Service 或 Manager 向外传输的对象。BOBusiness Object业务对象由 Service 层输出的封装业务逻辑的对象。AOApplication Object应用对象在 Web 层与 Service 层之间抽象的复用对象模型极为贴近展示层复用度不高。VOView Object显示层对象通常是 Web 向模板渲染引擎层传输的对象。Query数据查询对象各层接收上层的查询请求。超过两个参数的查询封装禁止使用 Map 类进行传输。
痛点
由于代码分层的原因就会导致代码中有多种 Bean如 UserVOUserDTOUserDO 等并且经常发生各种 VO / DTO / DO 之间的转换。从而产生很多 vo.setUsername(dto.getUsername()) 的代码。当字段多了不仅容易出错而且很浪费开发时间。也有使用 BeanUtils.copyProperties() 进行转换这样虽然减少了开发时间和代码但依然存在问题。如1利用反射导致性能不好2不同名称的属性无法直接进行映射。
解决方案
本次使用的 Java 实体对象映射框架是 MapStruct 。MapStruct基于 JSR 269 的 Java 注解处理器用于生成类型安全高性能无依赖的 Bean 映射代码自动生成对象的代码使用便捷性能优越。
特点
1通过 getter / setter 进行字段拷贝而不是利用反射机制。2字段名称相同直接转换名称不同使用 Mapping 注解标识。
区别
与动态映射框架相比MapStruct 的优势
1使用普通的 getter / setter 方法而不是反射机制执行更快性能更好。2编译时类型安全。3清晰的错误提示信息。
依赖 pom.xml 需要引入 mapstruct 和 mapstruct-processor同时 scope 设置为 provided 即它只影响到编译测试阶段。
dependencygroupIdorg.mapstruct/groupIdartifactIdmapstruct/artifactIdversion1.5.0.Final/versionscopeprovided/scope
/dependencydependencygroupIdorg.mapstruct/groupIdartifactIdmapstruct-processor/artifactIdversion1.5.0.Final/versionscopeprovided/scope
/dependency代码实现
第一步编写 Student 实体类 Student.java package com.lm.system.common;import lombok.*;import java.io.Serializable;
import java.util.Date;/*** author DUHAOLIN* date 2024/11/12*/
Data
Builder
public class Student implements Serializable {private static final long serialVersionUID 1L;private Integer id;private String name;private Integer age;private String gender;private Date createTime;}
第二步编写 StudentVO 实体类 StudentVO.java package com.lm.system.common.dto;import lombok.Data;/*** author DUHAOLIN* date 2024/11/12*/
Data
public class StudentVO {private Integer userId;private String username;private Integer age;private String gender;}
第三步编写实体类转换接口 StudentConvert.java package com.lm.system.convert;import com.lm.system.common.Student;
import com.lm.system.common.dto.StudentVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;/*** author DUHAOLIN* date 2024/11/12*/
Mapper
public interface StudentConvert {/*** 获取该类自动生成的实体类实例*/StudentConvert INSTANCES Mappers.getMapper(StudentConvert.class);Mappings({Mapping(source id, target userId),Mapping(source name, target username)})StudentVO toStudentVO(Student student);}
第四步编写测试类 MapStructTest.java package com.lm.system.test;import com.lm.system.common.Student;
import com.lm.system.common.dto.StudentVO;
import com.lm.system.convert.StudentConvert;
import org.junit.Test;import java.util.Date;/*** author DUHAOLIN* date 2024/11/12*/
public class MapStructTest {Testpublic void testStudent() {Student student getStudent();System.out.println(student);StudentVO studentVO StudentConvert.INSTANCES.toStudentVO(student);System.out.println(studentVO);}private Student getStudent() {return Student.builder().id(1).name(Tom).age(18).gender(男).createTime(new Date()).build();}}
效果图 属性处理
简单属性
当 gender 传入的是男或女需要转换成对应的0或1再传入数据库时则需要进行处理。 StudentConvert.java Mappings({Mapping(source id, target userId),Mapping(source name, target username),Mapping(target gender, expression java(student.getGender() \男\ ? \0\ : \1\))
})
StudentVO toStudentVO(Student student);复杂属性
限制输入年龄的数值。 StudentConvert.java package com.lm.system.convert;import com.lm.system.common.Student;
import com.lm.system.common.dto.StudentVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;/*** author DUHAOLIN* date 2024/11/12*/
Mapper
public interface StudentConvert {/*** 获取该类自动生成的实体类实例*/StudentConvert INSTANCES Mappers.getMapper(StudentConvert.class);Mappings({Mapping(source id, target userId),Mapping(source name, target username),Mapping(target gender, expression java(student.getGender() \男\ ? \0\ : \1\)),Mapping(source age, target age, qualifiedByName transferAge)})StudentVO toStudentVO(Student student);Named(transferAge)default Integer transferAge(Integer age) {if (age 0) {return 0;}else if (age 120){return 120;}else {return age;}}} Spring中使用
如果在 Spring 中使用需要修改组件模型为 spring可以通过 pom.xml 参数修改也可以通过注解修改。修改后会在实现类上添加 Component 注解从而成为一个 Bean加入 Spring 容器中。 StudentConvert.java Mapper(componentModel spring)
public interface StudentConvert {}报错
如果遇到报错java.lang.NoSuchMethodError则在 IDEA 右侧的 Maven 选项中运行 clean 和 compile再进行重试。
项目结构图 参考链接
推荐一款Java实体映射工具—mapstruct【https://www.cnblogs.com/lvmengtian/p/14594185.html】 【springboot进阶】优雅使用 MapStruct 进行类复制【https://blog.csdn.net/lrb0677/article/details/127838138】 芋道 Spring Boot 对象转换 MapStruct 入门【https://www.iocoder.cn/Spring-Boot/MapStruct/?self】