Spring Controller:使用域对象作为@RequestBody [英] Spring Controller: use domain objects as @RequestBody
问题描述
我有一个域对象类用户
(它是一个JPA实体):
I have a domain object class User
(it is a JPA entity):
@Entity
public class User {
private String name;
private boolean enabled = true;
// getters/setters
}
我试图提供一个REST API允许客户端使用Spring 3 MVC创建新用户:
And I am trying to offer a REST API to allow clients to create new users, using Spring 3 MVC:
@Controller
public class UserController {
@RequestMapping(value="/user", method=RequestMethod.POST)
@ResponseBody
public String createRealm(@RequestBody User user) {
user.setEnabled(true); // client is not allowed to modify this field
userService.createUser(user);
...
}
}
效果很好,但是我不知道将域对象用作@RequestBody 是否是一个好主意,因为我必须保护一些不应被客户端直接修改的字段(即启用)案例)。
It works great, but I do not know if it is a good idea to use the domain objects as @RequestBody, because I have to protect some fields that should not be directly modified by the client (i.e. "enabled" in this case).
这些替代方案的优缺点是什么:
What are the pros/cons of these alternatives:
- 使用域对象并保护不允许用户修改的字段(例如,将其设置为null或手动设置为默认值)
- 使用一组新的辅助对象(类似于DTO),例如UserRequest,它只包含我想通过REST API公开的字段,并映射它们(即用推土机)到域对象。
- Use the domain objects and protect the fields the user is not allowed to modify (for example set them to null or to its default value by hand)
- Use a new set of auxiliar objects (something similar to a DTO), such as a UserRequest that only contains the fields I want to expose through the REST API, and map them (i.e. with Dozer) to the domain objects.
第二种选择如下:
@Entity
public class User {
private String name;
private boolean enabled = true;
// getters/setters
}
public class UserRequest {
private String name;
// enabled is removed
// getters/setters
}
@Controller
public class UserController {
@RequestMapping(value="/user", method=RequestMethod.POST)
@ResponseBody
public String createRealm(@RequestBody UserRequest userRequest) {
User user = ... // map UserRequest -> User
userService.createUser(user);
...
}
}
还有其他吗?避免代码重复并且更容易维护的方法?
Is there any other way that avoids code duplication and is easier to maintain?
推荐答案
还有另一种选择 - 你可以禁止提交一个给定的集合属性,使用 DataBinder.setDisallowedFields(..)
(或使用 .setAllowedFields(..)
)
There is another option - you can disallow the submission of a given set of properties, using the DataBinder.setDisallowedFields(..)
(or using .setAllowedFields(..)
)
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields(..);
}
如果您有一个或两个不同的属性,这没关系。
This is fine if you have one or two properties that differ.
否则,有一个特殊对象(如 ProfileDetails
或 UserRequest
)更有意义。我在这个场景中使用这样一个类似DTO的对象,然后从commons-beanutils
Otherwise, having a special object (like ProfileDetails
or UserRequest
) makes more sense. I am using such a DTO-like object for this scenario and then transfer the fields with BeanUtils.copyProperties(..)
from commons-beanutils
第三个,也许是更好的选择,是将所有与配置文件相关的字段放入一个单独的实体(用 @OneToOne
与用户映射)或者 @Embeddable
对象,并改为使用它。
A third, perhaps better option, is to put all profile-related fields into a separate entity (mapped with @OneToOne
with user) or to an @Embeddable
object, and use it instead.
这篇关于Spring Controller:使用域对象作为@RequestBody的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!