转自: https://qtdebug.com/fe-rest/
使用 REST 风格提交请求时,Content-Type 标准的来说应该用 application/json,但是服务器端获取请求的参数时必须从 Request Body 中获取,而且有些框架对从 Request Body 中获取数据支持不好,需要我们自己实现,SpringMVC 中使用注解 @RequestBody从 Request Body 中获取数据,但不能使用 Filter 进行 XSS 过滤。
这里主要使用 SpringMVC 来作为后端进行介绍,SpringMVC 提供了一个 Filter HiddenHttpMethodFilter,把 Content-Type 为 application/x-www-form-urlencoded 的 POST 请求,参数中 _method 值为 PUT 的请求分发为 PUT 请求,为 DELETE 请求分发为 DELETE 请求,实现了普通表单的 REST 风格提交,这样就可以使用 @RequestParam 获取参数的值了。
下面结合 SpringMVC 来介绍:
- Content-Type 为 application/x-www-form-urlencoded + HiddenHttpMethodFilter
- 优点: 服务器端 GET, PUT, POST, DELETE 时直接参数映射为对象,或则都使用 @RequestParam 获取参数,使用形式一致、简洁
- 缺点:
- 不是标准的 REST 规范
- 参数是按照 key/value 的形式发送的,和普通表单的参数形式一样,有兴趣的可以在 Chrome 的 Network 中查看请求的 Headers
- 不能传递复杂对象,例如 value 又是一个 Json 对象,只能传递简单的 key/value,也就是作为参数的 Json 对象只能有一层 key/value,不过非特殊情况也够用了,普通表单能做的它都能做
- PUT 时参数中需要带上 _method=”PUT”,DELETE 时参数中需要带上 _method=”DELETE”
- Content-Type 为 application/json
- 优点: 标准的 REST 规范,GET 处理和上面的一样,但是 POST, PUT, DELETE 的参数是序列化后的 JSON 字符串,能够传递复杂的对象
- 缺点:
- 服务器端直接参数映射为对象,或则 GET 时使用 @RequestParam 获取参数,POST, PUT, DELETE 使用 @RequestBody 获取参数到 Map 中,然后再从 Map 中获取一个一个的参数,非常繁琐
- GET 和 POST, PUT, DELETE 获取参数的形式不统一,一个用 @RequestParam,其他的用 @RequestBody,需要脑子转换一下
- 还有就是浏览器端 PUT, POST, DELETE 传递的 JSON 对象需要序列化后才能传给服务器端,可以使用 JSON.stringify(jsonObject) 进行序列化
总结下来,在 SpringMVC 中推荐使用 application/x-www-form-urlencoded + HiddenHttpMethodFilter
的方式实现 REST 的请求,就是为了获取参数时比较统一,当需要传递复杂的参数时,例如属性是多层嵌套的对象,Json 对象的数组,这时再使用 application/json 的方式。
为了简化 Rest Ajax 的访问,下面对 jQuery 的 Ajax 进行了简单的封装,例如更新用户名原始实现大致如下:
1 | $.ajax({ |
如果每个 REST 的请求都像上面这样写一遍: PUT
, POST
, DELETE
时需要 JSON.stringify(data)
, 请求不同时 type 也不同,dataType 和 contentType 是固定的,这么多限制,很容易出错。使用下面实现的 rest 插件后,简化如下,只需要关心参数和回调,不需要处理其他额外信息,而且 $.rest.update 名字也更有语义化,一看就知道是更新操作:
1 | $.rest.update({ |
测试页面:
1 |
|
输出:
1 | {code: 0, data: "Alice", message: "GET handled", success: true} |
服务器端
添加下面的 Filter 到 web.xml, servlet-name 为 DispatcherServlet 的 servlet-name,根据自己的配置进行修改:
1 | <!-- 浏览器的 form 不支持 put, delete 等 method, 由该 filter |
Controller 的实现:
1 | package com.xtuer.controller; |
Result.java
Result 用于统一服务器端返回的 JSON 格式,例如:
1 | { |
1 | package com.xtuer.bean; |
附录:REST 插件 jquery.rest.js:
1 | ; |