RESTful API的設(shè)計,是以請求方式GET、POST、PUT等為動作,URL為動作請求的資源名詞的標(biāo)準(zhǔn)來設(shè)計的。
但是在實際應(yīng)用中,光靠HTML其實無法完成除了GET和POST之外的請求方法,那么DELETE和PUT方法如果完成呢?RESTful怎么投入到應(yīng)用呢?
可能有人想到通過form表單來向后端提交數(shù)據(jù),但是form表單在HTML標(biāo)準(zhǔn)中是只支持POST和GET方法的。
鑒于現(xiàn)有條件,光靠HTML不能發(fā)送PUT和DELETE請求,我們這里用到了Javascript語言的Ajax技術(shù)來輔助實現(xiàn)RESTful。
在傳統(tǒng)的Internet編程中,如果想得到服務(wù)器后端數(shù)據(jù),或者發(fā)送客戶端信息到服務(wù)器,需要建立一個HTML form然后只能以GET或者POST方法將數(shù)據(jù)發(fā)送到服務(wù)器端。
用戶需要點擊”Submit”按鈕來發(fā)送數(shù)據(jù)信息,然后等待服務(wù)器響應(yīng)請求,頁面重新加載。 這樣服務(wù)器每次都會返回一個新的頁面, 響應(yīng)有可能很慢并且用戶交互不友好。
使用AJAX技術(shù), 就可以使Javascript通過XMLHttpRequest對象直接與服務(wù)器進(jìn)行交互。
通過HTTP Request,不但可以在HTTP協(xié)議請求中加入Request Method:GET(POST、PUT、DELETE)的HTTP頭,來模擬多種HTTP請求, 還可以做到異步發(fā)送請求到web服務(wù)器并且接受web服務(wù)器返回的信息(不用重新加載頁面,既做到免刷新),在回調(diào)函數(shù)中對服務(wù)器返回的數(shù)據(jù)在HTML中進(jìn)行動態(tài)渲染,并且展示給用戶的還是同一個頁面。
總結(jié)AJAX技術(shù)作用:
1、通過JS自帶的XMLHttpRequest對象,實現(xiàn)多種HTTP請求,彌補HTML標(biāo)簽只能完成POST和GET請求的缺陷。
2、不用重新請求頁面,僅僅以JS線程和服務(wù)器后端互動,得到后端數(shù)據(jù)后可以在回調(diào)函數(shù)中完成前端頁面的動態(tài)渲染,做到免刷新技術(shù)。
下面是在Springboot框架中的實例演示,筆者的Spingboot文件結(jié)構(gòu)如下所示:

在ViewController控制器中添加以下路由實現(xiàn)方法,來作為展示的基礎(chǔ)頁面:
@RequestMapping("/ajax")
public String ajax() {
System.out.println(">> ViewController.ajax() is called!");
return "ajax";
}
在ajax.html中,主要內(nèi)容如下:
<button id="get">GET(獲取數(shù)據(jù))</button>
<button id="post">POST(添加數(shù)據(jù))</button>
<button id="put">PUT(更新數(shù)據(jù))</button>
<button id="delete">DELETE(刪除數(shù)據(jù))</button>
并且通過引用的方式來調(diào)用Jquery(一個JS框架,可以使用封裝好的AJAX方法)和一個自定義JS文件:
<!--使用jquery框架-->
<script type="text/javascript" src="js/jquery.min.js"></script>
<!--JS實現(xiàn)AJAX部分-->
<script type="text/javascript" src="js/main.js"></script>
main.js內(nèi)容如下(如讀者不熟悉Javascript的使用,可以看注釋來了解功能):
/**
* Created by Doublestar on 2017/10/1.
*/
$(document).ready(function(){ //在HTML文檔加載完成后執(zhí)行
//GET方法
$("#get").click(function(){ //HTML中id為get的HTML標(biāo)簽的點擊動作
$.ajax({
url:'http://localhost:8080/product', //請求的URL地址
type:'GET', //請求方法,GET、POST、PUT、DELETE在這里設(shè)置
timeout:5000, //超時時間
dataType:'text', //返回的數(shù)據(jù)格式:json/xml/html/script/jsonp/text
success:function(data,textStatus,jqXHR){ //成功的回調(diào)函數(shù)
$("#result").html(data) //設(shè)置id為result的標(biāo)簽的html內(nèi)容為返回的data數(shù)據(jù)
},
error:function(xhr,textStatus){ //失敗的回調(diào)函數(shù)
$("#result").html(textStatus)
}
})
})
//POST方法
$("#post").click(function(){
$.ajax({
url:"http://localhost:8080/product/?id=1&name=測試POST&age=21",
type:'POST', //請求方法,GET、POST、PUT、DELETE在這里設(shè)置
timeout:5000, //超時時間
dataType:'text', //返回的數(shù)據(jù)格式:json/xml/html/script/jsonp/text
success:function(data,textStatus,jqXHR){
$("#result").html(data)
},
error:function(xhr,textStatus){
$("#result").html(textStatus)
}
})
})
//PUT方法
$("#put").click(function(){
$.ajax({
url:'http://localhost:8080/product/1/?name=測試PUT&age=22',
type:'PUT', //請求方法,GET、POST、PUT、DELETE在這里設(shè)置
timeout:5000, //超時時間
dataType:'text', //返回的數(shù)據(jù)格式:json/xml/html/script/jsonp/text
success:function(data,textStatus,jqXHR){
$("#result").html(data)
},
error:function(xhr,textStatus){
$("#result").html(textStatus)
}
})
})
//DELETE方法
$("#delete").click(function(){
$.ajax({
url:'http://localhost:8080/product/1',
type:'DELETE', //請求方法,GET、POST、PUT、DELETE在這里設(shè)置
timeout:5000, //超時時間
dataType:'text', //返回的數(shù)據(jù)格式:json/xml/html/script/jsonp/text
success:function(data,textStatus,jqXHR){
$("#result").html(data)
},
error:function(xhr,textStatus){
$("#result").html(textStatus)
}
})
})
})
最后的瀏覽器效果如下:

以上是實例演示基礎(chǔ)的內(nèi)容,接下來介紹具體的請求執(zhí)行:
User類代碼:
package com.hello.data;
public class User {
private Long id;
private String name;
private Integer age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
在DataController中,筆者寫了四個路由分別來響應(yīng)對應(yīng)的GET、POST、PUT和DELETE方法(講解略):
//使用User類來存儲數(shù)據(jù)實現(xiàn)增刪改查
static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>());
@GetMapping("/product")
public List<User> getInfo(){
List<User> r = new ArrayList<User>(users.values());
return r;
}
@PostMapping("/product")
public String addInfo(@ModelAttribute User user){
users.put(user.getId(), user);
return "success";
}
@PutMapping("/product/{id}")
public String putInfo(@PathVariable Long id, @ModelAttribute User user){
// 處理"/users/{id}"的PUT請求,用來更新User信息
User u = users.get(id);
u.setName(user.getName());
u.setAge(user.getAge());
users.put(id, u);
return "success";
}
@DeleteMapping("/product/{id}")
public String delInfo(@PathVariable Long id){
// 處理"/users/{id}"的DELETE請求,用來刪除User
users.remove(id);
return "success";
}
這四個路由對應(yīng)的處理方法,對應(yīng)上文對main.js展示中AJAX的URL。
下面我們來看執(zhí)行效果:
首先我們點擊GET按鈕獲取數(shù)據(jù),發(fā)現(xiàn)為空
[]

再點擊POST按鈕,顯示執(zhí)行成功,并且再點擊GET查看,發(fā)現(xiàn)多了一條數(shù)據(jù)
[{"id":1,"name":"測試POST","age":21}]

再點擊PUT按鈕來嘗試更新數(shù)據(jù),發(fā)現(xiàn)數(shù)據(jù)更新為
[{"id":1,"name":"測試PUT","age":22}]

最后,我們嘗試刪除這條數(shù)據(jù),刪除成功后,GET查看數(shù)據(jù)發(fā)現(xiàn)已經(jīng)清空為
[]

至此,使用AJAX技術(shù)對于RESTful API的實現(xiàn)演示結(jié)束了,筆者在這里使用了JAVAEE的Spingboot框架,但是上文所講技術(shù)移植性很強(qiáng),除了對于后端實現(xiàn)部分,其他部分均可以在PHP、Python等后端環(huán)境下正常工作(讀者如有細(xì)節(jié)問題,可以結(jié)合閱讀代碼理解)。
感謝閱讀
作者:Doublestar
博客:https://www.yourhome.ren