Spring MVC + JSON = 406 Not Acceptable

僤鯓⒐⒋嵵緔 提交于 2019-12-07 21:27:57

在开发接口时发现了一个很好玩的问题,两个接口均是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.本文来分析一下其中的原因。

  先介绍一下出错的接口情况,接口代码如下:

/**
 * 验证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;
}

  通过Swagger生成的接口描述如下图所示:

  在上图的表单中将email的值设置为456213@qq.com,发起对接口的测试请求,界面返回结果如下图:

  服务端控制台异常代码如下:

org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

  细心的读者可能会发现,在本文第二张图中Curl中的header设置为'Accept: text/html',这和本文提出的问题有没有关联呢?下面我们再做一次实验,将email的值设置为456213,再次发送测试请求,界面返回结果如下图:

  小伙伴们现在心里有疑问了吧?为什么header中的Accpet值会不一样?为什么这次能过正常响应呢?让我们回想一下响应码406的意思——Not Acceptable,即请求数据类型与返回数据类型不匹配。我原本请求返回html数据,你服务端却给我返回json数据,我当然Not Acceptable啦!
  我们已经很清楚的知道,restful接口返回结果均使用@ResponseBody注解转为json格式,如果客户端请求json数据,接口肯定能正常响应;如果客户端请求其他形式数据,我们的接口也只能响应json数据,这样子就出现本文讨论的问题了。
  进一步讨论,为什么修改参数之后,header中Accept的值不一样了呢?让我们好好审视一下Request URL吧!

http://localhost:8083/arrow-api/users/emailCheck/456213%40qq.com

  这个URL是以.com结尾,其形式为使用.com顶级域名的网址,所以客户端默认在这种请求的头部设置'Accept: text/html',因为这种形式的地址一般都是对网页的请求。不信,你可以试试把该url的后缀.com去掉,再次测试请求。我猜,一定可以正常响应。

  那碰到这种情况怎么办呢?其实,很简单!只要不使用restful的形式绑定参数即可。我是这么修改的:

/**
 * 验证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哦!你应该明白了!

文章作者: xiaohui249
本文链接: http://javatech.wang/index.php/archives/77/
版本所有 ©转载时必须以链接形式注明作者和原始出处
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!