RESTAPI可以从Postman调用,显示来自Java的400个错误请求

RESTAPI可以从Postman调用,显示来自Java的400个错误请求,java,rest,Java,Rest,我正在尝试使用POST-restful服务。当我在邮递员身上试用时,我得到了成功的回复。但当我用下面的代码在java上尝试时,我得到的响应代码是400。在《邮递员》中,我用替换转义字符粘贴相同的输入 try { URL url = new URL("https://localhost/PasswordVault/api/Accounts"); HttpURLConnection conn = (HttpURLConnection) url.openConne

我正在尝试使用POST-restful服务。当我在邮递员身上试用时,我得到了成功的回复。但当我用下面的代码在java上尝试时,我得到的响应代码是400。在《邮递员》中,我用替换转义字符粘贴相同的输入

try {

    URL url = new URL("https://localhost/PasswordVault/api/Accounts");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("POST");
    conn.setDoOutput(true);

    conn.setRequestProperty("Content-Type", "application/json");
    String input = "{\"qty\":100,\"name\":\"iPad 4\", \"detail\":{\"ver\":\"2020\",\"productionDate\":\"2020\"}}";

    OutputStream os = conn.getOutputStream();
    os.write(input.getBytes());
    os.flush();


    if (conn.getResponseCode() != HttpURLConnection.HTTP_CREATED) {
        throw new RuntimeException("Failed : HTTP error code : "
                + conn.getResponseCode());
    }

    BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));

    String output;
    System.out.println("Output from Server .... \n");
    while ((output = br.readLine()) != null) {
        System.out.println(output);
    }

    conn.disconnect();
} catch (Exception e) {
        System.out.println("Exception:- " + e);
}
一些想法:

  • 用UTF-8编码您的请求post数据:
    “post数据”.getBytes(StandardCharsets.UTF_8)
  • 阅读服务器的响应(不仅仅是代码),希望获得有关问题的更多详细信息(
    connection.getErrorStream()
  • 是否缺少授权标头?(API令牌等)
  • 使用单引号使请求数据字符串更具可读性,或者使用JSON库避免手动错误
  • 在flush()之后还调用OutputStream.close()
例如


我强烈建议您为此使用库。 您可以使用Jackson,这大大简化和标准化了java与远程HTTP服务的交互

以下几点可以让您开始:

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

public class ApiClient
{

    private transient Client client;
    protected transient WebTarget apiRoot;

    public ApiClient(String rootUrl) 
    {
        this.client = ClientBuilder.newBuilder().build();
        // The root URL is your API starting point, e.g. https://host/api
        this.apiRoot = client.target(rootUrl);
    }

    public Response doPostToAccounts(String data)
    {
        try 
        {
            // This is where you execute your POST request
            return apiRoot.path("/Accounts")
                .request(MediaType.APPLICATION_JSON)
                .post(Entity.entity(data, MediaType.APPLICATION_JSON));
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

}

首先,检查邮递员可能正在发送而您的代码没有发送的请求头。在发送请求之前,您可能需要向请求中添加一些标题。第二,我强烈建议使用一些3d方Http客户端库,而不是自己编写Http请求。一些著名的图书馆是和。我个人使用自己的Http客户端,它是MgntUtils开源库的一部分。欢迎您也尝试一下。以下是简化代码,仅用于演示如何从站点读取一些响应:

    try {
        HttpClient client = new HttpClient();
        client.setConnectionUrl("https://www.yahoo.com/");
        String result = client.sendHttpRequest(HttpMethod.GET);
        System.out.println(result);
    } catch (IOException e) {
        System.out.println(TextUtils.getStacktrace(e, "com.mgnt."));
    }
    

当然,您也可以使用这个库发送POST请求、设置请求头、读取文本或二进制响应和响应头。这里是一个链接。该库本身可以随时访问,包括Javadoc和源代码

谢谢您的回复。我试过你的解决办法。我收到“服务器重定向次数太多(20)”错误。然后我搜索了它,发现添加了ClientProperties.FOLLOW_重定向,false可能已经解决了问题,但这次我得到了301-永久移动你通过了
https://localhost/PasswordVault/api
作为根URL,
/Accounts
作为路径?通常情况下,301意味着它希望在结尾处有一个/。另外:
响应
对象将包含有关其重定向到何处的信息。感谢您的警告。正如你所提到的,我错误地复制了url。更正后,我又收到了400个错误的请求。我尝试了3种不同的调用服务的方法。得到同样的400回答。我很肯定邮递员的要求与此有所不同。我将在我的请求中添加postman标头中的额外内容。请记住HTTP 400错误通常意味着:请求正文对于资源不正确,或者内容类型对于正文不正确。感谢您的回复。正如你所建议的,我试过使用ApacheHttpClien。但是我仍然收到400个错误的请求-响应。因此,检查响应头,您可能会找到您收到错误的原因。此外,如果您使用我的库,如果返回错误代码,它会自动检索errorStream。因此,您可以在无需额外编码的情况下获得更多信息。我正在从另一个URL获取授权令牌。令牌URL响应包含额外的引号。这就是问题所在。真可惜。谢谢你的帮助。太好了,很高兴听到这个消息!
    try {
        HttpClient client = new HttpClient();
        client.setConnectionUrl("https://www.yahoo.com/");
        String result = client.sendHttpRequest(HttpMethod.GET);
        System.out.println(result);
    } catch (IOException e) {
        System.out.println(TextUtils.getStacktrace(e, "com.mgnt."));
    }