Spring Controller:使用域对象作为@RequestBody [英] Spring Controller: use domain objects as @RequestBody

查看:262
本文介绍了Spring Controller:使用域对象作为@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:


  1. 使用域对象并保护不允许用户修改的字段(例如,将其设置为null或手动设置为默认值)

  2. 使用一组新的辅助对象(类似于DTO),例如UserRequest,它只包含我想通过REST API公开的字段,并映射它们(即用推土机)到域对象。

  1. 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)
  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆