假设:
我们必须创建用于管理用户的REST层。
对我们来说,自然是创造两种方法:
我们从第一个开始,首先关注定义用户模型:名字,姓氏,年龄,国家,语言等。
到现在为止还挺好。接下来是获取用户详细信息的方法:名字,姓氏,年龄,国家,语言以及在用户注册期间设置的整箱其他值:id,用户所属的默认组,可能是角色(管理员,主持人?),用户注册时的日期时间等等。
我们会在一个类(用户模型)中设置有关用户的信息,但是为这些内部元素设置约束呢?例如:在两种情况下都需要和定义名字或姓氏(创建和获取),没关系,但是用户ID?在'create user'方法中不需要它(即使它是禁止的)但是get方法应该有这个字段。
最简单的方法是将用户模型拆分为两个类:UserBase包含所有必填字段(用于注册),User扩展UserBase用于其他情况。
这只是基于资源实现良好的REST服务的要求:创建新资源(用户):POST ../users获取资源(用户):GET ../users/{id}
处理此问题的最佳做法是什么?
我已经回答了类似的问题here。为REST API提供专用的模型类将为您提供更长的灵活性,并带来一些好处。提一下:
可以避免将持久性模型映射到REST API模型的样板代码:可以使用many mapping frameworks来实现此目的。例如,看看MapStruct,它是基于注释的,并作为Maven注释处理器。
还要考虑Lombok为你生成getters,setters,equals()
,hashcode()
和toString()
方法。
对于复杂的应用程序,我倾向于创建一个包含用户需要的所有内容的User类,然后添加一个与User相关的新层,该层只包含该类操作所需的数据。
我称这个新的层为DTO。
然后我有一个第三方库,就像User和DTO对象之间的模型映射器一样。我有使用ModelMapper的好经验。
例如,如果我有一个Order类作为模型层中的主类,而另一个类OrderDTO只显示特定操作所需的信息,则映射的工作方式如下:
// Assume getters and setters on each class
class Order {
Customer customer;
Address billingAddress;
}
class Customer {
Name name;
}
class Name {
String firstName;
String lastName;
}
class Address {
String street;
String city;
}
和OrderDTO:
// Assume getters and setters
class OrderDTO {
String customerFirstName;
String customerLastName;
String billingStreet;
String billingCity;
}
要玩这两个我只需要:
ModelMapper modelMapper = new ModelMapper();
OrderDTO orderDTO = modelMapper.map(order, OrderDTO.class);
不是每个人都喜欢DTO方法,但我认为这是最灵活的做事方式,特别是如果应用程序变得复杂的话。
现在,关于验证。我倾向于使用来自javax.validation.constraints
的注释来注释User类,并验证BindingResult
是否存在任何错误。