如何向所有HttpClient请求方法添加参数?

13

我正在编写一些Java代码,使用Apache HttpClient 版本4.2.2 来调用RESTful的第三方API。该API具有使用HTTP GET, POST, PUTDELETE 方法的功能。需要注意的是,我使用的是4.x.x版本而不是3.x.x版本,因为从3到4版本API发生了很多变化。所有相关的示例都是针对3.x.x版本的。

所有API调用都需要您提供api_key作为一个参数(无论您使用哪种方法)。这意味着无论我是进行GET、POST或其他操作,我都需要提供这个api_key,以便进行服务器端身份验证。

// Have to figure out a way to get this into my HttpClient call,
// regardless of whether I'm using: HttpGet, HttpPost, HttpPut
// or HttpDelete...
String api_key = "blah-whatever-my-unique-api-key";

我正在尝试弄清楚如何在不考虑请求方法的情况下(这取决于我要访问哪个RESTful API方法),为HttpClient提供api_key。看起来HttpGet甚至不支持参数的概念,而HttpPost使用了一个称为HttpParams的东西;但是这些HttpParams似乎只存在于HttpClient的3.x.x版本中。

所以我想问:正确的v4.2.2方法是如何将我的api_key字符串添加到所有四种请求中:

  • HttpGet
  • HttpPost
  • HttpPut
  • HttpDelete

提前致谢。

3个回答

32

您可以使用 URIBuilder 类为所有的HTTP方法构建请求URI。URI构建器提供setParameter 方法来设置参数。

URIBuilder builder = new URIBuilder();
builder.setScheme("http").setHost("www.google.com").setPath("/search")
    .setParameter("q", "httpclient")
    .setParameter("btnG", "Google Search")
    .setParameter("aq", "f")
    .setParameter("oq", "");
URI uri = builder.build();
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());

输出应该是

http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq= 

4
感谢@rboorgapally(+1)的回复,但我认为这仅适用于HttpGet(在查询字符串中设置参数),对于HttpPostHttpPutHttpDelete没有任何影响。 尽管每个方法都有一个接受URI参数的构造函数,但我不认为URIBuilder隐式地知道如何将查询字符串参数转换为HttpPost POST变量等。 因此,尽管我将使用带有完整查询字符串的URI传递非 HttpGet 方法,但我不认为它们会知道如何将该查询字符串转换为他们知道如何处理的数据格式。 - user1768830
我想补充一下,setParameter 方法会覆盖现有的值。因此,如果要在 URI 中设置 List 变量,例如 /search?q=1&q=2&y=3,那么这里的 q 是一个列表,其最终值将是 2 而不是 [1,2]。为了避免这种情况,可以使用 URIBuilder 的 addParameter 方法。文档:http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/utils/URIBuilder.html#addParameter%28java.lang.String,%20java.lang.String%29 - Siddharth Trikha
那么这个答案适用于非 GET 请求吗? - Kartik Chugh

6
您也可以使用这种方法来传递一些 HTTP 参数并发送 JSON 请求:
(注意:我添加了一些额外的代码,以防对其他读者有所帮助,并且导入是从 org.apache.http 客户端库中进行的)
public void postJsonWithHttpParams() throws URISyntaxException, UnsupportedEncodingException, IOException {

    //add the http parameters you wish to pass
    List<NameValuePair> postParameters = new ArrayList<>();
    postParameters.add(new BasicNameValuePair("param1", "param1_value"));
    postParameters.add(new BasicNameValuePair("param2", "param2_value"));

    //Build the server URI together with the parameters you wish to pass
    URIBuilder uriBuilder = new URIBuilder("http://google.ug");
    uriBuilder.addParameters(postParameters);

    HttpPost postRequest = new HttpPost(uriBuilder.build());
    postRequest.setHeader("Content-Type", "application/json");

    //this is your JSON string you are sending as a request
    String yourJsonString = "{\"str1\":\"a value\",\"str2\":\"another value\"} ";

    //pass the json string request in the entity
    HttpEntity entity = new ByteArrayEntity(yourJsonString.getBytes("UTF-8"));
    postRequest.setEntity(entity);

    //create a socketfactory in order to use an http connection manager
    PlainConnectionSocketFactory plainSocketFactory = PlainConnectionSocketFactory.getSocketFactory();
    Registry<ConnectionSocketFactory> connSocketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", plainSocketFactory)
            .build();

    PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(connSocketFactoryRegistry);

    connManager.setMaxTotal(20);
    connManager.setDefaultMaxPerRoute(20);

    RequestConfig defaultRequestConfig = RequestConfig.custom()
            .setSocketTimeout(HttpClientPool.connTimeout)
            .setConnectTimeout(HttpClientPool.connTimeout)
            .setConnectionRequestTimeout(HttpClientPool.readTimeout)
            .build();

    // Build the http client.
    CloseableHttpClient httpclient = HttpClients.custom()
            .setConnectionManager(connManager)
            .setDefaultRequestConfig(defaultRequestConfig)
            .build();

    CloseableHttpResponse response = httpclient.execute(postRequest);

    //Read the response
    String responseString = "";

    int statusCode = response.getStatusLine().getStatusCode();
    String message = response.getStatusLine().getReasonPhrase();

    HttpEntity responseHttpEntity = response.getEntity();

    InputStream content = responseHttpEntity.getContent();

    BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
    String line;

    while ((line = buffer.readLine()) != null) {
        responseString += line;
    }

    //release all resources held by the responseHttpEntity
    EntityUtils.consume(responseHttpEntity);

    //close the stream
    response.close();

    // Close the connection manager.
    connManager.close();
}

1

这里需要明确说明必须使用的Apache软件包,因为有多种实现GET请求的方法。

例如,您可以使用Apache CommonsHttpComponents。在本例中,我将使用HttpComponents (org.apache.http.*)

请求类:

package request;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import Task;

public void sendRequest(Task task) throws URISyntaxException {

    URIBuilder uriBuilder = new URIBuilder();
    uriBuilder.setScheme("http")
            .setHost("localhost")
            .setPort(8080)
            .setPath("/TesteHttpRequest/TesteDoLucas")
            .addParameter("className", task.getClassName())
            .addParameter("dateExecutionBegin", task.getDateExecutionBegin())
            .addParameter("dateExecutionEnd", task.getDateExecutionEnd())
            .addParameter("lastDateExecution", task.getDateLastExecution())
            .addParameter("numberExecutions", Integer.toString(task.getNumberExecutions()))
            .addParameter("idTask", Integer.toString(task.getIdTask()))
            .addParameter("numberExecutions" , Integer.toString(task.getNumberExecutions()));
    URI uri = uriBuilder.build();

    HttpGet getMethod = new HttpGet(uri);

    CloseableHttpClient httpclient = HttpClients.createDefault();

    CloseableHttpResponse response = null;

    try {
        response = httpclient.execute(getMethod);
    } catch (IOException e) {
        //handle this IOException properly in the future
    } catch (Exception e) {
        //handle this IOException properly in the future
    }
}

我将为您翻译此内容:

我正在使用Tomcat v7.0服务器,然后上面的类接收一个任务并将其发送到链接中特定的servlet http://localhost:8080/TesteHttpRequest/TesteDoLucas

我的动态Web项目名为TesteHttpRequest,我的servlet通过url /TesteDoLucas 进行响应。

任务类:

package bean;

public class Task {

    private int idTask;
    private String taskDescription;
    private String dateExecutionBegin;
    private String dateExecutionEnd;
    private String dateLastExecution;
    private int numberExecutions;
    private String className;

    public int getIdTask() {
        return idTask;
    }

    public void setIdTask(int idTask) {
        this.idTask = idTask;
    }

    public String getTaskDescription() {
        return taskDescription;
    }

    public void setTaskDescription(String taskDescription) {
        this.taskDescription = taskDescription;
    }

    public String getDateExecutionBegin() {
        return dateExecutionBegin;
    }

    public void setDateExecutionBegin(String dateExecutionBegin) {
        this.dateExecutionBegin = dateExecutionBegin;
    }

    public String getDateExecutionEnd() {
        return dateExecutionEnd;
    }

    public void setDateExecutionEnd(String dateExecutionEnd) {
        this.dateExecutionEnd = dateExecutionEnd;
    }

    public String getDateLastExecution() {
        return dateLastExecution;
    }

    public void setDateLastExecution(String dateLastExecution) {
        this.dateLastExecution = dateLastExecution;
    }

    public int getNumberExecutions() {
        return numberExecutions;
    }

    public void setNumberExecutions(int numberExecutions) {
        this.numberExecutions = numberExecutions;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }
}

Servlet类:

package servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/TesteDoLucas")
public class TesteHttpRequestServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;

     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String query = request.getQueryString();
        System.out.println(query);
     }

     protected void doPost(HttpServletRequest request, HttpServletResponse   response) throws ServletException, IOException {
        doGet(request, response);
        }
    }

发送的查询参数将在控制台显示。

className=java.util.Objects%3B&dateExecutionBegin=2016%2F04%2F07+22%3A22%3A22&dateExecutionEnd=2016%2F04%2F07+06%3A06%3A06&lastDateExecution=2016%2F04%2F07+11%3A11%3A11&numberExecutions=10&idTask=1&numberExecutions=10

为了修复编码问题,您可以查看这里:HttpServletRequest UTF-8 编码

你的答案与现有答案有何不同?它聚合了什么价值?你应该把重点放在向请求中添加参数上。在问题的背景下,Task类是无关紧要的。 - cassiomolin
我发布了这个问题,因为几天前我也有同样的疑问,而我在stackoverflow上找到的每一个答案都忽略了发送请求的整个过程。我的意思是,添加新参数的部分是正确的,但是我不得不在其他主题中搜索如何完成请求(我只在官方文档中找到了),这花费了我很多时间。它可以大大简化你的工作方式,你可以复制和粘贴它,并获得一个真正的功能请求示例,其中包含你获取的参数,节省了你在文档中搜索细节的时间。任务类是无关紧要的,但可以帮助例如... - Lucas Amorim Silva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接