java springboot中,PO、BO、VO等转换工具

java后端代码中,经常会涉及到各种属性基本相同对象的转换过程,常见的如PO、BO、VO等。通常,后端开发规范中,会要求PO对象只能应用在DAO层,BO对象应用在service层,VO对象应用在web层;
为了方便代码的管理以及增加代码的可读性,我们需要一个统一的Convert工具类;为了应对不同业务对象,以及Convert工具类的方法统一,我们定义一个泛型接口;

1.泛型接口,用于不同的业务对象转换


/**
 * @Author win
 * @Description
 * @Date 2023/7/10 13:44
 */
public interface Converter<P,B,V> {
    B voToBo(V v) throws Exception;
    default List<B> voListToBoList(List<V> voList) throws Exception{
        List<B> boList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(voList)) {
            for (V v : voList) {
                boList.add(voToBo(v));
            }
        }
        return boList;
    }

    V boToVo(B b) throws Exception;

    default List<V> boListToVoList(List<B> boList) throws Exception{
        List<V> voList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(boList)) {
            for (B b : boList) {
                voList.add(boToVo(b));
            }
        }
        return voList;
    }

    P boToPo(B b) throws Exception;
    default List<P> boListToPoList(List<B> boList) throws Exception{
        List<P> poList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(boList)) {
            for (B b : boList) {
                poList.add(boToPo(b));
            }
        }
        return poList;
    }

    B poToBo(P p) throws Exception;

    default List<B> poListToBoList(List<P> poList) throws Exception{
        List<B> boList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(poList)) {
            for (P p : poList) {
                boList.add(poToBo(p));
            }
        }
        return boList;
    }

}

A:Converter接口中,使用了三个泛型类,P、B、V,分别代表PO、BO、VO的类;
B:XXXConverter工具类实现Converter接口,重写接口中的voToBo等方法;
C:利用java8中,接口中使用default 关键字修饰方法,把默认的集合转换方法先定义好,XXXConverter不需要重写这一部分代码,可以直接调用。

2.定义UserConverter工具类,实现Converter接口

import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @Author win
 * @Description
 * @Date 2023/7/10 13:55
 */
@Component("userConverer")
public class UserConverter implements Converter<UserPO, UserBO, UserVO>{
    @Override
    public UserBO voToBo(UserVO vo) throws Exception {
       UserBO bo = new UserBO ();
        if (vo != null) {
        	bo.setUserName(vo.getUserName()); 
            ...
            //其他属性的赋值
            //或者直接使用spring bean中的  BeanUtils.copyProperties(vo , bo);
        }
        return bo;
    }

    @Override
    public UserVO boToVo(UserBO bo) throws Exception {
         UserVO vo = new UserVO ();
        if (bo != null) {
             //属性的赋值
        }
        return vo;
    }

    @Override
    public UserPO boToPo(UserBO bo) throws Exception {
        UserPO po = new UserPO();
        if (bo != null) {
          //属性的赋值
        }
        return po;
    }

    @Override
    public UserBO poToBo(UserPO po) throws Exception {
        UserBO bo = new UserBO ();
        if (po != null) {
         //属性的赋值
        }
        return bo;
    }
}

以上,就能UserConverter 就能将PO、BO、VO互相转换;在类上,使用@Component注解,将UserConverter 对象放到springBean容器中管理;

3.方法调用

在view层或者是service层就能通过 @Autowired或者 @Resource自动注入XXXConverter 为属性。
下面以Controller层为例:

@RestController
@RequestMapping(value = "/v1/user", produces = "application/json;charset=UTF-8")
public class UserController {
	@Resource
    private UserConverter userConverter;
    @Resource
    private UserService userservice;
    
    @RequestMapping(value = "/add_user", method = RequestMethod.POST)
    public Result addUser(@RequestBody UserVO userVO) {
        Result result = new Result();
        //vo转换成bo
       UserBO bo =  userConverter.voToBo(userVO);
       //调用业务层
       userservice.add(bo);
       return result;
    }
}

当我们的服务中,存在很多的Converter实体类时,在同一个Controller或者Service中,需要注入多个类似于UserConverter 的属性时,会让代码看起来比较的臃肿。

4.ConverterFactory泛型工厂,实现ApplicationContextAware接口

当某一个Controller或者Service需要多个Converter 时,用Factory的来管理这些Converter 对象,只要调用Factory中的某个方法,就可以获得某个指定的Converter 工具类;
使用泛型边界设置,限制Factory只允许获取Converter实体类对象

/**
 * 说明: 将spring bean对象转换成静态变量;当前类只作用于Converter接口的子类
 *
 * @Author: win
 * @Description:
 * @Date 2023/4/21 15:43
 */
@Component
public class ConverterFactory<T extends Converter> implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    /**
     * 方法说明: 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.
     *
     * @param applicationContext
     * @return void
     * @date 2023/5/31 18:16
     * @author win
     */
    public void setApplicationContext(ApplicationContext applicationContext) {
        ConverterFactory.applicationContext = applicationContext;
    }

    /**
     * 方法说明: 取得存储在静态变量中的ApplicationContext.
     *
     * @param
     * @return org.springframework.context.ApplicationContext
     * @date 2023/5/31 18:15
     * @author win
     */
    public static ApplicationContext getApplicationContext() {
        checkApplicationContext();
        return applicationContext;
    }

    /**
     * 方法说明: 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
     *
     * @param name 可以通过枚举,定义beanName;在UserConverter中的@Component("userConverer"),userConverer即是bean的名字;但是这个名字有可能会重复,
     * @return T
     * @date 2023/5/31 18:14
     * @author win
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        checkApplicationContext();
        return (T) applicationContext.getBean(name);
    }

    /**
     * 方法说明: 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型;如果有多个Bean符合Class, 取出第一个.
     *
     * @param clazz
     * @return T
     * @date 2023/5/31 18:15
     * @author win
     */
    @SuppressWarnings("unchecked")
    public static <T extends Converter> T getBean(Class<T> clazz) {
        checkApplicationContext();
        @SuppressWarnings("rawtypes")
        Map beanMaps = applicationContext.getBeansOfType(clazz);
        if (beanMaps != null && !beanMaps.isEmpty()) {
            return (T) beanMaps.values().iterator().next();
        } else {
            return null;
        }
    }

    private static void checkApplicationContext() {
        if (applicationContext == null) {
            throw new IllegalStateException("applicationContext未注入");
        }
    }
}

此时,修改UserController中的调用方法

@RestController
@RequestMapping(value = "/v1/user", produces = "application/json;charset=UTF-8")
public class UserController {
    @Resource
    private UserService userservice;
   
    @RequestMapping(value = "/add_user", method = RequestMethod.POST)
    public Result addUser(@RequestBody UserVO userVO) {
        Result result = new Result();
        //vo转换成bo
       UserBO bo =  ConverterFactory.getBean(UserConverter.class).voToBo(userVO)
       //调用业务层
       userservice.add(bo);
       return result;
    }
}

至此,在代码中都可以使用 ConverterFactory.getBean(XXXConverter.class)调用XXXConverter中的所有方法,也包括Converter接口中的voListToBoList(voList)等集合转换方法。
注:ConverterFactory中限制用T extends Converter限制边界,未完全测试,有可能有问题。望大佬指教!!!

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java,可以使用以下两种方式实现PO(Persistent Object)和VO(Value Object)之间的转换: 1. 手动转换 手动转换是最基本的方式,即通过编写转换代码将PO对象转换VO对象或将VO对象转换PO对象。手动转换的优点是灵活性高,可以根据具体需求定制转换过程,缺点是比较繁琐,需要写大量的转换代码。 例如,下面是一个将PO对象转换VO对象的示例代码: ``` public class UserPO { private Long id; private String name; private Integer age; //省略getter和setter方法 } public class UserVO { private Long id; private String name; private Integer age; //省略getter和setter方法 } public class UserConverter { public static UserVO convertToVO(UserPO po) { UserVO vo = new UserVO(); vo.setId(po.getId()); vo.setName(po.getName()); vo.setAge(po.getAge()); return vo; } } ``` 2. 使用第三方库 除了手动转换外,还可以使用一些第三方库来简化转换过程。常用的库有Dozer、ModelMapper、BeanUtils等。这些库可以通过反射机制自动完成对象属性的映射,避免了手动编写转换代码的繁琐过程。 例如,使用Dozer库实现PO对象到VO对象的转换代码如下: ``` public class UserPO { private Long id; private String name; private Integer age; //省略getter和setter方法 } public class UserVO { private Long id; private String name; private Integer age; //省略getter和setter方法 } public class UserConverter { private static Mapper mapper = DozerBeanMapperBuilder.buildDefault(); public static UserVO convertToVO(UserPO po) { UserVO vo = mapper.map(po, UserVO.class); return vo; } } ``` 使用第三方库的优点是可以大幅减少转换代码的编写量,提高开发效率,但缺点是可能会引入额外的依赖,增加项目的复杂度。另外,不同的库有不同的特点和适用场景,需要根据具体情况选择合适的库。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值