SpringBoot中VO/DTO/PO的具体使用

 更新时间:2024年03月17日 09:22:03   作者:tang_seven  
VO/DTO/PO等实体类中字段常常会存在多数相同,根据业务需求少数不同,本文主要介绍了SpringBoot中VO/DTO/PO的具体使用,感兴趣的可以了解一下

1.概念叙述

  • VO:View Object,主要用于展示层。它的作用是把某个指定前端页面的所有数据封装起来。他的作用主要是减少传输数据量大小和保护数据库隐私数据(如用户密码、用户邮箱等相关信息)不外泄,同时保护数据库的结构不外泄。
  • DTO:Data Transfer Object,数据传输对象,用于展示层与服务层之间的数据传输对象。(注:实际开发中还存在BO,其作用和DTO类似,当业务逻辑不复杂时一般会被合并。)
  • PO:Persistant Object,持久化对象,和数据库形成映射关系。简单说PO就是每一个数据库中的数据表,一个字段对应PO中的一个变量。(也就是我们常用的Entities)

几者之间的关系如下图:

从前端页面中收到JSON格式数据,后端接口中将其封装为一个VO对象;接口接收到VO对象后将其转换为DTO对象,并调用业务类方法对其进行处理;然后处理为PO对象,调用Dao接口连接数据库进行数据访问(查询、插入、更新等)。

后端从数据库得到结果后,根据Dao接口将结果映射为PO对象,然后调用业务类方法将其转换为需要的DTO对象,再根据前端页面实际需求,转换为VO对象进行返回。

2.类型转换

上述过程中,VO/DTO/PO等实体类中字段常常会存在多数相同,根据业务需求少数不同。为避免频繁的set和get操作对其进行转换,spring为我们提供了多种方法。

(1)使用BeanUtils:(springframework包下)

UserDto user = new UserDto ();
BeanUtils.copyProperties(userInfo ,user ,new String[]{"birthday"});

上述代码中,意思是将左边UserInfo实体类(可以视为一个VO对象)和UserDto实体类类(可以视为一个DTO对象)中一样的值进行赋值user对象中,new String[]{""}中是跳过赋值的字段,该属性可以为空。

(2)使用BeanUtils:(Apache包下)

UserDto user = new UserDto ();
BeanUtils.copyProperties(user,userInfo);

上述代码中,意思是将右边UserInfo实体类(可以视为一个VO对象)和UserDto实体类类(可以视为一个DTO对象)中一样的值进行赋值user对象中。(和spring包下方法相反)

(3)使用modelMapper:

导入依赖:

        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>2.3.9</version>
        </dependency>

配置文件:

@Configuration
public class ModelMapperConfig {

    private Converter<Date, String> dateToStringConverter = new AbstractConverter<Date, String>() {
        @Override
        protected String convert(Date date) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            return date == null ? null : simpleDateFormat.format(date);
        }
    };

    @Bean
    public ModelMapper modelMapper() {
        ModelMapper modelMapper = new ModelMapper();

        // 官方配置说明: http://modelmapper.org/user-manual/configuration/
        // 完全匹配
        modelMapper.getConfiguration().setFullTypeMatchingRequired(true);

        // 匹配策略使用严格模式
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);

        modelMapper.addConverter(dateToStringConverter);

        configureUser(modelMapper);

        return modelMapper;
    }

    private void configureUser(ModelMapper modelMapper) {
        //将dto转为UserAccount实体类
        modelMapper.typeMap(UserInfor.class, UserAccount.class)
                .addMappings(mapper -> mapper.map(UserInfor::getUsername, UserAccount::setUsername))
                .addMappings(mapper -> mapper.map(UserInfor::getPassword, UserAccount::setPassword));

}

使用:

UserAccount account= modelMapper.map(userInfo,UserAccount.class);

上述代码,根据配置文件中configureUser方法中配置的字段,将两个实体类中的字段进行复制赋值。

3.使用实例

下面我们模拟一个业务:后端接口从前端中接收到用户注册数据,进行注册;前端调用查询接口,获取用户的数据。

首先,我们定义VO、DTO、PO对象:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserInfo implements Serializable {
    //该实体类为封装好的前端传输页面VO对象
    @NotBlank(message = "用户名不能为空")
    private String Username;
    @NotBlank(message = "密码不能为空")
    private String Password;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDTO implements Serializable {
    //该实体类为业务处理DTO对象
    private int Account;
    private String Username;
    private String Password;
    private String Roles;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("user_account")
public class UserAccount implements Serializable {
    //该实体类为用户账号表对应PO对象
    @TableId
    private int SerialNum;
    private int Account;
    private String Username;
    private String Password;
    private String Roles;
    private String status;
    private String registerDate;
}

然后,我们编写用户注册相关代码(基于springboot+mybatis plus),由于使用mybatis plus,此处省略mapper层代码,仅展示serviceImpl和controller中代码。

控制层:

    //用户注册
    @PostMapping("/register")
    public CommonResult<Object> userRegister(@RequestBody @Valid UserInfo user){
        int result = userService.userRegister(user);
        if(result!=0){
            return CommonResult.success(result);
        }else {
            return CommonResult.fail(result);
        }
    }

业务处理:

    @Override
    public int userRegister(UserInfo user) {
        if(accountMapper.selectCount(new QueryWrapper<UserAccount>().eq("username",user.getUsername()))!=0){
            log.info("用户名已存在");
            return 0;
        }
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(userDTO,user);
        //加密密码
        Md5Hash md5Hash = new Md5Hash(userDTO.getPassword(), userDTO.getUsername(),2);
        userDTO.setPassword(md5Hash.toString());
        //模拟生成账号
        userDTO.setAccount(12345678);
        //赋予权限
        userDTO.setRoles("user");
        return accountMapper.insert(userDTO);
    }

最终,我们可以往数据库中传入一条用户刚注册的账号数据,status和RegisterDate等属性取数据库设置好的默认值。

然后,我们再定义一个VO用于展示用户的信息:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserVo implements Serializable {
    //该VO用于展示用户信息,去除了用户密码等敏感信息
    private int serialNum;
    private int account;
    private String username;
}

进行用户信息的查询,获取所有的用户账号:

业务层:

    public List<UserAccount> getAllUser() {
        return accountMapper.selectList(null);
    }

控制层:

    @GetMapping("/get/all")
    public CommonResult<Object> getAllAccount() throws InvocationTargetException, IllegalAccessException {
        //查询所有数据
        List<UserAccount> userAccountList = userService.getAllUser();
        List<AdminInfo> resultList = new ArrayList<>();
        //封装为VO进行展示
        for(UserAccount u:userAccountList){
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(userVo,u);
            resultList.add(userVo);
        }
        //根据序列号进行排序,后注册的放在最前面
        resultList.sort(new Comparator<UserVo>() {
            @Override
            public int compare(UserVo o1, UserVo o2) {
                return o2.getSerialNum() - o1.getSerialNum();
            }
        });
        return new CommonResult<>(200,"账号列表如下:",resultList,resultList.size());
    }

然后我们就可查询得到所有的去除了敏感信息可用于展示的用户账号信息。

注:此处由于业务简单,没有将PO对象转换为DTO再转换为VO。

到此这篇关于SpringBoot中VO/DTO/PO的具体使用的文章就介绍到这了,更多相关SpringBoot VO/DTO/PO内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 浅谈Java中Properties类的详细使用

    浅谈Java中Properties类的详细使用

    properties类继承自hashtable,通常和io流结合使用。它最突出的特点是将key/value作为配置属性写入到配置文件中以实现配置持久化,或从配置文件中读取这些属性。它的这些配置文件的规范后缀名为".properties"。表示了一个持久的属性集
    2021-06-06
  • 使用SpringBoot中的Schedule定时发送邮件的方法

    使用SpringBoot中的Schedule定时发送邮件的方法

    在SpringBoot中,你可以使用@Scheduled注解来创建定时任务,@Scheduled注解可以应用于方法上,表示这个方法是一个定时任务,可以根据指定的时间间隔或固定时间执行,本文就给大家介绍一下如何使用SpringBoot中的Schedule定时发送邮件,需要的朋友可以参考下
    2023-08-08
  • Java用自带的Image IO给图片添加水印

    Java用自带的Image IO给图片添加水印

    本文主要介绍了如何采用Java自带的Image IO实现图片添加水印的需求,并整合了一些其他功能,感兴趣的朋友可以参考下
    2021-06-06
  • 基于SpringMVC接受JSON参数详解及常见错误总结

    基于SpringMVC接受JSON参数详解及常见错误总结

    下面小编就为大家分享一篇基于SpringMVC接受JSON参数详解及常见错误总结,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • 详解Java单元测试Junit框架实例

    详解Java单元测试Junit框架实例

    这篇文章主要介绍了Java的异常测试框架JUnit使用上手指南,JUnit是Java代码进行单元测试中的常用工具,需要的朋友可以参考下
    2017-04-04
  • SpringBoot 中常用注解及各种注解作用

    SpringBoot 中常用注解及各种注解作用

    本篇文章将介绍几种SpringBoot 中常用注解及各个注解的作用,感兴趣的朋友跟随脚本之家小编一起学习吧
    2018-03-03
  • 详解springboot + profile(不同环境读取不同配置)

    详解springboot + profile(不同环境读取不同配置)

    本篇文章主要介绍了springboot + profile(不同环境读取不同配置),具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • 解决SpringBoot web项目启动后立即关闭的问题

    解决SpringBoot web项目启动后立即关闭的问题

    这篇文章主要介绍了解决SpringBoot web项目启动后立即关闭的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Java C++题解leetcode902最大为N的数字组合数位DP

    Java C++题解leetcode902最大为N的数字组合数位DP

    这篇文章主要为大家介绍了Java C++题解leetcode902最大为N的数字组合数位DP,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • Spring循环依赖的解决方案详解

    Spring循环依赖的解决方案详解

    这篇文章将用实例为大家详细介绍了介绍如何解决Spring的循环依赖问题,文中的示例代码讲解详细,对我们学习Spring有一定的帮助,需要的可以参考一下
    2022-07-07

最新评论