| 
                         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 才更健全。                         (编辑:我爱故事小小网_铜陵站长网) 
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! 
                     |