Я собираюсь приступить к разработке нового api для отдыха в Java. Мой вопрос об использовании PATCH - Почему?В java REST API, используя PATCH vs PUT для обновления объекта
Допустим, у нас есть объект с именем Address.java
public class Address {
@Id
private Long id
@NotNull
private String line1;
private String line2; //optional
@NotNull
private String city;
@NotNull
private String state;
}
Чтобы создать новый адрес, я хотел бы сделать этот запрос HTTP:
POST http://localhost:8080/addresses
со следующей просьбой:
{
"line1" : "mandatory Address line 1",
"line2" : "optional Address line 2",
"city" : "mandatory City",
"state" : "cd"
}
Предположим, что запись создана с идентификатором 1
Соответствующий @RestController AddressResource.java будет иметь этот метод:
@PostMapping(value = "/addresses")
public ResponseEntity<Address> create(@valid Address newAddress) {
addressRepo.save(newAddress);
}
@valid обеспечит предприятие является действительным до сохранения данных в таблицу.
Теперь предположим, что я перехожу из своей квартиры наверх в дом по улице. Если я использую заплату, он становится
PATCH http://localhost:8080/addresses/1
с запросом полезной нагрузки:
{
"line1" : "1234 NewAddressDownTheStreet ST",
"line2" : null
}
Соответствующий метод @RestController будет:
@PatchMapping(value = "/addresses/{id}")
public ResponseEntity<Address> patchAddress(@PathVariable Long id, Address partialAddress)
{
Address dbAddress = addressRepo.findOne(id);
if (partialAddress.getLine1() != null) {
dbAddress.setLine1(partialAddress.getLine1());
}
if (partialAddress.getLine2() != null) {
dbAddress.setLine2(partialAddress.getLine2());
}
if (partialAddress.getCity() != null) {
dbAddress.setCity(partialAddress.getCity());
}
if (partialAddress.getState() != null) {
dbAddress.setState(partialAddress.getState());
}
addressRepo.save(dbAddress)
}
Теперь, если вы запрашиваете таблицу, выиграл» t мой адрес будет?
"line1" : "1234 NewAddressDownTheStreet ST",
"line2" : "optional Address line 2", <-- INCORRECT. Should be null.
"city" : "mandatory City",
"state" : "cd"
Как видно, приведенное выше обновление приводит к неправильному значению для строки2. Это потому, что в Java все переменные экземпляра в классе Address обнуляются (или по умолчанию начальные значения, если они примитивы) при создании экземпляра класса. Таким образом, нет возможности различать между изменением строки 2 на нуль от значения по умолчанию.
Вопрос 1) Есть ли стандартный способ обойти это?
Другой недостаток заключается в том, что я не могу использовать @Valid аннотации для подтверждения запроса на точке входа - сог это лишь частично. Таким образом, недопустимые данные могут попасть в систему.
Например, представьте, там было дополнительное поле со следующим определением:
@Min(0)
@Max(100)
private Integer lengthOfResidencyInYears,
И пользователь случайно набрал 190 (если они на самом деле имел в виду 19 лет), она не подведет.
Вместо PATCH, если бы я использовал PUT, клиенту необходимо было бы отправить полный адресный объект. Это имеет то преимущество, что я могу использовать @Valid, чтобы убедиться, что адрес действительно действует
Если один делает предпосылку, что GET должен всегда быть сделано, прежде чем делать какие-либо обновления, почему бы один использовать PUT над PATCH? Я что-то упустил?
Помимо
Мой вывод состоит в том, что разработчики, использующие динамически типизированных языков являются сторонниками использования PATCH, как я не вижу никакой пользы для его использования из статически типизированный язык строки Java или C#. Похоже, что это еще больше усложняет.
похоже, что статус действителен, после запроса PATCH ваш запрос db должен показывать строку: «дополнительная строка адреса 2», так как вы проверяете, partialAddress.getLine2()! = Null. – kuhajeyan
Патч-запрос должен содержать инструкции, рассчитанные клиентом, который сервер может использовать для преобразования состояния A некоторого ресурса в состояние B и является не только упрощенным частичным обновлением. Дальнейшее чтение: [SO documentation] (http://stackoverflow.com/documentation/http/3423/http-for-apis/11812/edit-a-resource#t=201610031245323472567) и [хорошее сообщение в блоге] (http://williamdurand.fr/2014/02/14/please-do-not-patch-like-an-idiot/) –
Это хороший вопрос. Что касается нулевой строки в строке2, то именно потому, что вы вручную сопоставляете свои поля и проверяете ненулевые значения, чтобы перезаписать. В настоящее время я работаю над проектом, в котором мы используем [Dozer] (http://dozer.sourceforge.net/documentation/usage.html), и вы можете выбрать отображение нулей. В любом случае мы используем POST для добавления/создания ресурсов и PUT для их изменения, однако с помощью этого mapper он может выполнять частичные сопоставления. Поэтому я обсуждаю, является ли это предпочтительным способом, или я должен использовать POST (создание), PUT (полное обновление), PATCH (частичное обновление). –