Spring Boot - повторное использование контроллера REST для запросов AJAX, сериализация данных формы - PullRequest
0 голосов
/ 10 декабря 2018

Мы создаем приложение с использованием подхода, основанного на API, в котором мы создаем API-интерфейсы REST только для начала и добавляем графический интерфейс позже.

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

У меня есть метод RestController в моем веб-приложении Spring Boot для создания пользователя

    @PostMapping(value={"/rest/admin/users", "/ajax/admin/users"})
    @ApiOperation(value="Create a user", produces="application/json", consumes="application/json")
    public ResponseEntity<User> create(@RequestBody User user) {
        User createdUser = this.userService.add(user);
        URI location = CommonFunctions.buildResourceLocation("/{id}", createdUser.getId());
        return ResponseEntity.created(location).body(createdUser);
    } 

Наши REST API защищены базовой аутентификацией, и API работают без проблем.

Здесь следует отметить следующее:

  1. Этот метод доступен из /rest/admin/users, а также из /ajax/admin/users (/rest указывает на вызов REST и /ajax указываетвызов AJAX из пользовательского интерфейса).Является ли это приемлемым подходом?
  2. Любые вызовы через URL /rest должны иметь заголовок Basic Auth, в то время как вызовы /ajax не защищены с помощью Basic auth.Вместо этого они принимают обычную форму авторизации входа в систему.В этом случае им просто нужны заголовки X-CSRF.

Теперь, чтобы уменьшить код, который мы должны написать, я просто хочу повторно использовать вышеупомянутый метод контроллера REST для создания пользователя черезAjax.

В моем JSP есть форма, подобная приведенной ниже:

<form:form action="/ajax/admin/users" modelAttribute="user" id="user_create_form">
    <label for="name">Full Name</label>
    <input type='text' id='name' name='name' placeholder='' class='form-control focus-on-load'/>

    <label for="email">E-Mail Address</label>
    <input type='text' id='email' name='email' placeholder='' class='form-control'/>

    <label for="role">Role</label>
    <select class='form-control short' name='role.id' id='role'>
        <option value='2'>User</option>
        <option value='1'>Site Administrator</option>
    </select>
</form:form>

При нажатии кнопки сохранения я сериализирую данные формы, чтобы я мог получитьтакой JSON:

{
    "name":"User Full Name",
    "email":"useremail@somedomain.com",
    "role":{
        "id":1
    }
}

Для сериализации я использую следующий код:

var formData = getFormData($form);

Я получил логику для getFormData($form) из здесь

Это мой AJAX-вызов

$.ajax({
    url:$form.attr('action'),
    method:'POST',
    dataType:'json',
    contentType:'application/json',
    data:JSON.stringify(formData),
    beforeSend:function(xhr) {
        if (header && token) {
            xhr.setRequestHeader(header, token);
        }
    },
    success:function(result) {
         //Do something to indicate success
    }, error: function(xhr, textStatus, errorThrown) {
         //Do something to indicate failure
    }
});

Здесь все отлично работает, кроме сериализации.Когда я сериализую данные формы, это то, что я получаю

{
    "name":"SOme Name",
    "email":"someemail@org.com",
    "role.id":1
}

, а не

{
    "name":"Some Name",
    "email":"someemail@org.com",
    "role":{"id":1}
}

Это единственное, что мешает мне повторно использовать методы контроллера REST для AJAXЗапросы.Запросы GET работают без проблем.

Хотя я знаю, что могу создать собственный объект JSON до запуска вызова AJAX, я хочу общее решение, так как будет много экранов, и я хочу избежать ошибок, так какнасколько это возможно.

Большой вопрос здесь заключается в том, целесообразно ли повторно использовать контроллеры REST для запросов AJAx (при условии, что оба имеют разные области / схемы аутентификации)?Если да, то я придерживаюсь правильного подхода?

Спасибо, Шрирам

1 Ответ

0 голосов
/ 10 декабря 2018
  1. Вы используете один и тот же API с одним запросом с аутентификацией и другим без аутентификации (не рекомендуется).

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

Я думаю, что то, чего вы пытаетесь достичь, действительно нарушает стандарт REST-API.Итак, предлагаем вам переписать этот API двумя разными методами (два разных URL с разными методами), где один /ajax/admin/users должен быть указан в анонимном открытом URL, а /rest/admin/users должен быть защищенным.

Насколько мне известно, csrf токен, используемый в Spring Security для проверки клиента .... поэтому вы должны отправлять свой токен при каждом запросе для проверки / аутентификации пользователя на портале.

Теперь перейдем ко второй точке ... (ajax call Serialization)

Насколько я вижу, что ваша структура формы HTML плоская (все на том же уровне иерархии)

 <label for="name">Full Name</label>
 <input type='text' id='name' name='name' placeholder='' class='form-control focus-on-load'/>

 <label for="email">E-Mail Address</label>
 <input type='text' id='email' name='email' placeholder='' class='form-control'/>

 <label for="role">Role</label>
 <select class='form-control short' name='role.id' id='role'>
     <option value='2'>User</option>
     <option value='1'>Site Administrator</option>
 </select>

, если вы видите, что имя выбора равно role.id и ваше существование html-элементов является прямо параллельным по форме.Таким образом, стандартный json по умолчанию будет генерироваться при сериализации ajax. Это будет плоский json, такой как

{
    "name":"SOme Name",
    "email":"someemail@org.com",
    "role.id":1
}

Рекомендую вам написать собственный метод для изменения структуры объекта в соответствии с вашими потребностями.

Спасибо ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...