【问题标题】:Spring Controller: use domain objects as @RequestBodySpring Controller:使用域对象作为@RequestBody
【发布时间】:2011-10-25 19:11:42
【问题描述】:

我有一个域对象类User(它是一个 JPA 实体):

@Entity
public class User {
   private String name;
   private boolean enabled = true;
   // getters/setters
}

我正在尝试提供一个 REST API 以允许客户端使用 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是否是一个好主意,因为我必须保护一些不应由客户端直接修改的字段(即在本例中为“启用”)。

这些替代方案的优缺点是什么:

  1. 使用域对象并保护不允许用户修改的字段(例如手动将它们设置为 null 或默认值)
  2. 使用一组新的辅助对象(类似于 DTO),例如仅包含我想通过 REST API 公开的字段的 UserRequest,并将它们映射(即使用 @ 987654321@) 到域对象。

第二种选择如下所示:

@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);
            ...
    }
}

有没有其他方法可以避免代码重复,更容易维护?

【问题讨论】:

    标签: java rest jpa spring-mvc


    【解决方案1】:

    还有另一个选项 - 您可以禁止提交给定的一组属性,使用 DataBinder.setDisallowedFields(..)(或使用 .setAllowedFields(..)

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.setDisallowedFields(..);
    }
    

    如果您有一两个不同的属性,这很好。

    否则,拥有一个特殊的对象(如ProfileDetailsUserRequest)更有意义。我在这种情况下使用了这样一个类似 DTO 的对象,然后从 commons-beanutils 传输带有BeanUtils.copyProperties(..) 的字段

    第三种可能更好的选择是将所有与配置文件相关的字段放入一个单独的实体(与用户一起使用 @OneToOne 映射)或 @Embeddable 对象,然后使用它。

    【讨论】:

    • 博卓的回答很好,谢谢。您如何看待创建 Disallowed 注释来注释您不想公开的字段(我认为 Spring 不提供类似的东西)并调用 binder.setDisallowedFields(MyUtils.findDisallowedFields(User.class))?允许的注释可能更安全。
    • 对不起,打扰了。你认为这是一个使用某种 AOP 切入点的好地方吗?
    • 听起来更像是 WebBindingInitializer 的工作
    • @Bozho 我听说 initbinder 不能与 RequestBody 一起使用。我也尝试这样做,它没有设置 bindingResult.getSuppressedFields()。你能帮忙吗?还有其他事情要做吗?
    猜你喜欢
    • 2011-12-05
    • 2020-09-05
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 2017-09-15
    • 2014-08-05
    • 2017-08-23
    相关资源
    最近更新 更多