網絡上對這個問題的分析及解決不是很深刻,大部分並不能解決問題,並且內容基本相同,拿來主義,把內容放在本身的博客上!git
報錯緣由可能有兩種狀況:
1.請求頭中沒有設置Content-Type參數,或Content-Type參數值不是application/json;
2.請求頭中正確設置了Content-Type參數及參數值,可是在項目jar依賴中(pom.xml或build.gradle)沒有添加處理json字符串的處理類,若是SpringMVC框架在啓動的時候,檢查com.fasterxml.jackson.databind.ObjectMapper和com.fasterxml.jackson.core.JsonGenerator有一個不存在或不能加載,則不會註冊MappingJackson2HttpMessageConverter,這個類使用Jackson將json請求參數轉成相應的方法參數;一樣檢查com.google.gson.Gson,若是不存在或不能加載,則不會註冊GsonHttpMessageConverter,這個類使用Gson將json請求參數轉成相應的方法參數;若是依賴的Jackson和Gson都沒有被添加或不能加載,則SpringMVC將找不到對應的參數處理類。github
在使用SpringMVC的時候,都會添加json
若是配置了json參數轉換處理類,SpringMVC框架將根據請求頭中的Content-Type參數遍歷messageConverters,選擇匹配的轉換器類,進行參數轉換。若是Content-Type參數值類型是messageConverters中不支持的,那麼就沒辦法作轉換。網絡
首先,SpringMVC框架在啓動的時候會遍歷Spring容器中的全部bean,對標註了@Controller或@RequestMapping註解的類中方法進行遍歷,將類和方法上的@RequestMapping註解值進行合併,使用@RequestMapping註解的相關參數值(如value、method等)封裝一個RequestMappingInfo,將這個Controller實例、方法及方法參數信息(類型、註解等)封裝到HandlerMethod中,而後以RequestMappingInfo爲key,HandlerMethod爲value存到一個以Map爲結構的handlerMethods中。app
接着,將@RequestMapping註解中的value(即請求路徑)值取出,即url,而後以url爲key,以RequestMappingInfo爲value,存到一個以Map爲結構的urlMap屬性中。框架
客戶端發起請求的時候,根據請求的URL到urlMap中查找,找到RequestMappingInfo,而後根據RequestMappingInfo到handlerMethods中查找,找到對應的HandlerMethod,接着將HandlerMethod封裝到HandlerExecutionChain;接着遍歷容器中全部HandlerAdapter實現類,找到支持此次請求的HandlerAdapter,如RequestMappingHandlerAdapter,而後執行SpringMVC攔截器的前置方法(preHandle方法),而後對請求參數解析及轉換,這裏主要根據HandlerMethod中封裝的參數信息(方法參數上的註解)來遍歷argumentResolvers(List結構,存儲了HandlerMethodArgumentResolver接口實現類,不一樣實現類,實現對不一樣註解參數的解析,如RequestResponseBodyMethodProcessor能夠實現對@RequestBody和@ResponseBody參數的解析),找到支持這個註解的HandlerMethodArgumentResolver實現類,而後解析請求參數。源碼分析
插播一下請求參數的解析及轉換,下圖是HandlerMethodArgumentResolver接口的實現類。
從上圖中能夠看到不少常見註解參數的解析類,這裏分析RequestResponseBodyMethodProcessor,其它處理類感興趣的能夠本身研究一下。RequestResponseBodyMethodProcessor會從請求頭中獲取Content-Type參數值,例如application/json,而後遍歷messageConverters,查找可以處理這種Content-Type的轉換器類,若是messageConverters中有能夠處理application/json請求的處理類,如Jackson或Gson,則使用Jackson或Gson對請求體中的參數進行讀取轉換,轉換成具體方法參數類型,下面是Jackson具體的處理代碼。
若是messageConverters沒有匹配的處理類,那就會報415。post
最後,(使用反射)調用具體Controller的對應方法返回一個ModelAndView對象,執行攔截器的後置方法(postHandle方法),而後對返回的結果進行處理,最後執行afterCompletion方法。gradle