Spring Controller: используйте доменные объекты как @RequestBody - PullRequest
7 голосов
/ 12 августа 2011

У меня есть класс объектов домена 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), например UserRequest, который содержит только поля, которые я хочу предоставить через API REST, и сопоставить их (т. е. с 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 голосов
/ 12 августа 2011

Есть еще один вариант - вы можете запретить отправку заданного набора свойств, используя DataBinder.setDisallowedFields(..) (или используя .setAllowedFields(..))

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

Это нормальноесли у вас есть одно или два свойства, которые отличаются.

В противном случае наличие специального объекта (например, ProfileDetails или UserRequest) имеет больше смысла.Я использую такой DTO-подобный объект для этого сценария, а затем переношу поля с BeanUtils.copyProperties(..) из commons-beanutils

Третий, возможно, лучший вариант, это поместить все связанные с профилем поля в отдельный объект(сопоставляется с @OneToOne с пользователем) или с объектом @Embeddable и используется вместо него.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...