一、普通請求方法發送 PUT 請求
1. 如果不用 ajax 發送 PUT,我們可以通過設置一個隱藏域設置 _method 的值,如下:
<form action="/emps" method="post"> <input type="hidden" name="_method" value="PUT"> <input type="text" name="username"> <input type="password" name="password"> <input type="submit"/> </form>
2. 控制層:
@RequestMapping(value="/emps", method=RequestMethod.PUT) public String updateEmp(Employee employee) { System.out.println(employee); return "redirect:success.jsp"; }
注意:這里如果采用請求轉發的方式即 return "success.jsp",將會出現以下問題:(Tomcat 7.0 版本不會出現這個問題)
SpringMVC HTTP Status 405 - JSPs only permit GET POST or HEAD
采用重定向的方式可以避免這個問題。
3. 這種方式發送 PUT 請求,還需在 web.xml 中配置一個 HiddenHttpMethodFilter 過濾器(如果使用Spring Boot 則會自動配置)
<filter> <filter-name>HiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>HiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
瀏覽器 form 表單只支持 GET 與 POST 請求,而DELETE、PUT 等 method 並不支持,Spring3.0 添加了一個過濾器,可以將這些請求轉換為標准的 http 方法,使得支持 GET、POST、PUT 與 DELETE 請求。
首先看到 HiddenHttpMethodFilter 過濾器的源碼:


二、通過 ajax 發送 DELETE 請求(需要帶_method參數)
/* 刪除員工 */ function deleteEmp(empId){ $.ajax({ url : "emps", data : {_method : "DELETE", empId : empId}, type : "POST", success : function(result){ } }) }
發送表單 ajax 請求:
$("#updateBtn").click(function(){ $.ajax({ url : "emps", data : $("#updateEmpFormNode").serialize()+"&_method=put", type : "post", success : function(result){ alert(result); } }) })
三、直接指定 ajax 請求中的 type 為 put/delete(不帶 _method 參數)
1. 把上述第二點的表單更新改寫為如下:
$("#updateBtn").click(function(){ $.ajax({ url : "emps", data : $("#updateEmpFormNode").serialize(), type : "PUT", success : function(result){ alert(result); } }) })
出錯:
這問題是由於 Tomcat 本身引起的,導致這個問題是因為 SpringMVC 綁定 POJO 對象時獲取不到數據,然后執行更新語句時 sql 語句出錯導致的。由於 POJO 的數據都為空,所以被執行的更新語句可能會為 update emp set where empId = ?,反正被執行更新語句肯定是有錯的。想要知道為什么獲取不到數據,下面首先先了解一下 Tomcat 如何封裝數據以及SpringMVC如何綁定數據
① Tomcat 首先會將請求體中的數據,封裝一個map。
② request.getParameter("empName") 就會從這個map中取值。
③ SpringMVC封裝POJO對象的時候,通過 request.getParamter("empName"); 獲取一個字段的值,然后賦值到 POJO 中屬性名為 empName 的屬性。如:
String temp = (String)request.getParamter("empName");
Employee emp = new Employee();
emp.setEmpName(temp);
查找到 protected void parseParameters() 該方法
protected String parseBodyMethods = "POST";
if( !getConnector().isParseBodyMethod(getMethod()) ) {
success = true;
return;
}
當 Tomcat 知道是請求不是 POST 請求時,會直接 return,而不會繼續往下執行解析封裝參數,所以當 request.getParamter("empName") 從 map 取數據時,由於 empName 參數沒有被封裝到 map 中,getParmater獲取到值為 null。
2.1 在 web.xml 配置上HttpPutFormContentFilter;
<filter> <filter-name>HttpPutFormContentFilter</filter-name> <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class> </filter> <filter-mapping> <filter-name>HttpPutFormContentFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2.2 HttpPutFormContentFilter 的作用;將請求體中的數據解析包裝成一個map。
2.3 request被重新包裝,request.getParameter()被重寫,就會從自己封裝的map中取數據
四,仍然使用PUT DELETE 請求:傳遞參數的時候data需要設置為json字符串
1.仍然使用put和delete請求,直接指定 ajax 請求中的 type 為 put/delete(不帶 _method 參數),並且需要傳遞參數的時候data需要設置為json字符串。(SpringBoot環境中不需要配置任何東西,其他未知)
var jsonstr = {"id":1,"name":"zsw"}; $.ajax({ url:"/update", type:"PUT", contentType:"application/json",//設置請求參數類型為json字符串 data:JSON.stringify(jsonstr),//將json對象轉換成json字符串發送 dataType:"json", success:function(result){ alert(result); }, });
客戶端需要使用@RequestBody標注
@RequestMapping(value = "update",method = RequestMethod.PUT) public String update(@RequestBody Book book){ System.out.println(book); return BookClient.update(book); }
我現在正在用的
//不能傳表單序列化數據
var jsonstr = {"id":8,"projectName":"z"};
$.ajax({
url:"/project/update",
type:"PUT",
contentType:"application/json",//設置請求參數類型為json字符串
data:JSON.stringify(jsonstr),//將json對象轉換成json字符串發送
dataType:"json",
success:function(result){
alert(result);
},
});
//對應的controller
@RequestMapping(value = "update",method = RequestMethod.PUT)
public Result updateProjectById(@RequestBody Project project){
var data=$("#updateForm").serialize(); console.log(data); $.ajax({ url:"/project/update", type:"POST", data : $("#updateForm").serialize()+"&_method=put", // data:{_method:"PUT"}, success:function(result){ alert("修改成功"); } }) //對應的controller @RequestMapping(value = "update",method = RequestMethod.PUT) public Result updateProjectById(Project project){
拓展:
Ajax請求($.ajax()為例)中data屬性傳參數的形式
參考鏈接:
https://blog.csdn.net/Mrs_Yu/article/details/92376069
https://blog.csdn.net/liuyuanjiang109/article/details/78972644