我们正在使用API优先方法构建应用程序,我们只是为了开始构建REST API并在以后添加GUI .
现在,我正在尝试将GUI添加到某些模块中,而这就是我选择正确的前进方式所困扰的地方 .
我的Spring Boot Web App中有一个 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完美运行,没有任何问题 .
这里要注意的是:
-
可以从
/rest/admin/users
以及/ajax/admin/users
(/rest
表示REST调用和/ajax
表示来自UI的AJAX调用)访问该方法 . 这是一种可接受的方法吗? -
通过
/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对象,但我想要一个通用的解决方案,因为会有很多屏幕,我想尽可能避免错误 .
这里更大的问题是,是否建议将REST控制器重用于AJAx请求(如果两者都有不同的身份验证领域/方案)?如果是这样,我是否采取了正确的方法?
谢谢,Sriram
1 回答
在您第一次注意到的事情中,您定义了您为两个不同的目的重复使用相同的方法 .
我认为你试图实现的东西实际上违反了REST-API标准 . 因此,建议您使用两种不同的方法(使用不同方法的两个不同的URL)重写此api,其中一个
/ajax/admin/users
必须在匿名打开的URL中列出,而/rest/admin/users
必须是安全的 .据我所知,在Spring安全性中使用
csrf
令牌来验证客户端....因此,您必须在每次请求时发送令牌以验证/验证门户上的用户 .据我所知,你的html表单结构是扁平的(所有在相同的层次结构)
如果你看到select的名字是
role.id
,你的html元素的存在形式是直的 . 所以,默认标准json将由ajax序列化生成,将是一个扁平的json之类建议您编写自己的自定义方法,根据需要更改对象结构 .
谢谢...