REST — обновление частичных данных

В настоящее время я программирую службу REST и веб-сайт, который в основном использует эту службу REST.

Модель:

public class User {
    private String realname;
    private String username;
    private String emailAddress;
    private String password;
    private Role role;
    ..
}

Вид:

Одна форма для обновления

  • настоящее имя
  • Адрес электронной почты
  • имя пользователя

Еще одна форма для обновления роли

И третья форма для смены пароля

.

Сосредоточившись на первом представлении, какой шаблон был бы хорошей практикой?

PUT /user/{userId}

imho не потому, что форма содержит только частичные данные (не роль, не пароль). Поэтому он не может отправить весь пользовательский объект.

ИСПРАВЛЕНИЕ /user/{userId}

может быть в порядке. Это хороший способ реализовать его, например:

1) прочитать текущий пользовательский объект

2)

if(source.getRealname() != null) // Check if field was set (partial update)
dest.setRealname(source.getRealname());
.. for all available fields

3) спасти место назначения

POST /user/{userId}/generalInformation

как сводка для реального имени, электронной почты, имени пользователя

.

Благодарю вас!


person NoobieNoob    schedule 18.12.2016    source источник


Ответы (2)


Одна из проблем с этим подходом заключается в том, что пользователь не может аннулировать необязательные поля, поскольку код не применяет значение, если (ввод пуст, а значение) равно нулю. Это может быть нормально для пароля или другого обязательного поля объекта, но, например, если у вас есть необязательное поле Note, пользователь не может «очистить» это поле.

Кроме того, если вы используете простую форму, вы не можете использовать метод PATCH, только GET или POST.

Если вы используете Ajax, вас могут заинтересовать JSON Merge Patch (проще) и/или < исправление href="https://tools.ietf.org/html/rfc6902" rel="nofollow noreferrer">JavaScript Object Notation (JSON) (наиболее полное); обзор проблем, возникающих при частичном обновлении и использовании PATCH, см. также эта страница.

Дело в том, что форма может отправлять только пустое или заполненное значение, а свойство объекта JSON может иметь три состояния: значение (обновление), ноль (установить нуль) и отсутствие свойства (игнорировать).

Я с успехом использовал реализацию ZJSONPATCH.

person Testo Testini    schedule 18.12.2016
comment
Спасибо. Я уже использую JSON (сериализованная html-форма). Мне очень нравится патчный подход. Вы когда-нибудь использовали для этого какой-либо Java API? - person NoobieNoob; 18.12.2016

Сосредоточившись на первом представлении, какой шаблон был бы хорошей практикой?

Мое предложение начинается с простой идеи: как бы вы сделали это как веб-страницы в HTML?

Вы, вероятно, начинаете со страницы, которая предлагает представление пользователя с такими гиперссылками, как «Обновить профиль», «Обновить роль», «Изменить пароль». При нажатии на профиль обновления будет загружена html-форма, возможно, с уже заполненными значениями по умолчанию. Оператор внесет изменения, затем отправит форму, которая отправит сообщение на конечную точку, которая знает, как расшифровать тело сообщения и обновить модель.

Первые два шага «безопасны» — оператор не предлагает никаких изменений. На последнем этапе оператор предлагает изменение, поэтому безопасные методы не подходят.

HTML, как формат гипермедиа, ограничен двумя методами (GET, POST), поэтому мы можем увидеть, как браузер делает что-то вроде

GET  /user/:id
GET  /forms/updateGeneralInformation?:id
POST /updates/generalInformation/:id

Существует множество вариантов написания, которые вы можете использовать, в зависимости от того, как вы предпочитаете организовывать свои ресурсы. Браузеру все равно, потому что он просто переходит по ссылкам.

У вас есть такая же гибкость в вашем API. Первым трюком в наборе всегда должно быть «могу ли я решить это с новым ресурсом?».

Ян Робинсон заметил: специализация и инновации зависят от открытого множества. Если вы ограничиваете себя закрытым словарем HTTP-методов, то открытый набор, который вам нужно внедрять, должен лежать где-то еще: подход RESTful заключается в использовании открытого набора ресурсов.

Обновление профиля действительно похоже на операцию, которая должна быть идемпотентной, поэтому вы хотели бы использовать PUT, если можете. Что-то не так с:

GET /user/:id/generalInformation
PUT /user/:id/generalInformation

Это запись, это идемпотент, это полная замена ресурса generalInformation, так что спецификация HTTP довольна.

Да, изменение текущего представления нескольких ресурсов с помощью одного запроса допустимо для HTTP. На самом деле это один из подходов, описанных в RFC 7231.

Частичные обновления содержимого возможны путем нацеливания на отдельно идентифицированный ресурс, состояние которого перекрывает часть более крупного ресурса.

Если вам не нравится поддержка нескольких представлений ресурса и поддержка PUT для каждого из них, вы можете применить ту же эвристику («добавить больше ресурсов»), введя очередь команд для обработки изменений базовой модели.

GET /user/:id/generalInformation
PUT /changeRequests/:uuid

Вам решать, хотите ли вы представлять все запросы на изменение как записи в одной коллекции или иметь специализированные коллекции запросов на изменение для подмножеств операций. Помидор, помидор.

person VoiceOfUnreason    schedule 19.12.2016