栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

解决跨服务接口调用406 Not Acceptable问题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

解决跨服务接口调用406 Not Acceptable问题

一、问题描述

前段时间写一功能,需要调用外部接口,使用postman可以调用成功,但是通过代码去调用一直报406 Not Acceptable的错误。错误信息如下图:

 调用的代码片段一类似如下(下面代码只是调用的方式,为了不透露公司代码):

package com.test.controller;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.linkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/1")
    @ResponseBody
    public JSonObject test1(String param1, String param2) {
        String url = "http://XX.XXX.XXX.XXX/rest/main/XXX";
        MultiValueMap formData = new linkedMultiValueMap<>();
        JSonObject dataJson = new JSonObject();
        dataJson.put("param1", param1);
        dataJson.put("param2", param2);
        String param = dataJson.toJSonString();
        formData.add("data", param);
        log.info("url:{},formdata:{}.", url, formData);
        // 1
        JSonObject result = restTemplate.postForObject(url, formData, JSONObject.class);
        log.info("result:{}.", result);
        return result;
    }
}
二、定位问题

通过维基百科可以知道406状态码的含义

说白了就是,不管是前端调用后端接口得到数据还是跨服务间接口的调用,若被调用者返回的数据的格式与调用者期望得到的数据格式不符或不能转换为调用者想要转换的数据格式便会报406异常。

OK,知道了什么情况会出现406,回到代码中看有什么问题。代码中使用的是post请求,并将结果转换为JSONObject形式。那问题可能就出在返回给我的不是json的,导致转换成JSONObject时出错。

联系到提供该接口的同事看了下他们这个接口的代码,果然问题出在这。被调用接口部分代码如下图:

 可以通过@RequestMapping注解中的produces属性设置响应体类型和字符编码,可以看到上面接口设置的响应体类型为纯文本的形式。虽然纯文本内容的格式是json形式,但不能直接使用别的类型来转换接收。需要用String类型来接收该返回值,然后再转成JSONObject类型数据。

三、解决问题

将上述代码1处改为如下即可,即先用String类型接收响应体,然后再转换为JSONObject类型对象。

// 1
String result = restTemplate.postForObject(url, formData, String.class);
JSonObject jsonObject = JSONObject.parseObject(result);

四、补充

这个接口文档只有出参举例,没有出参类型,看着是出参是json结构就想当然的用JSONObject接数据,接口文档书写不规范害死人啊。

还有为什么同样请求该接口,postman就可以调用成功?

因为使用postman创建一个新的请求时,请求头中的Accept属性值为*/*,即可以接受所有媒体类型的数据,当然可以接受“text/plain"类型的数据。

 还有一点就是,在使用postman调用成功时就已经显示响应体是纯文本格式了。

若响应体是JSON格式的,则该处应如下:

也怪自己粗心当时没注意,兜转半天。 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/318089.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号