Spring Boot-将REST控制器重用于AJAX请求,表单数据序列化

时间:2018-12-10 11:37:29

标签: jquery ajax rest spring-boot

我们正在使用API​​优先方法来构建应用程序,在此过程中,我们仅以REST API为基础开始构建,然后再添加GUI。

现在,我正在尝试将GUI添加到某些模块中,这就是我坚持选择正确的前进方式的地方。

我的Spring Boot Web应用程序中有一个RestController方法来创建用户

    @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指示来自UI的AJAX调用)访问该方法。这是可以接受的方法吗?
  2. 通过/rest URL进行的任何呼叫都必须具有基本身份验证标头,而/ajax的呼叫不受基本身份验证的保护。他们采用普通形式的登录身份验证。在这种情况下,它们只需要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);

我从here得到了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请求可以正常工作而不会出现问题。

虽然我知道可以在触发AJAX调用之前生成自定义JSON对象,但我希望有一个通用的解决方案,因为屏幕很多,而且我希望尽可能避免出错。

这里更大的问题是,是否建议对AJAx请求重新使用REST控制器(前提是两者都具有不同的身份验证领域/方案)?如果是这样,我是否遵循正确的方法?

谢谢, 斯里拉姆

1 个答案:

答案 0 :(得分:0)

  
      
  1. 您使用的是同一个API,一个请求具有验证,而另一个请求没有验证(不推荐)。
  2.   

在第一件事中,您定义要出于两个不同目的而重复使用同一方法。

我认为您尝试实现的目标实际上违反了REST-API标准。 因此,建议您使用两种不同的方法(两个具有不同方法的不同url)来重写此api,其中一个/ajax/admin/users必须在匿名打开的url中列出,而/rest/admin/users必须是安全的。

据我所知,csrf令牌在春季安全性中用于验证客户端...。因此,您必须在每次请求时发送令牌以在门户上验证/验证用户。

  
      
  1. 现在来到第二点...(ajax调用序列化)
  2.   

据我所知,您的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
}

建议您编写自己的自定义方法来根据需要更改对象结构。

谢谢...