Подтвердить что ты не робот

Spring MVC, REST и HATEOAS

Я изо всех сил стараюсь внедрить службы Spring MVC 3.x RESTful с HATEOAS. Рассмотрим следующие ограничения:

  • Я не хочу, чтобы мои объекты домена загрязнялись конструкциями web/rest.
  • Я не хочу, чтобы мои контроллеры были загрязнены конструкциями представлений.
  • Я хочу поддерживать несколько видов.

В настоящее время у меня есть хорошее приложение MVC без HATEOAS. Объекты домена - это чистые POJO без каких-либо взглядов или встроенных понятий web/rest. Например:

class User {
   public String getName() {...}
   public String setName(String name) {...}
   ...
}

Мои контроллеры также просты. Они обеспечивают маршрутизацию и статус, а также делегируют в рамки разрешения Spring. Обратите внимание, что мое приложение поддерживает JSON, XML и HTML, но никакие объекты или контроллеры домена не имеют встроенной информации о просмотре:

@Controller
@RequestMapping("/users")
class UserController {

  @RequestMapping
  public ModelAndView getAllUsers() {
    List<User> users = userRepository.findAll();
    return new ModelAndView("users/index", "users", users);
  }

  @RequestMapping("/{id}")
  public ModelAndView getUser(@PathVariable Long id) {
    User user = userRepository.findById(id);
    return new ModelAndView("users/show", "user", user);
  }
}

Итак, теперь моя проблема - я не уверен в чистом способе поддержки HATEOAS. Вот пример. Скажем, когда клиент запрашивает пользователя в формате JSON, он выглядит следующим образом:

{
  firstName: "John",
  lastName: "Smith"
}

Предположим также, что когда я поддерживаю HATEOAS, я хочу, чтобы JSON содержал простую ссылку "self", которую клиент может использовать для обновления объекта, удаления его или чего-то еще. У него также может быть ссылка "друзей", указывающая, как получить список пользователей:

{
  firstName: "John",
  lastName: "Smith",
  links: [
    {
      rel: "self",
      ref: "http://myserver/users/1"
    },
    {
      rel: "friends",
      ref: "http://myserver/users/1/friends"
    }
  ]
}

Как-то я хочу привязать ссылки к моему объекту. Я считаю, что правильное место для этого - в уровне контроллера, поскольку все контроллеры знают правильные URL-адреса. Кроме того, поскольку я поддерживаю несколько представлений, я чувствую, что все правильно, это как-то украсить объекты моего домена в контроллере, прежде чем они будут преобразованы в JSON/XML/что угодно в рамки разрешения w760. Один из способов сделать это может заключаться в том, чтобы связать POJO с общим классом ресурсов, который содержит список ссылок. Для того, чтобы хрустнуть в формат, который я хочу, потребуется некоторое изменение настроек, но его выполнимость. К сожалению, вложенные ресурсы не могут быть обернуты таким образом. Другие вещи, которые приходят на ум, включают добавление ссылок на ModelAndView, а затем настройку каждого из Spring готовых решений для отображения ссылок на созданный JSON/XML/и т.д. Я не хочу постоянно обрабатывать JSON/XML и т.д. для размещения различных ссылок, когда они приходят и уходят в процессе развития.

Мысли?

4b9b3361

Ответ 1

В GitHub есть полезный проект под названием Spring HATEOAS, который имеет следующее описание:

"Этот проект предоставляет некоторые API для облегчения создания представлений REST которые следуют принципу HATEOAS при работе с Spring и особенно Spring MVC"

Если класс ресурса, который вы возвращаете, расширяет "ResourceSupport", вы можете легко добавлять к нему ссылки, и вы можете создавать ссылки с помощью "ControllerLinkBuilder", например, чтобы добавить ссылку на себя:

import static org.sfw.hateoas.mvc.ControllerLinkBuilder.*;

Link link = linkTo(YourController.class).slash(resource.getName()).withSelfRel();
resource.add(link);

Это совершенно новый проект, но он доступен из публичного репозитория Maven при необходимости:

<dependency>
    <groupId>org.springframework.hateoas</groupId>
    <artifactId>spring-hateoas</artifactId>
    <version>0.3.0.RELEASE</version>
</dependency>

Если вы используете артефакт maven:

org.sfw.hateoas.mvc.ControllerLinkBuilder

становится:

org.springframework.hateoas.mvc.ControllerLinkBuilder

Ответ 2

Мои мысли:

  • используя какое-то соглашение об именах, так что, например, собственный ссылочный url может быть построен из имени класса объекта.
  • Я не думаю, что добавление материалов ссылок должно быть добавлено контроллером (кстати, вы сами писали "Я не хочу, чтобы мои контроллеры были загрязнены конструкциями представлений". Я попытался бы найти способ расширить сериализацию JSON так что он автоматически добавит дополнительные материалы. Может потребоваться добавить некоторые аннотации к вашим объектам, даже если это немного их загрязнит.

Ответ 3

Просто наткнулся на это, ища что-то еще и подумал, что вы должны рассматривать использование заголовка Link вместо содержимого в теле JSON, которое действительно просто загрязняет представления ваших ресурсов.

Обратите внимание на заметку IETFs на веб-ссылку, а также реестр IANA отношений связи.

Ответ 4

Чтобы создать ссылку в REST api, вы можете использовать проект HAETOAS структуры Spring.

org.springframework.hateoas.mvc.ControllerLinkBuilder класс имеет набор методов, которые вы можете использовать для построения ссылки типа -

Link link=linkTo(PersonControllerImpl.class).slash(null).withSelfRel();

Также, если у вас есть метод контроллера с аннотацией @RequestMapping с некоторым значением URI -

@RequestMapping(value = "/customer", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity<?> getCustomer() {

//...
}

то вы можете создать ссылку с использованием значения URI метода как -

linkTo(methodOn(PersonControllerImpl.class).getCustomer()).toUri().toString()

он вернет значение String (http://www.urhost.com/customer), которое вы можете установить в entity Object.