对象转换小工具

  1. DTO (Data Transfer Object):
    DTO is a design pattern used to transfer data between different layers or components of an application. It is a simple object that carries data and has no behavior logic. DTOs are often used in distributed systems or when data needs to be transferred between remote services. They serve as a container for data that needs to be exchanged between different parts of the system and are commonly used to encapsulate data fetched from a database or received from external services.

DTOs typically have properties that represent the data being transferred, and they may also provide methods for accessing and manipulating the data. They are usually designed to be serializable so that they can be easily transmitted over a network or stored in a persistent storage system.

  1. VO (Value Object):
    VO, also known as a value object, is a design pattern used to represent an immutable object that holds values and is primarily used for modeling concepts or entities within a domain. Value objects are characterized by their immutability, meaning their state cannot be modified once created. They are usually used to encapsulate a set of related attributes or properties that form a coherent value.

Value objects are often used to represent concepts like dates, coordinates, addresses, or any other concept that can be defined by its values rather than its identity. They are typically used to enforce business rules and ensure that the values they hold remain consistent and unchanged.

通常需要将DTO中的属性搬运到VO中,再发送给前端进行页面展示:

 public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {

        response.setContentType("application/json;charset=utf-8");


        User user=(User)authentication.getPrincipal();
        AuthorizeVO vo =new AuthorizeVO();
        Account account=service.findAccountByNameOrEmail(user.getUsername());
        String token =utils.createJwt(user,account.getId(),account.getUsername());

        vo.setExpire(utils.expireTime());
        vo.setRole(account.getRole());
        vo.setToken(token);
        vo.setUsername(account.getUsername());

        response.getWriter().write(RestBean.success(vo).asJsonString());
        System.out.println(RestBean.success(token).asJsonString());
    }

可以看到这样的搬运不太方便

spring提供了一个方便的办法,beanutils中的copyproperties方法能够将前一个对象中的属性拷贝到后一个对象中:


        BeanUtils.copyProperties(account,vo);

        vo.setExpire(utils.expireTime());
//        vo.setRole(account.getRole());
        vo.setToken(token);
//        vo.setUsername(account.getUsername());

我们尝试手动显现这个功能

在entity包下编写basedata接口,account继承basedata接口中的方法,快速的将dto转换成vo对象:

package com.example.entity;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public interface BaseData {
    default <V> V asViewObject(Class<V> clazz) {
        try {
            //获取vo中的fields并创建新的vo实例
            Field[] declaredFields = clazz.getDeclaredFields();
            Constructor<V> constructor = clazz.getConstructor();
            V v = constructor.newInstance();
            //对于vo中的每一个属性,在当前dto如果存在则赋值给vo
            for (Field declaredField : declaredFields) {
                convert(declaredField,v);
            }
            return v;

        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }

    }

    private void convert(Field field, Object vo) {
        try {
            // 获取当前DTO类中与VO中存在的属性同名的字段
            Field source = this.getClass().getDeclaredField(field.getName());

            // 设置字段可访问(即使是私有字段)
            field.setAccessible(true);
            source.setAccessible(true);

            // 从当前DTO对象中获取对应字段的值,并将其设置到VO对象中的相应字段中
            field.set(vo, source.get(this));
        } catch (NoSuchFieldException e) {
            // 如果字段不存在,则抛出运行时异常
            System.out.println(e);
//            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            // 如果访问字段时发生非法访问异常,则抛出运行时异常
//            throw new RuntimeException(e);
            System.out.println(e);
        }
    }
}

In a broader context, the Consumer<V> functional interface’s effect is to enable you to define a piece of behavior or an action that operates on an object of type V (the input argument) without returning any result. The Consumer<V> interface represents a function that accepts an object and performs some operation on it.

但有额外的信息需要传入viewobject,通过consumer接口构造匿名函数使得整体更简约:

 AuthorizeVO vo=account.asViewObject(AuthorizeVO.class,viewobject->{
            viewobject.setExpire(utils.expireTime());
            viewobject.setToken(token);
        });
default <V> V asViewObject(Class<V> clazz, Consumer <V> consumer) {
        V v=this.asViewObject(clazz);
        consumer.accept(v);
        return v;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

湿物男

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值