【问题标题】:HTTP(S) request to any URL in Java [duplicate]对Java中任何URL的HTTP(S)请求[重复]
【发布时间】:2021-02-17 05:27:45
【问题描述】:

我需要向用户提供的 URL(可以是 http 或 https)发出 GET 请求

在 JavaScript 中我可以做到:

fetch(prompt()).then(r => r.text()).then(console.log)

Java 的等效代码是什么?

这如何与自定义证书一起使用?

【问题讨论】:

标签: java http networking https


【解决方案1】:

网址/网址连接

Java 与 js 有着根本的不同。

其中一个区别是 java 是阻塞/同步的,这意味着默认方式是等待请求:

已知/可信证书或 HTTP

final URL url=new URL("url here");//create url
//Open an InputStream (binary) to the URL
//Convert it to a reader(text)
//Use buffering
try(BufferedReader br=new BufferedReader (new InputStreamReader(url.openStream(),StandardCharsets.UTF_8))){
    br.lines().forEach(System.out::println);//print all lines
}catch(IOException e){
    //Error handling
}

try-with-resources 语句会在不再需要资源时自动关闭它们。

这样做很重要,这样您就不会发生资源泄漏。

自签名/自定义证书

this answer 中所述,您可以配置TrustStore 以添加自定义证书:

//Load certificate
File crtFile = new File("server.crt");
Certificate certificate = CertificateFactory.getInstance("X.509").generateCertificate(new FileInputStream(crtFile));

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("server", certificate);

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);

final URL url=new URL("url here");//create url

HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();//open a connection
connection.setSSLSocketFactory(sslContext.getSocketFactory());

//Open an InputStream (binary) to the URL
//Convert it to a reader(text)
//Use buffering
try(BufferedReader br=new BufferedReader (new InputStreamReader(connection.getInputStream(),StandardCharsets.UTF_8))){
    br.lines().forEach(System.out::println);//print all lines
}catch(IOException e){
    //Error handling
}


HttpClient

如果您使用 Java 11 或更新版本,您还可以尝试使用异步 HttpClient,如 here 所述。

这更类似于 JS 的方式。

已知/可信证书或 HTTP

HttpClient client = HttpClient.newHttpClient();//create the HTTPClient
HttpRequest request = HttpRequest.newBuilder()//create a request object, GET is the default
      .uri(URI.create("url here"))//set the url
      .build();//build the request object
client.sendAsync(request, BodyHandlers.ofString())//send the request in a background thread (fetch() in your code)
      .thenApply(HttpResponse::body)//get the body as a string (.then(r=>r.text()) in your code))
      .thenAccept(System.out::println);//print it (.then(console.log) in your code)

这种方法与您的 JS 示例一样是异步的。

自签名/自定义证书

如果您想使用自定义证书,可以使用sslContect 方法,如here

//Load certificate
File crtFile = new File("server.crt");
Certificate certificate = CertificateFactory.getInstance("X.509").generateCertificate(new FileInputStream(crtFile));

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("server", certificate);

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);

//Execute the request
HttpClient client = HttpClient.newBuilder()//create a builder for the HttpClient
    .sslContext(sslContext)//set the SSL context
    .build();//build the HttpClient
HttpRequest request = HttpRequest.newBuilder()//create a request object, GET is the default
      .uri(URI.create("url here"))//set the url
      .build();//build the request object
client.sendAsync(request, BodyHandlers.ofString())//send the request in a background thread (fetch() in your code)
      .thenApply(HttpResponse::body)//get the body as a string (.then(r=>r.text()) in your code))
      .thenAccept(System.out::println);//print it (.then(console.log) in your code)

外部库

第三种可能性是使用像OkHttp这样的外部库。

【讨论】:

  • javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径跨度>
  • JavaScript 代码只是演示我想要做什么的示例
  • 你用的是什么java版本?您使用旧版本的 Java 8 吗?服务器使用什么https认证?服务器是否使用 Let's Encrypt X3?
  • 正如我在问题中所说,服务器证书是未知的,因为它是用户提供的。我正在使用 Java 8
  • 查看我对如何使用自定义证书的编辑。
【解决方案2】:

来自 java.net 包的

HttpURLConnection 类可用于发送 以编程方式进行 Java HTTP 请求。今天我们将学习如何使用 HttpURLConnection 在 java 程序中发送 GETPOST 请求,然后打印响应。

以下是我们使用 HttpURLConnection 类发送 Java HTTP 请求时需要遵循的步骤。

  1. 从 GET/POST URL 字符串创建 URL 对象。
  2. 在返回实例的 URL 对象上调用 openConnection() 方法 HttpURLConnection
  3. HttpURLConnection实例中设置请求方法,默认 值为 GET。
  4. HttpURLConnection 实例上调用 setRequestProperty() 方法 设置请求标头值,例如“User-Agent”和 “接受语言”等。
  5. 我们可以调用getResponseCode()来获取响应HTTP代码。 这样我们就知道请求是否已成功处理 是否抛出任何 HTTP 错误消息。
  6. 对于 GET,我们可以简单地使用 Reader 和 InputStream 来读取 响应并相应地处理它。
  7. 对于 POST,在读取响应之前,我们需要获取 OutputStream 从 HttpURLConnection 实例并将 POST 参数写入 它。

HttpURLConnection 示例

基于以上步骤,下面是一个示例程序,展示了使用 HttpURLConnection 来发送 Java GET 和 POST 请求。

JAVA 代码

package com.mr.rockerz.HttpUrlExample;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpURLConnectionExample {

    private static final String USER_AGENT = "Mozilla/5.0";

    private static final String GET_URL = "https://localhost:9090/SpringMVCExample";

    private static final String POST_URL = "https://localhost:9090/SpringMVCExample/home";

    private static final String POST_PARAMS = "userName=Pankaj";

    public static void main(String[] args) throws IOException {

        sendGET();
        System.out.println("GET DONE");
        sendPOST();
        System.out.println("POST DONE");
    }

    private static void sendGET() throws IOException {
        URL obj = new URL(GET_URL);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod("GET");
        con.setRequestProperty("User-Agent", USER_AGENT);
        int responseCode = con.getResponseCode();
        System.out.println("GET Response Code :: " + responseCode);
        if (responseCode == HttpURLConnection.HTTP_OK) { // success
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream()));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();

            // print result
            System.out.println(response.toString());
        } else {
            System.out.println("GET request not worked");
        }

    }

    private static void sendPOST() throws IOException {
        URL obj = new URL(POST_URL);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod("POST");
        con.setRequestProperty("User-Agent", USER_AGENT);

        // For POST only - START
        con.setDoOutput(true);
        OutputStream os = con.getOutputStream();
        os.write(POST_PARAMS.getBytes());
        os.flush();
        os.close();
        // For POST only - END

        int responseCode = con.getResponseCode();
        System.out.println("POST Response Code :: " + responseCode);

        if (responseCode == HttpURLConnection.HTTP_OK) { //success
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream()));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();

            // print result
            System.out.println(response.toString());
        } else {
            System.out.println("POST request not worked");
        }
    }

}

当我们执行上述程序时,我们得到以下响应。

GET Response Code :: 200
<html><head>    <title>Home</title></head><body><h1>    Hello world!  </h1><P>  The time on the server is March 6, 2015 9:31:04 PM IST. </P></body></html>
GET DONE
POST Response Code :: 200
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>User Home Page</title></head><body><h3>Hi Pankaj</h3></body></html>
POST DONE

如果您有任何疑问,请在评论中提问。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-31
    • 2016-06-16
    • 2014-09-21
    • 1970-01-01
    • 2014-01-20
    • 2016-10-13
    • 2018-08-09
    • 1970-01-01
    相关资源
    最近更新 更多