Java 中的 HTTP 请求

原文:https://www.studytonight.com/java-examples/http-requests-in-java

HttpURLConnection类是java.net包的一部分,用于发送 HTTP 请求和获取响应。这是一个抽象类,扩展了URLConnection类。该类提供基本功能。高级功能最好使用其他 HTTP 库。在本教程中,我们将学习如何使用这个类来处理 HTTP 请求。

使用 http 连接创建请求

要获取HttpURLConnection类的实例,我们需要在 URL 上使用 openConnection() 方法。还需要显式强制转换。

我们可以通过在 HttpURLConnection 对象上使用 setRequestMethod() 来设置请求的类型。它可以采用以下值之一,默认值是 GET。

  • 得到
  • 邮政
  • 选择
  • 删除
  • 微量
import java.net.*;

public class Demo
{
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("https://www.studytonight.com");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
    }
}

添加请求参数

我们可以向我们的 HTTP 请求添加请求或查询参数。我们首先需要使用 setDoOutput() 方法在连接对象上启用写入。然后我们可以获取数据输出流并向其写入字符串。字符串的格式必须为“参数 1=val1 &参数 2=val2 &参数 3=val3”。

import java.net.*;
import java.io.*;
public class Demo
{
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("https://www.demo.com/");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        connection.setDoOutput(true);
        String parameter = "param1=val1&param2=val2";

        DataOutputStream outputStream = (DataOutputStream)connection.getOutputStream();
        outputStream.writeChars(parameter);
        outputStream.flush();
        outputStream.close();
    }
}

我们可以通过编写一个方法来简化我们的工作,该方法采用一个 HashMap,并从映射的键值对中生成参数值字符串。

import java.net.*;
import java.io.*;
import java.util.*;

public class Demo
{
    public static String addParameters(HashMap<String, String> parameters) throws Exception
    {
        StringBuilder sb = new StringBuilder();        
        for(Map.Entry<String, String> e : parameters.entrySet())
        {
            sb.append(URLEncoder.encode(e.getKey(), "UTF-8"));
            sb.append("=");
            sb.append(URLEncoder.encode(e.getValue(), "UTF-8"));
            sb.append("&");
        }        
        String params = sb.toString();
        if(params.length() > 0)
            return params.substring(0, params.length() - 1);
        else
            return params;
    }
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("https://www.demo.com/");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setDoOutput(true);
        HashMap<String, String> parameters = new HashMap<>();
        parameters.put("param1", "val1");
        parameters.put("param2", "val2");
        parameters.put("param3", "val3");

        String params = addParameters(parameters);

        DataOutputStream outputStream = (DataOutputStream)connection.getOutputStream();
        outputStream.writeChars(params);
        outputStream.flush();
        outputStream.close();
    }
}

读取请求标题

为了读取请求头的值,我们在连接对象上使用 getHeaderField() 方法。此方法可以将标题字段的名称作为参数,并返回相应的值。

import java.net.*;

public class Demo
{
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("https://www.studytonight.com/");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        String date = connection.getHeaderField("Date");
        System.out.print(date);
    }
}

Fri,2021 年 8 月 6 日,格林尼治时间 02:52:29

我们也可以使用一个整数来获取第 n 个标题字段。使用 getHeaderFieldKey() 方法获取第 n 个头字段的名称。

import java.net.*;

public class Demo
{
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("https://www.studytonight.com/");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        String headerKey1 = connection.getHeaderFieldKey(1);
        String headerField1 = connection.getHeaderField(1);

           String headerKey2 = connection.getHeaderFieldKey(2);
        String headerField2 = connection.getHeaderField(2);

        System.out.println("Header Field 1: " + headerKey1 + "-->" + headerField1);
        System.out.println("Header Field 2: " + headerKey2 + "-->" + headerField2);
    }
}

标头字段 1:日期- > Fri,2021 年 8 月 6 日 02:52:29 格林尼治标准时间 标头字段 2:服务器->Apache/2 . 4 . 46(Unix)OpenSSL/1 . 1 . 1d

设置请求标题

我们可以在HttpURLConnection实例上使用 setRequestProperty() 方法来设置请求头值。让我们设置连接和缓存控制头的值。

import java.net.*;

public class Demo
{
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("https://www.studytonight.com/");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("Cache-Control", "no-cache");
    }
}

设置超时

我们可以使用 HttpURLConnection 类的 setConnectTimeout()setReadTimeout() 方法来更改连接和读取的默认超时值。我们可以使用 getConnectTimeout()getReadTimeout() 方法查看这些值。

import java.net.*;

public class Demo
{
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("https://www.studytonight.com/");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        System.out.println("Default Timeout Values:");
        System.out.println("Connect Timeout: " + connection.getConnectTimeout());
        System.out.println("Read Timeout: " + connection.getReadTimeout());

        connection.setConnectTimeout(10000);
        connection.setReadTimeout(10000);
        //After
        System.out.println("After Setting Timeout Values:");
        System.out.println("Connect Timeout: " + connection.getConnectTimeout());
        System.out.println("Read Timeout: " + connection.getReadTimeout());
    }
}

默认超时值: 连接超时:0 读取超时:0 设置超时值后: 连接超时:10000 读取超时:10000

处理饼干

HttpCookieCookieManager课程可以帮助我们使用饼干。为了读取 Cookie,我们可以获取 Set-Cookie 头的值,并使用 HttpCookie 类的 parse() 方法对其进行解析。

import java.net.*;
import java.util.*;
import org.apache.commons.lang3.StringUtils;

public class Demo
{
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("https://www.gmail.com/");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        String  cookieHeaderField = connection.getHeaderField("Set-Cookie");
        List<HttpCookie> cookiesList = HttpCookie.parse(cookieHeaderField);

        System.out.println(cookieHeaderField);
        System.out.println(cookiesList);        
    }
}

Host-gap = 1:wozoyd 84 dr 89 kgux6-xfHQcJX0PpqA:KS-fe4ij 1w 4 gim;路径=/;到期=孙,06-2023 年 8 月 06 日 06:23:56 格林尼治标准时;安全;HttpOnly 优先级=高 [ 主机-间隙= 1:wozoyd 84 dr 89 kgux6-xfhqcjx0 ppqa:KS-fe4ij 1 w4 gim]

我们也可以在食谱中加入饼干。我们可以使用 CookieStore 来设置连接的 Cookie 请求属性。为此,我们需要关闭并重新打开我们的连接。

public class Demo
{
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("https://www.gmail.com/");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        String  cookieHeaderField = connection.getHeaderField("Set-Cookie");
        List<HttpCookie> cookiesList = HttpCookie.parse(cookieHeaderField);

        CookieManager cm = new CookieManager();
        cookiesList.forEach(cookie -> cm.getCookieStore().add(null, cookie));

        connection.disconnect();
        connection = (HttpURLConnection) url.openConnection();
        connection.setRequestProperty("Cookie", 
        StringUtils.join(cm.getCookieStore().getCookies(), ";"));
    }
}

处理重定向

我们可以在 HttpURLConnection 实例上使用setinstancefloredirections()方法来启用或禁用重定向。

import java.net.*;

public class Demo
{
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("https://www.google.com/");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        connection.setInstanceFollowRedirects(true);
    }
}

我们还可以通过使用setfollowsredirections()方法来启用或禁用所有连接的重定向。

HttpURLConnection.setFollowRedirects(true);

我们可以使用位置头字段来获取新的重定向网址。我们可以用它向新的重定向网址发送请求。请注意,重定向的响应代码是 301(永久移动)302(临时重定向)

import java.net.*;

public class Demo
{
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("https://www.google.com/");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");        
        boolean redirect = false;        
        if(connection.getResponseCode() == HttpURLConnection.HTTP_MOVED_TEMP || connection.getResponseCode() == HttpURLConnection.HTTP_MOVED_PERM)
            redirect = true;        
        if(redirect)
        {
            String redirectURL = connection.getHeaderField("Location");
            URL newURL = new URL(redirectURL);
            connection = (HttpURLConnection) newURL.openConnection();
        }
    }
}

阅读回应

HttpURLConnection 类提供了几种方法来读取对我们请求的响应。

读取响应代码和响应消息

我们可以在连接实例上使用 getResponseCode()getResponseMessage() 方法来读取响应代码和响应消息。

import java.net.*;

public class Demo
{    
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("http://www.google.com");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        int responseCode = connection.getResponseCode();
        String responseMsg = connection.getResponseMessage();
        System.out.print("Response Code: " + responseCode + " Response Message: " + responseMsg);
    }
}

响应代码:200 响应消息:OK

读取响应标题

我们可以使用 getHeaderField() 方法来访问单个头字段。我们可以使用 getHeaderFields() 方法获取所有的头。它将返回一个映射集合。映射中的每个键表示标题字段,相应的值存储在列表中。

import java.net.*;
import java.util.List;
import java.util.Map;

public class Demo
{
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("https://www.studytonight.com/");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        Map<String, List<String>> headerFields = connection.getHeaderFields();

        for(Map.Entry<String, List<String>> e : headerFields.entrySet())
            System.out.println(e.getKey() + "-->" + e.getValue());
    }
}

传输-编码- >【分块】 保活- >【超时=5,最大= 100】 空->【HTTP/1.1 200 OK】 服务器->【Apache/2 . 4 . 46(Unix)OpenSSL/1 . 1 . 1d】 X-内容-类型-选项->【nosniff】 连接- >【保活】【T6 包括域名;预加载] 缓存-控制- >【无存储,无缓存,必须-重新验证】 Vary - >【接受-编码】 Set-Cookie->【phpsesid = 8 iqquicvn 5 ada 6 cjb1 ktkbjlcg;路径=/] 过期->【1981 年 11 月 19 日星期四格林尼治时间 08:52:00】 X-XSS-保护->【1;模式=块] 内容-类型- >【文本/html;charset = UTF-8] X-power-By->【PHP/7 . 4 . 15】

阅读回复内容

我们可以借助 HttpURLConnection 对象的 InputStream 读取响应内容。如果响应代码大于 200,那么我们将使用geterrortstream()方法。否则,请使用 getInputStream()方法。我们将使用BufferedReader类来包装InputStreamReader

import java.net.*;
import java.io.*;

public class Demo
{    
    public static void main(String[] args) throws Exception
    {
        URL url = new URL("http://www.google.com");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        InputStreamReader isr;
        if(connection.getResponseCode() > 299)
            isr = new InputStreamReader(connection.getErrorStream());
        else
            isr = new InputStreamReader(connection.getInputStream());

        BufferedReader br = new BufferedReader(isr);

        String line;
        while ((line = br.readLine()) != null)
            System.out.println(line);
    }
}

摘要

HTTP 连接类经常用于处理 HTTP 请求。这个类是 java.net 包的一部分,它扩展了 URLConnection 类。在本教程中,我们学习了这门课的基础知识。我们学习了如何从一个网址创建一个连接。我们学习了如何设置不同的属性和头值。我们还学习了如何读取响应状态、响应头和响应内容。