Spring MVC, REST и HATEOAS - PullRequest
       21

Spring MVC, REST и HATEOAS

23 голосов
/ 24 августа 2011

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

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

В настоящее время у меня есть прекрасно составленное приложение MVC без HATEOAS.Доменные сущности - это чистые POJO без каких-либо представлений или веб-концепций.Например:

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 / что угодно в среде разрешения представления Spring.Одним из способов сделать это может быть обертывание рассматриваемого POJO с помощью универсального класса Resource, который содержит список ссылок.Некоторая подстройка представления потребовалась бы, чтобы сжать это в формат, который я хочу, но это выполнимоК сожалению, вложенные ресурсы не могут быть упакованы таким образом.Другие вещи, которые приходят на ум, включают добавление ссылок на ModelAndView, а затем настройку каждого из готовых преобразователей представления Spring для вставки ссылок в сгенерированный JSON / XML / etc.Чего я не хочу, так это постоянно создавать вручную JSON / XML / и т. Д.для размещения различных ссылок по мере их появления в процессе разработки.

Мысли?

Ответы [ 4 ]

10 голосов
/ 30 ноября 2012

На 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
1 голос
/ 15 августа 2012

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

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

1 голос
/ 24 августа 2011

Мои мысли:

  • с использованием какого-либо соглашения о присвоении имен, так что, например, URL-адрес собственной ссылки может быть создан из имени класса объекта.
  • Я недумаю, что добавление ссылок должно быть добавлено контроллером (кстати, вы сами написали: «Я не хочу, чтобы мои контроллеры были загрязнены конструкциями представления». Я бы попытался найти способ расширить сериализацию JSON, чтобы он автоматически добавилдополнительные вещи. Возможно, вам понадобится добавить аннотации к вашим сущностям, даже если это немного их загрязнит.
0 голосов
/ 19 сентября 2016

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

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), которое вы можете установить в entityObject.

...