簡介:
項目改造了下框架,把控制器的API全部REST化,不做不知道,SpringMVC的REST有各種坑讓你去跳,順利繞過它們花了我不少時間,這次來提下SpringMVC的PUT提交參數為null的情況。
不過發現了一個很好玩的現象:就是當PUT參數接收為空的時候,前台是正確傳值,后端接收對象映射不上,即為空,通過打印:request.getInputStream流里的內容,發現是有參數的,就是沒有映射進來,其實是:spring默認沒有開啟。
1:JSON提交方式: Content-Type:application/json
后端:對象接收:除了:get請求,不需要增加@ReqeustBody注解,其它的都需要。
參數接收:使用:@RequestParam 或者不用。
使用這種請求: 其它后端同事開發的時候:客戶端(SOAP)模擬請求時,有了@ReqeustBody參數接收不到,於是去掉,前端開發時,更新代碼又加上。因為公司網不能下載插件,后換成了:form表單提交。
2:form表單提交方式:Content-Type:application/x-www-form-urlencoded
form表單數據格式:為:param1=111¶m2=222 這種開式。
后端:對象接收:除了:所有請求:都不加@ReqeustBody注解
參數接收:可以使用:@RequestParam 或者不用。
SpringBoot解決方式:
//使用@bean注解 @Configuration @EnableWebMvc public class WebMvcConfig extends WebMvcConfigurerAdapter { // 就是這個 @Bean public HttpPutFormContentFilter httpPutFormContentFilter() { return new HttpPutFormContentFilter(); } } //或者使用:@Component,其實原理都是一樣,就是開啟:HttpPutFormContentFilter @Component public class PutFilter extends HttpPutFormContentFilter { }
SpringMVC解決方式:
這種方式來自:SpringMVC控制器接收不了PUT提交的參數的解決方案
照常先貼出我的控制器代碼,沒什么特別的,就是打印出接受到的前台參數值:
@RequestMapping(value = "/{id}", method = RequestMethod.PUT) @ResponseBody public Map<String, Object> update( @RequestParam(value = "isform", required = false) String isform, @PathVariable("id") String id) { System.out.println("id value: " + id); System.out.println("isform value: " + isform); return null; }
很常規的PUT控制器,用來修改原有的記錄,原有的的web.xml中,我只添加了一個和REST涉及的過濾器
org.springframework.web.filter.HiddenHttpMethodFilter
<filter> <filter-name>HttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>HttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
這個因為大多數人都知道它的作用,這里再啰嗦提一下:
瀏覽器form表單只支持GET與POST請求,而DELETE、PUT等method並不支持,spring3.0添加了一個過濾器,可以將這些請求轉 換為標准的http方法,使得支持GET、POST、PUT與DELETE請求,該過濾器為HiddenHttpMethodFilter,只需要在表單中添加一個隱藏字段"_method"
<form action="..." method="post"> <input type="hidden" name="_method" value="put" /> ...... </form>
下邊我們來看下,運行的結果,我會在我的前台發起一個PUT請求作為案例,

我們來看下后台的參數打印情況:

id參數順利的獲取到了,因為它其實是由@PathVariable獲取的,這個沒有什么問題,但是http body中提交的參數值isform卻為null,查詢了一番,原因是:
如果是使用的是PUT方式,SpringMVC默認將不會辨認到請求體中的參數,或者也有人說是Spirng MVC默認不支持 PUT請求帶參數,
解決方案也很簡單,就是在web.xml中把原來的過濾器改一下,
換成org.springframework.web.filter.HttpPutFormContentFilter
<filter> <filter-name>HttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class> </filter> <filter-mapping> <filter-name>HttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
在更改之后我們繼續一下剛才的案例,發送一個PUT請求,參數基本都不變

看下后台打印的結果:

ok,現在已經可以成功的獲取並打印出前台的參數。
