BeanUtils.copyProperties 是一个浅拷贝方法,复制属性时,我们只需要把 DTO 对象和要转化的对象两个的属性值设置为一样的名称,并且保证一样的类型就可以了。如果你在做 DTO 转化的时候一直使用 set 进行属性赋值,那么请尝试这种方式简化代码,让代码更加清晰!
转化的语义
上边的转化过程,读者看后肯定觉得优雅很多,但是我们再写 Java 代码时,更多的需要考虑语义的操作,再看上边的代码:
- User user = new User();
- BeanUtils.copyProperties(userInputDTO,user);
虽然这段代码很好的简化和优化了代码,但是他的语义是有问题的,我们需要提现一个转化过程才好,所以代码改成如下:
- @PostMapping
- public User addUser(UserInputDTO userInputDTO){
- User user = convertFor(userInputDTO);
- return userService.addUser(user);
- }
- private User convertFor(UserInputDTO userInputDTO){
- User user = new User();
- BeanUtils.copyProperties(userInputDTO,user);
- return user;
- }
这是一个更好的语义写法,虽然他麻烦了些,但是可读性大大增加了,在写代码时,我们应该尽量把语义层次差不多的放到一个方法中,比如:
- User user = convertFor(userInputDTO);
- return userService.addUser(user);
这两段代码都没有暴露实现,都是在讲如何在同一个方法中,做一组相同层次的语义操作,而不是暴露具体的实现。
如上所述,是一种重构方式,读者可以参考 Martin Fowler 的《Refactoring Imporving the Design of Existing Code》(重构 改善既有代码的设计) 这本书中的 Extract Method 重构方式。
抽象接口定义
当实际工作中,完成了几个 API 的 DTO 转化时,我们会发现,这样的操作有很多很多,那么应该定义好一个接口,让所有这样的操作都有规则的进行。
如果接口被定义以后,那么 convertFor 这个方法的语义将产生变化,它将是一个实现类。
看一下抽象后的接口:
- public interface DTOConvert<S,T> {
- T convert(S s);
- }
虽然这个接口很简单,但是这里告诉我们一个事情,要去使用泛型,如果你是一个优秀的 Java 程序员,请为你想做的抽象接口,做好泛型吧。
我们再来看接口实现:
- public class UserInputDTOConvert implements DTOConvert {
- @Override
- public User convert(UserInputDTO userInputDTO) {
- User user = new User();
- BeanUtils.copyProperties(userInputDTO,user);
- return user;
- }
- }
我们这样重构后,我们发现现在的代码是如此的简洁,并且那么的规范:
- @RequestMapping("/v1/api/user")
- @RestController
- public class UserApi {
- @Autowired
- private UserService userService;
- @PostMapping
- public User addUser(UserInputDTO userInputDTO){
- User user = new UserInputDTOConvert().convert(userInputDTO);
- return userService.addUser(user);
- }
- }
review code
如果你是一个优秀的 Java 程序员,我相信你应该和我一样,已经数次重复 review 过自己的代码很多次了。
我们再看这个保存用户的例子,你将发现,API 中返回值是有些问题的,问题就在于不应该直接返回 User 实体,因为如果这样的话,就暴露了太多实体相关的信息,这样的返回值是不安全的,所以我们更应该返回一个 DTO 对象,我们可称它为 UserOutputDTO:
- @PostMapping
- public UserOutputDTO addUser(UserInputDTO userInputDTO){
- User user = new UserInputDTOConvert().convert(userInputDTO);
- User saveUserResult = userService.addUser(user);
- UserOutputDTO result = new UserOutDTOConvert().convertToUser(saveUserResult);
- return result;
- }
这样你的 API 才更健全。 (编辑:晋中站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|