在开发接口时发现了一个很好玩的问题,两个接口均是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哦!你应该明白了!