美文网首页springboot
java对象转换看这篇就够了

java对象转换看这篇就够了

作者: 雨中星辰0 | 来源:发表于2021-09-30 10:42 被阅读0次

    java对象转换看这篇就够了

    概述

    我们在java开发过程中经常遇到对象属性拷贝的需求,总结一下,通常可以使用以下几种办法:

    1. 通过自定义编码方式
      • 优点:灵活、简单
      • 缺点:当大量不同的对象需要进行属性拷贝时,工作量大
      • 适用场景:少量的对象属性拷贝时
    2. 通过反射方式
      • 原理:通过反射方式获取对象的属性名,然后通过set方法设置对象属性
      • 优点:使用简单,可通过commons-beanutilsspring BeanUtils等工具进行转换
      • 缺点:只适合对象属性名一致时进行属性拷贝,当属性不一致时,仍需要手动处理
      • 适用场景:适合属性名称一致,但类不一致情况下进行属性拷贝
    3. 通过json方式
      • 原理:先将对象转为json字符串,再将json转为另一个类型
      • 优点:使用简单
      • 缺点:对象转换时,有一些转换逻辑时,不支持。
      • 适用场景:1. 类名不一样,但属性名一样时;2. 源类型和目标类型属性名,虽不一样,但是有对应关系时,可通过在源类型上面设置json的属性别名,进行转换。
    4. 通过mapstruct
      • 原理:在转换接口上面配置注解,mapstruct自动生成转换接口的实现。
      • 优点:基本能满足各种场景的对象转换
      • 缺点:框架较重,开发时偶尔出现,没有实时修改转换实现的情况。

    示例

    1. 自定义编码

      public static OperationHistory poseidonFileToTransferHistory(PoseidonFile file){
          OperationHistory operationHistory = new OperationHistory();
          operationHistory.setExtension(file.getExtension());
          operationHistory.setFileName(file.getFileName());
          operationHistory.setFileSize(file.getFileSize());
          operationHistory.setFileType(file.getFileType());
          operationHistory.setFullPath(file.getFullPath());
          operationHistory.setFileId(file.getId());
          operationHistory.setModifyDate(new Date());
          operationHistory.setParentId(file.getParentId());
          operationHistory.setReadableSize(file.getReadableSize());
          operationHistory.setUserid(file.getUserid());
          operationHistory.setUsername(file.getUsername());
          operationHistory.setIdPath(file.getIdPath());
          operationHistory.setStorePath(file.getStorePath());
          return operationHistory;
      }
      
    2. 反射

      示例使用的是commons-beanutils。

      pom依赖:

      <dependency>
          <groupId>commons-beanutils</groupId>
          <artifactId>commons-beanutils</artifactId>
          <version>1.9.3</version>
      </dependency>
      
      

      java示例:

      public static OperationHistory poseidonFileToTransferHistory2(PoseidonFile file ) throws InvocationTargetException, IllegalAccessException {
          OperationHistory operationHistory = new OperationHistory();
          BeanUtils.copyProperties(file, operationHistory);
          return operationHistory;
      }
      
    3. json

      示例的json工具用的是gson,其他json库也类似。

      pom依赖

      <dependency>
          <groupId>com.google.code.gson</groupId>
          <artifactId>gson</artifactId>
          <version>2.8.8</version>
      </dependency>
      

      java示例:

      public static OperationHistory poseidonFileToTransferHistory3(PoseidonFile file ) throws InvocationTargetException, IllegalAccessException {
          Gson gson = new Gson();
          String json = gson.toJson(file);
          return gson.fromJson(json, OperationHistory.class);
      }
      

      gson中也可以通过@SerializedName注解对属性重命名,这样就解决了源对象属性名与目标对象属性名不一致的问题

      import com.google.gson.annotations.SerializedName;
       
      public class User {
       
          private String account;
       
          @SerializedName("code")
          private String password;
       
          private String name;
       
          private int age;
       
          public String getAccount() {
              return account;
          }
       
          public void setAccount(String account) {
              this.account = account;
          }
       
          public String getPassword() {
              return password;
          }
       
          public void setPassword(String password) {
              this.password = password;
          }
       
          public String getName() {
              return name;
          }
       
          public void setName(String name) {
              this.name = name;
          }
       
          public int getAge() {
              return age;
          }
       
          public void setAge(int age) {
              this.age = age;
          }
       
          @Override
          public String toString() {
              return "User [account=" + account + ", password=" + password + ", name=" + name + ", age=" + age + "]";
          }
       
      }
      
      1. mapstruct

        由于mapstruct转换代码是自动生成的,所以配置略显复杂。

        maven配置:

        ...
        <properties>
            <org.mapstruct.version>1.5.0.Beta1</org.mapstruct.version>
        </properties>
        ...
        <dependencies>
            <dependency>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct</artifactId>
                <version>${org.mapstruct.version}</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.mapstruct</groupId>
                                <artifactId>mapstruct-processor</artifactId>
                                <version>${org.mapstruct.version}</version>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        ...
        

        idea配置:

        IntelliJ IDEA中安装MapStruct Support插件:File -> Settings -> Plugins 搜索 MapStruct support 安装,同时File -> Settings -> Compiler -> Annotation Processors 勾选“Enable annotation processing”

        还要确保您的项目使用的是 Java 1.8 或更高版本(项目属性→“Java 编译器”→“编译合规性级别”)。它不适用于旧版本。

        java示例:

        import org.mapstruct.Mapper;
        
        import org.mapstruct.Mapper;
        import org.mapstruct.Mapping;
        import org.mapstruct.Mappings;
        @Mapper
        public interface CarMapper {
            CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
              
              //当源类型与目标类型属性名不一致时
            @Mapping(target = "manufacturer", source = "make")
            @Mapping(target = "seatCount", source = "numberOfSeats")
            CarDto carToCarDto(Car car);
              
              //当源类型与目标类型属性名一致时
            @Mappings({})
            PersonDto personToPersonDto(Person person);
            
            @Override
            @Mappings({
            //当对象属性转换有一些规则时,可调用java方法进行转换,注意:这里的参数名应为方法定义时的参数名一致
            @Mapping(target = "service", expression = "java(toService(entity))"),
            @Mapping(target = "mocks", expression = "java(toMocks(entity))"),
            @Mapping(target = "params", expression = "java(toRule(entity))"),
            //当对象的属性需要依赖其他属性转换完后才能转换,可以使用dependsOn进行配置
            @Mapping(target = "url", dependsOn = {"service", "params"}, expression = "java(dto2URL(demotionDTO).toFullString())")})
            DemotionDTO update2DTO(DemotionUpdateParam entity);
            
           default String toService(DemotionUpdateParam entity) {
           return StringUtils.isEmpty(entity.getGroup()) ? entity.getServiceInf() : entity.getGroup() + "/" + entity.getServiceInf();
            }
            
           default Map<String, String> toMocks(DemotionUpdateParam entity) {
           return entity.getMocks()
              .stream()
              .filter(i -> StringUtils.split(i, "=").length > 1)
              .collect(Collectors.toMap(
                      i -> i.split("=")[0],
                      i -> i.split("=")[1]
                      )
              );
            }
            
           default String toRule(DemotionUpdateParam entity) {
           Map<String, String> map = toMocks(entity);
           return map.keySet().stream()
              .map(i -> i + "=" + URL.encode(map.get(i)))
              .collect(Collectors.joining("&"));
           }
        }
        

    相关文章

      网友评论

        本文标题:java对象转换看这篇就够了

        本文链接:https://www.haomeiwen.com/subject/ldcenltx.html