You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用RestTemplate调用POST接口返回403,但HttpEntity体非空

问题描述

使用RestTemplate调用需API-Key认证的POST接口时,持续收到403 Forbidden错误。相同授权头的GET请求可正常执行,说明API-Key有效;Postman调用该接口时,仅当不发送请求体才返回403,但代码中输出HttpEntity的体并非空值,推测是HttpEntity或restTemplate.exchange的使用有误,导致请求体未被正确发送。相关代码如下:

package at.acl.articledata.connector.smokeTest;

import at.acl.articledata.connector.pojos.request.Article;
import com.fasterxml.jackson.databind.util.JSONPObject;
import io.swagger.v3.core.util.Json;
import jakarta.annotation.PostConstruct;
import org.apache.coyote.Response;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.Collections;

@Component
public class SmokeTest {

    @Autowired
    RestTemplate restTemplate = new RestTemplate();

    @PostConstruct
    private void floodDatabase(){
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        headers.add("X-API-KEY", "myApiKey");

        JSONObject jsonArticle = new JSONObject();
        jsonArticle.put("ext_article_nr", "e001");
        jsonArticle.put("ean_numeric", BigDecimal.valueOf(420));
        jsonArticle.put("intern_art_nr", "i001");
        jsonArticle.put("article_name", "Flip Flops");
        jsonArticle.put("size", "45");
        jsonArticle.put("color", "Green");
        jsonArticle.put("group", "No Group");
        jsonArticle.put("brand", "Gucci");
        jsonArticle.put("season", "Summer");
        jsonArticle.put("article_link", "http://dummyimage.com/102x100.png/dddddd/000000");

        JSONArray jsonArticleArray = new JSONArray();
        jsonArticleArray.put(jsonArticle);

        JSONObject jsonBody = new JSONObject();
        jsonBody.put("count", 1);
        jsonBody.put("total_count", 8);
        jsonBody.put("data", jsonArticleArray);

        HttpEntity<JSONObject> request = new HttpEntity<>(jsonBody, headers);

        ResponseEntity<String> response = restTemplate.exchange("correctServerIP", HttpMethod.POST, request, String.class);
        System.out.println("Post Response: " + response);
    }
}
问题分析
  1. 消息转换器不兼容:RestTemplate默认使用MappingJackson2HttpMessageConverter处理JSON请求体,但该转换器仅支持Jackson的ObjectNode或POJO,无法正确序列化org.json.JSONObject,导致请求体未被正确发送到服务器。
  2. Content-Type未显式设置:代码仅设置了Accept头,但未指定Content-Type: application/json,服务器可能因无法识别请求体格式而拒绝请求。
  3. RestTemplate注入错误:同时使用@Autowired和new RestTemplate(),可能导致Spring容器中的RestTemplate实例与代码中创建的实例不一致,影响消息转换器的配置。
解决方案

1. 替换JSON处理方式,使用Jackson构建请求体

改用Jackson的ObjectMapper来构建请求体,或者直接使用POJO(推荐),确保RestTemplate能正确序列化请求体。

2. 显式设置Content-Type头

在HttpHeaders中添加Content-Type: application/json,明确告知服务器请求体的格式。

3. 修正RestTemplate注入方式

移除@Autowired后的赋值语句,若需要自定义RestTemplate,通过@Bean注解在配置类中创建实例。

修改后的代码示例
package at.acl.articledata.connector.smokeTest;

import at.acl.articledata.connector.pojos.request.Article;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.Collections;

@Component
public class SmokeTest {

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private ObjectMapper objectMapper;

    @PostConstruct
    private void floodDatabase(){
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        // 显式设置Content-Type
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("X-API-KEY", "myApiKey");

        // 使用Jackson构建请求体
        ObjectNode jsonArticle = objectMapper.createObjectNode();
        jsonArticle.put("ext_article_nr", "e001");
        jsonArticle.put("ean_numeric", BigDecimal.valueOf(420));
        jsonArticle.put("intern_art_nr", "i001");
        jsonArticle.put("article_name", "Flip Flops");
        jsonArticle.put("size", "45");
        jsonArticle.put("color", "Green");
        jsonArticle.put("group", "No Group");
        jsonArticle.put("brand", "Gucci");
        jsonArticle.put("season", "Summer");
        jsonArticle.put("article_link", "http://dummyimage.com/102x100.png/dddddd/000000");

        ArrayNode jsonArticleArray = objectMapper.createArrayNode();
        jsonArticleArray.add(jsonArticle);

        ObjectNode jsonBody = objectMapper.createObjectNode();
        jsonBody.put("count", 1);
        jsonBody.put("total_count", 8);
        jsonBody.set("data", jsonArticleArray);

        HttpEntity<ObjectNode> request = new HttpEntity<>(jsonBody, headers);

        ResponseEntity<String> response = restTemplate.exchange("correctServerIP", HttpMethod.POST, request, String.class);
        System.out.println("Post Response: " + response);
    }
}

额外建议:使用POJO替代手动构建JSON

如果已有Article类,可以创建一个包含请求体结构的POJO类,代码会更简洁易维护:

// 新增请求体POJO
public class ArticleBatchRequest {
    private int count;
    private int total_count;
    private List<Article> data;

    // Getter、Setter、构造方法
}

// 修改floodDatabase方法
@PostConstruct
private void floodDatabase(){
    HttpHeaders headers = new HttpHeaders();
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.add("X-API-KEY", "myApiKey");

    Article article = new Article();
    article.setExt_article_nr("e001");
    article.setEan_numeric(BigDecimal.valueOf(420));
    // 设置其他字段...

    ArticleBatchRequest requestBody = new ArticleBatchRequest();
    requestBody.setCount(1);
    requestBody.setTotal_count(8);
    requestBody.setData(Collections.singletonList(article));

    HttpEntity<ArticleBatchRequest> request = new HttpEntity<>(requestBody, headers);

    ResponseEntity<String> response = restTemplate.exchange("correctServerIP", HttpMethod.POST, request, String.class);
    System.out.println("Post Response: " + response);
}

内容的提问来源于stack exchange,提问作者Splatted I0I

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 05:10:55