Сопоставление пути REST Spring Boot

Я просто думаю, как лучше всего создать отображение PATH для службы отдыха. Допустим, у нас есть следующие пути:

/users POST
/users/1 PATCH, GET
/users/1/contacts GET, POST
/users/1/contacts/1 GET, PATCH

Вопрос в том, как лучше всего создавать контроллеры. Например, у нас есть UserController, куда мы технически можем поместить все эти сопоставления. Или - мы должны создать отдельные контроллеры (UserController, ContactsController). f.e UserController ниже, если мы все поместим под.

@RequestMapping("users")
@RestController
public class UserController {

    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<Void> createUser() {}

    @RequestMapping(method = RequestMethod.GET)
    public User getUser() {}

    @RequestMapping(value = "{id}/contacts", method = RequestMethod.GET)
    public List<Contact> getContacts() {}

    @RequestMapping(value = "{id}/contacts", method = RequestMethod.POST)
    public ResponseEntity<Void> createContact() {}

    .....
}

А если мы создадим отдельные контроллеры, как тогда должны быть организованы пути? Наверное, глупый вопрос, но буду рад, если кто-нибудь поделится опытом.


person comprex    schedule 11.10.2016    source источник
comment
Я поклонник отдельных контроллеров, поскольку они удаляют связь между пользователями и контактами (например) - что, если позже вы захотите использовать контакты в отдельном контексте? (т.е. независимо от пользователя, которому они принадлежат)   -  person blurfus    schedule 11.10.2016


Ответы (2)


Предположим, что количество объектов, связанных с пользователем, в будущем увеличится. Итак, очевидно, что лучше разделить его по сущностям:

UserController -> UserService -> UserRepository,

ContactController -> ContactService -> ContactRepository,

FriendshipController -> FriendshipService -> FriendshipRepository

По моему опыту, пользовательский контроллер

@RestController
@RequestMapping("/user")
public class UserController extends AbstractController {

...

   @RequestMapping(method = RequestMethod.POST)
   public ResponseEntity<?> createUser(@RequestHeader("X-Auth-Token") Optional<String> @RequestBody User user) {

...

   @RequestMapping(method = RequestMethod.GET)
   public ResponseEntity<?> listUsers(@RequestHeader("X-Auth-Token") Optional<String> authToken) {
...

связанные с пользовательской областью Контроллер дружбы:

@RestController
@RequestMapping("/user/{id}")
public class FriendshipController extends AbstractController {

...

@RequestMapping(value = "/friendship/code", method = RequestMethod.POST)
    public ResponseEntity<?> generateCodeForUser(@PathVariable("id") long id) {

...

 @RequestMapping(value = "/friendship/code", method = RequestMethod.GET)
    public ResponseEntity<?> retrieveCodeForUser(@PathVariable("id") long id) {

...

Не уверен, что это аксиома, но помогите мне организовать мой код.

person Sergii Getman    schedule 11.10.2016
comment
Я бы даже предложил, чтобы отображение контроллера дружбы было @RequestMapping("/user/{id}/friendship"), а затем все остальные сопоставления были упрощены до /code - person blurfus; 11.10.2016

Я поклонник отдельных контроллеров, поскольку они удаляют связь между Users и Contacts (например) - что, если позже вы захотите использовать Contacts в отдельном контексте? (т.е. независимо от User, которым они принадлежат)

Если бы они были разделены, пути были бы очень похожи на то, что у вас есть:

Пользователи

/users GET, POST
/users/{user-id} PATCH, GET

Контакты

/contacts GET, POST
/contacts/{contact-id} GET, PATCH

Если есть зависимость между Contacts и Users (и в этом случае похоже, что она есть), вы можете получить это так:

/contacts/for-user/{user-id} GET, POST
/contacts/for-user/{user-id}/{contact-id} GET, PATCH

Это позволяет добавлять контакты к другим объектам (не только к пользователям), а пользователей к другим контекстам (независимо от их контактов).

Например, пользователи кофеварки

/coffee-maker/users GET

Или, если кофеварка выйдет из строя, к кому обратиться за ремонтом?

/coffee-maker/contacts GET

Вероятно, контакт по ремонту кофеварки также является Пользователем (но не обязательно)

Еще одна вещь, вы можете перевернуть ее и сказать, что контакт предназначен для прибора (например, кофеварки).

  /contact/for-appliance/{appliance-id} GET

Я хочу сказать, что если вы отделяете контакты от пользователей, вы можете назначать контакты другим объектам вместо того, чтобы устанавливать отношения User -> Contacts - если, конечно, вы не хотите разъединять их из-за бизнес-правил или по какой-то причине.

В любом случае имейте в виду, что существует множество способов сопоставления

person blurfus    schedule 11.10.2016