在開發接口時發現了一個很好玩的問題,兩個接口均是restful形式,參數在URL路徑中傳遞,返回結果形式均爲json,可是在接口測試時,一個接口正常,另外一個接口報錯:The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.本文來分析一下其中的緣由。 php
先介紹一下出錯的接口狀況,接口代碼以下: html
/** * 驗證email是否可用 * @param email * @return */ @ResponseBody @RequestMapping(value = "/emailCheck/{email}", method = RequestMethod.GET) @ApiOperation(value = "驗證email是否可用", httpMethod = "GET", response = ApiResult.class, notes = "驗證email是否可用") public ApiResult checkEmailValid(@ApiParam(required = true, name = "email", value = "待校驗的電子郵箱") @PathVariable String email) throws Exception{ UcUserContact userContact = ucUserContactmanager.getByEmail(email); ApiResult<String> result = new ApiResult<String>(); if (userContact != null){ result.setData("0");//用戶名不可用 }else{ result.setData("1");//用戶名可用 } result.setCode(ResultCode.SUCCESS.getCode()); return result; }
在上圖的表單中將email的值設置爲456213@qq.com,發起對接口的測試請求,界面返回結果以下圖:
web
服務端控制檯異常代碼以下: spring
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
細心的讀者可能會發現,在本文第二張圖中Curl中的header設置爲'Accept: text/html',這和本文提出的問題有沒有關聯呢?下面咱們再作一次實驗,將email的值設置爲456213,再次發送測試請求,界面返回結果以下圖:
json
小夥伴們如今內心有疑問了吧?爲何header中的Accpet值會不同?爲何此次能過正常響應呢?讓咱們回想一下響應碼406的意思——Not Acceptable,即請求數據類型與返回數據類型不匹配。我本來請求返回html數據,你服務端卻給我返回json數據,我固然Not Acceptable啦!
咱們已經很清楚的知道,restful接口返回結果均使用@ResponseBody註解轉爲json格式,若是客戶端請求json數據,接口確定能正常響應;若是客戶端請求其餘形式數據,咱們的接口也只能響應json數據,這樣子就出現本文討論的問題了。
進一步討論,爲何修改參數以後,header中Accept的值不同了呢?讓咱們好好審視一下Request URL吧! api
http://localhost:8083/arrow-api/users/emailCheck/456213%40qq.com
這個URL是以.com結尾,其形式爲使用.com頂級域名的網址,因此客戶端默認在這種請求的頭部設置'Accept: text/html',由於這種形式的地址通常都是對網頁的請求。不信,你能夠試試把該url的後綴.com去掉,再次測試請求。我猜,必定能夠正常響應。 restful
那碰到這種狀況怎麼辦呢?其實,很簡單!只要不使用restful的形式綁定參數便可。我是這麼修改的: app
/** * 驗證email是否可用 * @param email * @return */ @ResponseBody @RequestMapping(value = "/emailCheck", method = RequestMethod.GET) @ApiOperation(value = "驗證email是否可用", httpMethod = "GET", response = ApiResult.class, notes = "驗證email是否可用") public ApiResult checkEmailValid(@ApiParam(required = true, name = "email", value = "待校驗的電子郵箱") @RequestParam String email) throws Exception{ UcUserContact userContact = ucUserContactmanager.getByEmail(email); ApiResult<String> result = new ApiResult<String>(); if (userContact != null){ result.setData("0");//用戶名不可用 }else{ result.setData("1");//用戶名可用 } result.setCode(ResultCode.SUCCESS.getCode()); return result; }
注意看上圖中的Curl和Request URL哦!你應該明白了!