2016-01-09 2 views
0

практика Предположим, что у меня есть очень простой User класс:Джерси: Лучший обработки успокоительный HTTP PUT (обновление) запрос

@JsonIgnoreProperties({"password", "created", "lastModified"}) 
public class User { 
    public String id; 
    public String name; 
    public String password 
    public Long created; 
    public Long lastModified; 
} 

Когда мы сериализовать User объект в JSON строку, мы отфильтровывать password, created и lastModified. И затем пользователь в передней части обновит имя пользователя и вернет пользователя обратно в нашу службу Restful.

И мой псевдо метод контроллера обработки PUT запрос:

@Path("/user/{id}") 
@POST 
@Consumes(MediaType.APPLICATION_JSON) 
public void saveUpdate(@PathParam("id")String id, User user) { 
    userService.save(user); 
} 

В приведенном выше методе я ожидаю Джексон десериализации строку JSON, посланный передним концом к user например POJO, а затем позвоните в нашу службу, чтобы сохранить экземпляр.

Пока все выглядит круто. Однако беспокойство возникает, когда мы передаем user POJO на номер userService, чтобы сохранить его. Помните, что у нас есть три свойства, которые игнорируются, когда мы сериализуем user в JSON: password, created, lastModified, и мы должны получить значение этих недостающих свойств из базы данных, а затем объединить с данными, отправленными с передней стороны.

Выполнение операции слияния - очень простая, но утомительная задача для кодера. Мне было интересно, есть ли какие-либо хорошие методы для легкого и изящного решения этого случая.

ответ

1

Я полагаю, что объект User является объектом сущности, который будет сохранен в БД, поэтому наилучшей практикой является не подвергать объекты объекта FE, но использовать объекты DTO, которые содержат только те поля, которые FE должен знать (подумайте о том, чтобы скрыть идентификатор и использовать UUID вместо этого, поскольку значения id предсказуемы). Позже вы можете сопоставить такой объект DTO с Entity, используя ModelMapper, чтобы вы могли легко объединиться между объектами userDTO и объектами пользователя, а затем просто сохранить объект, не беспокоясь о состоянии отсутствующих полей.

Кроме того, сегодня многие веб-службы отключили запросы PUT для своих приложений и вместо этого использует POST. Я не знаю много причин, но это было одной из проблем безопасности, когда мы передали приложение на проверку безопасности.

+0

от 'id' Я имею в виду используемый общий идентификатор, может быть UUID или любой другой идентификатор, используемый в системе подчеркивания; DTO не то, что я люблю. Чем меньше код, тем лучше; Можете ли вы указать ссылку на ** хороший ** пример, используя 'ObjectMapper'? 'PUT' не рекомендуется, потому что многие брандмауэры блокируют его. Вы все равно можете использовать 'PUT', но подделывать его через' POST' с заголовком 'X-HTTP-Method-Override', установленным на' PUT' –

+0

Фактически 'PUT' не подходит в случае, потому что по семантике предполагается обновить специфический атрибут 'User', а не весь объект. Я меняю его на 'POST' в вопросе –

+0

Я просто быстро google' ObjectMapper' и обнаружил, что это не поможет вам сопоставить 'DTO' с Entity. Фактически он преобразует ваш объект Java в/из строки JSON. –

1

Я думаю, что проблема связана скорее с вашей службой, чем с REST API. Я имею в виду, что если пользовательские свойства 3 «пароль», «созданный» и «последниймодифицированный» не должны быть видимыми для уровня представления, тогда служба должна иметь возможность обрабатывать сохранение без них.

В постоянном слое вы можете обязательно обновить User без всех заполненных объектов. Разделите UserLogin («id», «password», «created», «lastModified») и «User» («id», «name»), которые указывают на ту же таблицу DB. Тогда обновление для Пользователя вообще не нуждается в других ненужных свойствах.

+0

Подход UserLogin выглядит неплохо. Однако вещи «созданы», «lastModified» и, возможно, некоторые другие поля являются общими для всех классов моделей, то есть мне нужно определить отдельный класс DTO для всех классов моделей для применения этого подхода. Это не выглядит действительно сухим ... –

+0

Получил ваш момент. Такие данные аудита, как 'created' или' lastModified', являются общими для всех объектов домена. Поэтому, как правило, я бы создал базовый объект для этих свойств, например. 'AuditableEntity (созданный, lastModified, createdUser, lastModifiedUser)'. И эти базовые свойства будут обрабатываться центральной точкой вместо дублирования во всех сервисах, например, Hibernate listener https://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/listeners.html. Я думаю, мы достигли S (единственная ответственность) и D (DRY). –

+0

У меня есть общий способ обработки 'created' и' lastModified' уже. Вопрос в том, что я использую 'DTO' как' UserLogin', как вы упомянули выше, я могу легко объединить данные обновления в модельный объект, но мне нужно создать отдельный класс DTO для каждого класса модели, который не является СУХОЙ. Если я не создаю 'DTO', перед проблемой сохранения в базу данных я столкнулся с проблемой объединения значения null в общих свойствах, таких как' created' и 'lastModified', в сущность. 'lastModified' может быть проще, потому что мы все равно его обновим, но для других вещей, таких как' created', не так просто –

Смежные вопросы