首页 文章

Spring Controller:使用域对象作为@RequestBody

提问于
浏览
7

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

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

我正在尝试使用Spring 3 MVC提供REST API以允许客户端创建新用户:

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

它工作得很好,但我不知道 use the domain objects as @RequestBody 是否是一个好主意,因为我必须保护一些不应由客户端直接修改的字段(在本例中为"enabled") .

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

  • 使用 domain objects 并保护不允许用户修改的字段(例如,将它们设置为null或手动设置为默认值)

  • 使用 new set of auxiliar objects (类似于DTO的东西),例如仅包含我想通过REST API公开的字段的UserRequest,并将它们(即使用Dozer)映射到域对象 .

第二种选择如下:

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

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

1 回答

  • 6

    还有另一种选择 - 您可以使用DataBinder.setDisallowedFields(..)(或使用 .setAllowedFields(..) )禁止提交给定的属性集

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

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

    否则,拥有一个特殊对象(如 ProfileDetailsUserRequest )会更有意义 . 我在这个场景中使用这样一个类似DTO的对象,然后使用 BeanUtils.copyProperties(..) 从commons-beanutils传输字段

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

相关问题