通過 Ajax 發送 PUT、DELETE 請求的兩種實現方式


一、普通請求方法發送 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>

  

原理/問題:為什么要設置 _method 參數?
        瀏覽器 form 表單只支持 GET 與 POST 請求,而DELETE、PUT 等 method 並不支持,Spring3.0 添加了一個過濾器,可以將這些請求轉換為標准的 http 方法,使得支持 GET、POST、PUT 與 DELETE 請求。
         首先看到 HiddenHttpMethodFilter 過濾器的源碼:
        doFilterInternal方法能根據 _method 把 post 請求轉化為標准的Http方法,即GET,、POST、 HEAD、OPTIONS、PUT、DELETE、TRACE

二、通過 ajax 發送 DELETE 請求(需要帶_method參數)

       這種實現方式跟第一種的原理是一樣的,同樣是利用 _method 參數對 request 請求進行轉換,所以這種方式同樣需要配置HiddenHttpMethodFilter 過濾器。
       以下以刪除員工為例子(傳遞員工編號empId):
        /* 刪除員工 */
		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如何綁定數據
       1.1 Tomcat 封裝表單數據和 SpringMVC 綁定 POJO 對象數據時的流程如下:
                ① 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);
        1.2 由於 Ajax 發送的是 PUT 請求,Tomcat一看是PUT不會封裝請求體中的數據為map,只有POST形式的請求才封裝請求體為map,查看 Tomcat 的源碼:
            查找到 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. 解決方法
             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

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM