A list,

To put it simply, HttpURLConnection is the basic class library provided by Java to initiate HTTP requests, providing the basic functions of HTTP requests, but less encapsulation, in use, a lot of content needs to be set up, but also need to process their own request flows and response flows.

2. Get connections

Get an HttpURLConnection object as follows:

    // Define the URL object
	final URL url = new URL("http//ip:port/xxx");
    // Get the URL link
    URLConnection urlConnection =  url.openConnection();
    // Because the URL is a subclass of the URLConnection class generated based on the protocol in the URL (HTTP in this case)
    // HttpURLConnection. Therefore, convert this to an HttpURLConnection subclass for convenience
    // More apis in
    HttpURLConnection connection = (HttpURLConnection)urlConnection;
Copy the code

3. Set parameters

timeout

To prevent Http requests from being unreachable for a long time, you can set the timeout period in the following ways

 	// Set the connection timeout period. The value must be greater than 0. 0 indicates no timeout.
    connection.setConnectTimeout(30000);   
	// Set the read timeout period. The value must be greater than 0. 0 indicates that the timeout unit is milliseconds
    connection.setReadTimeout(60000);
Copy the code

Set request method

Http requests include GET, POST, and PUT methods. You can use the following methods to set the request method of an HttpURLConnection

// Set it to GET request,
connection.setRequestMethod("GET");
Copy the code

Note: The method must be set to uppercase, otherwise the following error will be reported

java.net.ProtocolException: Invalid HTTP method: get
Copy the code

You can set the enumeration type by defining it as follows:

// Define the request method enumeration class
public enum HttpMethod {
    GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH
  }

// Set the request method using enumeration
connection.setRequestMethod(HttpMethod.POST.name());
Copy the code

Request header information

Setting a custom request header or changing the value of conent-type can be done as follows:

// Set the request type to application/json
connection.setRequestProperty("Content-Type"."application/json; charset=UTF-8");
// Set the acceptable data type
connection.setRequestProperty("Accept"."* / *");
// Set the link to keep long
connection.setRequestProperty("Connection"."Keep-Alive");
// Set the custom header Token
connection.setRequestProperty("Token"."123456");
Copy the code

The other parameters

// Set not to use cache. Default is true
connection.setUseCaches(false);
// Sets whether redirect is supported for a single request. By default, this value is set to the setFollowRedirects method
connection.setInstanceFollowRedirects(false);

// Set whether to redirect or not. Note that this method is static, indicating that all requests do not support redirection. Default value: true
HttpURLConnection.setFollowRedirects(false);

Copy the code

Note:

All parameters must be set before the connection is established; otherwise, the following error will be reported

java.lang.IllegalStateException: Already connected
Copy the code

4. Establish a connection

Explicit connection

After all the parameters are set, you can make an explicit connection by calling the Connect method. As follows:

    // Call open connection, call this method, just establish a connection, does not send data.
    connection.connect();
Copy the code

Implicit linking

In addition to the above call connect to explicitly establish a connection, this method is implicitly called when the following method is called to establish a connection.

    // Get the output stream
    connection.getOutputStream();
    // Get the input stream
    connection.getInputStream();
Copy the code

In practice, the connect() method is not called to open the connection explicitly, because the result of the request is usually obtained when a network request is made.

5. Send data

A POST request

As we all know, the data in an HTTP POST request is contained in the request body. HttpURLConnection to send data via POST request, obtain the connected output stream object and write data to the output stream, as follows:

    // The data to send
    String connect = "I'm a POST request data.";

    // Since this is a POST request, the parameters should be placed in
    // inside the HTTP body, so it needs to be set to true, false by default;
    connection.setDoOutput(true);

    // Get the output stream from the connection
    OutputStream os = connection.getOutputStream();
    // Write data to the output stream
    os.write(connect.getBytes(StandardCharsets.UTF_8));
    // Flush and close the output stream
    os.flush();
    os.close();
Copy the code

Note:

Connection.setdooutput (true) must be called to write data. Method with an argument of true and needs to be called before the getOutputStream() method is called.

2. The written data is only written to the buffer, without actually sending the data to the resource side.

A GET request

The parameters of an Http GET request are concatenated after the URL. Therefore, when sending a GET request, concatenate the parameters after the connection is created.

It is important to note, however, that if the getOutputStream() method is also called in a GET request, the request is automatically changed to a POST request. The source code is as follows:

// Methods in HttpURLConnection,
private synchronized OutputStream getOutputStream0(a) throws IOException {
        try {
            if (!this.doOutput) {
               
            } else {
                // If the method is set to GET, change to POST
                if (this.method.equals("GET")) {
                    this.method = "POST"; }}}catch(Exception e){
            
        }
}

Copy the code

6. Response data

Request the results

Generally, you need to know the request status in HTTP requests. You can obtain the request status in the following ways in HttpURLConnection

200: successful, 404: resource not found, etc
int responseCode = connection.getResponseCode();

// Get the request description
String msg = connection.getResponseMessage();

Copy the code

Get header information

The response header can be obtained in the following ways:

// get all the response headers
 Map<String, List<String>> headerFields = connection.getHeaderFields();

// 2. Obtain the response header information based on the header name
String connectionHeader =  connection.getHeaderField("Connection");

// 3. Obtain the response header information based on the header index. The subscript must be greater than 0.
String secHeader = connection.getHeaderField(2);

Copy the code

Read the data

It is also easy to get the response data from the getInputStream() method in HttpURLConnection, and then from the input stream, as shown below:

	// Get the input stream
	InputStream inputStream = connection.getInputStream();
	// Define a temporary byte output stream
	ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
        // Start reading data
        byte[] buffer = new byte[256];
        int len = 0;
        while ((len = inputStream.read(buffer)) > 0){
            baos.write(buffer,0, len);
        }
        return new String(baos.toByteArray(), StandardCharsets.UTF_8);
    } finally {
        // Close the input and output streams
        inputStream.close();
        baos.close();
    }
Copy the code

7. Upload and download

upload

Uploading a file to a normal Web page is easy, just add encType =”multipart/form-data” to the FROM tag, and the rest is up to the browser to collect the sending data and send the Http request.

However, with HttpURLConnection out of the browser, it’s up to us to do the data collection and send the request ourselves. So let’s first look at how the browser collects upload data and sends requests.

Let’s look at the format of the request body:

// The content-type attribute in the request header defines the attribute splitter
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryfdRf0g4cPSTVeLkJ

// Request data body information
------WebKitFormBoundaryfdRf0g4cPSTVeLkJ
Content-Disposition: form-data; name="images"; filename="20150703212056_Yxi4L.jpeg"
Content-Type: image/jpeg


------WebKitFormBoundaryfdRf0g4cPSTVeLkJ
Content-Disposition: form-data; name="checkRecord"

{"describe":""."rectify":"Fix it now"}
------WebKitFormBoundaryfdRf0g4cPSTVeLkJ--
Copy the code

Analyzing the above data, we can find the following rules:

  1. The first line in the data body——WebKitFormBoundaryfdRf0g4cPSTVeLkJAs a separator, followed by\r\nCarriage return line feed character.
  2. The second lineContent-Disposition: form-data; name="images"; filename="*****"Is the form data field, where name indicates the interface attribute value and filename indicates the filename.
  3. The third lineContent-Type: image/jpegIndicates the type of the uploaded file.
  4. The fourth line is a carriage return newline character.
  5. The fifth line is the data content, which is not displayed because it is a picture.
  6. The rest follows the same pattern.
  7. The last line is the closing line. Notice the two more--.

According to the above rules, when uploading using HttpURLConnection, we can join the sent data flow according to this rule. Here is an example:

public void upload(File file) throws Exception {
    final URL url = new URL("http://localhost:10010/user/upload");

    // Get the URL link
    URLConnection urlConnection =  url.openConnection();
    // Because the URL is a subclass of the URLConnection class generated based on the protocol in the URL (HTTP in this case)
    // HttpURLConnection. Therefore, convert this to an HttpURLConnection subclass for convenience
    // More apis in
    HttpURLConnection connection = (HttpURLConnection)urlConnection;

    // Customize the splitter line and set the request header
    String boundary = "-- -- -- -- -- -- -- -- -- -- -- --" + System.currentTimeMillis();

    connection.setRequestProperty("Content-Type"."multipart/form-data; boundary=" + boundary);
    // Set the request to POST
    connection.setRequestMethod(METHOD.POST.name());
    // Open the output stream
    connection.setDoOutput(true);
    // Get the type of file to upload
    MagicMatch magicMatch = Magic.getMagicMatch(file, false.true);
    String mimeType = magicMatch.getMimeType();

    // Get the output stream
    OutputStream outputStream = connection.getOutputStream();

    // Concatenate request data
    StringBuilder builder = new StringBuilder();
    // The first line splits the row
    builder.append("\r\n").append("--" + BOUNDARY).append( "\r\n");
    // The second line forms the data
    builder.append("Content-Disposition: form-data; name=\"file\"; filename=\"").append(file.getName() ).append("\"\r\n");
    // The third line uploads the data type
    builder.append( "Content-Type:").append(mimeType).append("\r\n");
    The fourth line is a blank line
    builder.append("\r\n");
    outputStream.write(builder.toString().getBytes(StandardCharsets.UTF_8));
    // Start writing file data
    InputStream fileInput = new FileInputStream(file);
    byte[] buffer = new byte[512];
    int len = 0;
    while ((len = fileInput.read(buffer)) > 0){
        outputStream.write(buffer, 0, len);
    }


    // Start writing basic data
    StringBuilder textBuffer = new StringBuilder();
    // Separate the lines
    textBuffer.append("\r\n").append("--" + BOUNDARY).append("\r\n");
    // form data
    textBuffer.append("Content-Disposition: form-data; name=\"name\"\r\n");
    // a blank line
    textBuffer.append("\r\n");
    / / data values
    textBuffer.append("Zhang");
    outputStream.write(textBuffer.toString().getBytes(StandardCharsets.UTF_8));

    // Write the closing line
    outputStream.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes(StandardCharsets.UTF_8));
    outputStream.flush();
    outputStream.close();
    fileInput.close();
    int responseCode = connection.getResponseCode();
    printHeaders(connection.getHeaderFields());
    if(responseCode ! =200){
        LOGGER.error("Request failed, code: {}, message: {}", responseCode, connection.getResponseMessage());
    }else {
        InputStream inputStream = connection.getInputStream();
        String reader = reader(inputStream);
        LOGGER.info("The server returns: \n {}", reader); }}Copy the code

Note:

The base data is missing content-Type: image/ JPEG lines than file

download

File download is relatively simple, get the input stream, and then read the input stream, and read the data to the local can be, the following is to download the network picture for example.

/** * download *@paramUrl Download file path *@paramDistDir Path to the saved file */
   public void download(String url, String distDir) throws Exception {
       // Get the connection
       HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();

       // Set the request method
       connection.setRequestMethod("GET");
       connection.setRequestProperty("Charset"."UTF-8");

       // Get the file name
       String fileUrl = connection.getURL().getFile();
       String fileName = fileUrl.substring(fileUrl.lastIndexOf(File.separatorChar) + 1);

       LOGGER.info("Filename: {} -- {}", fileName,  File.separator);
       String filePath = distDir + File.separatorChar + fileName;
       File file = new File(filePath);
       if(! file.getParentFile().exists()){ file.getParentFile().mkdirs(); }// Get the input stream and write to the file
       try (InputStream inputStream = connection.getInputStream();
            OutputStream os = new FileOutputStream(file)) {
           byte[] buffer = new byte[256];
           int len = 0;
           while ((len = inputStream.read(buffer)) > 0) {
               os.write(buffer, 0, len); } os.flush(); }}Copy the code

Nine,

  1. throughURLOf the classopenConnection()Method to get the request connection
  2. Call if data needs to be writtensetDoOutput(true)Turn on the output stream
  3. In the callconnection(),getOutputStream(),getInputStream()Method before setting the request parameters.
  4. If the callgetOutputStream()Method, changes the request method toPOST
  5. Establish connections and callsgetOutputStream()After the method writes data and closes the connection, it does not send data, only callsgetInputStream()Before you actually send the data.
  6. When uploading data using HttpURLConnection, you need to manually join the data format as the browser does