首页 > 解决方案 > SpringBoot:HttpClientErrorException$BadRequest:400:调用restTemplate.postforEntity或restTemplate.exchange时[无正文]

问题描述

我正在尝试使用 restTemplate.exchange 和 restTemplate.postForEntity 从我的 springboot 应用程序中访问一个安静的端点,我收到 400 Bad request [no body] 异常。

我尝试了所有可能的解决方案来解决问题。从我使用 HttpURLConnection 到达端点的相同代码中,它工作正常。我能够得到有效的回应。我也试过从 Postman 打端点,效果很好

下面是端点代码

@RestController
@RequestMapping("auth")
@Slf4j
public class AuthController {

    @PostMapping(value = "/as/resourceOwner",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Token> getToken(@RequestParam(required = false)MultiValuedMap<?, ?> params) {
        log.info("token endpoint");
        return new ResponseEntity<>(new Token(), HttpStatus.OK);
    }
}

以下带有 HttpURLConnection 类的代码工作正常

public class Test {

    public static void main(String[] args) {
        try {
            URL url = new URL("http://localhost:8080/fc-services-mock-auth/fmrco/as/resourceOwner");
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setDoOutput(true);
            urlConnection.setRequestMethod("POST");
            urlConnection.setRequestProperty("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE);
            OutputStream writer = urlConnection.getOutputStream();
            writer.write("a=a&b=b".getBytes(StandardCharsets.UTF_8));
            writer.flush();
            writer.close();
            BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }

}

但是下面的带有 restTemplate 的代码不起作用

try {
        

    HttpEntity httpEntity = new HttpEntity<>(createBody(), createHeaders());
    ResponseEntity<String> response = restTemplate.exchange(new URI(endpointConfig.getTokenServiceUrl()),
            HttpMethod.POST, httpEntity, String.class);
            
    HttpEntity<MultiValueMap<String, String>> request =
            new HttpEntity<>(createBody(), createHeaders());

    ResponseEntity<TokenResponse> tokenResponse = restTemplate.postForEntity(
            new URI(endpointConfig.getTokenServiceUrl()),
            request,
            TokenResponse.class);

    logger.debug(" token process completed");
    return tokenResponse.getBody();
} catch (Exception e) {
    throw new TokenException(" token error: ", e);
}
    
    
private HttpHeaders createHeaders() {
    HttpHeaders headers = new HttpHeaders();
    headers.add("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE);
    return headers;
}

private  MultiValueMap createBody() {
    MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
    map.add("client_id", applicationConfig.getTokenClientId());
    map.add("client_secret", applicationConfig.getTokenClientSecret());
    map.add("grant_type", "password");
    map.add("username", applicationConfig.getTokenUsername());
    map.add("password", applicationConfig.getTokenPassword());

    return map;
}

谁能告诉我这里有什么问题?

此外,我还编写了另一个 GET RESTful 端点,如下所示,在使用 Exchange 访问端点时,我仍然遇到相同的错误。

@GetMapping(value = "test", produces =  MediaType.TEXT_PLAIN_VALUE)
    public ResponseEntity<String> test() {
        return new ResponseEntity<>("Hello", HttpStatus.OK);
    }

try {
            HttpHeaders headers = new HttpHeaders();
            headers.setAccept(Arrays.asList(MediaType.TEXT_PLAIN));
            HttpEntity<MultiValueMap<String, String>> entity =
                    new HttpEntity<>(null, headers);
            ResponseEntity<String> response = restTemplate.exchange(
                    "http://localhost:8080/context/path",
                    HttpMethod.GET, entity, String.class);
        } catch (Exception e) {
            System.out.println(e);
        }

另外,我故意尝试对 get 端点进行 POST 调用,以查看它是否返回 405 Method not allowed。但令我惊讶的是,它仍然返回 400 Bad Request no body。

标签: springspring-bootspring-restcontrollerspring-rest

解决方案


我终于弄明白了。restTemplate 配置为使用代理。我删除了代理,它现在工作正常。


推荐阅读