杰瑞科技汇

Java中如何处理querystring参数?

Of course! Let's dive deep into querystring in Java.

First, a crucial point: Unlike Node.js, which has a built-in querystring module, Java does not have a standard library class named QueryString. Instead, Java handles URL query strings using its core java.net package, primarily with the URI and URL classes.

Here’s a complete guide on how to parse, build, and manipulate query strings in Java.


Parsing a Query String (The Most Common Task)

The best way to parse a query string is to use the java.net.URI class. It's robust, handles encoding/decoding correctly, and is part of the standard Java SE.

Using java.net.URI (Recommended)

This is the standard and safest approach.

Example URL: https://www.example.com/search?q=java+programming&page=2&sort=desc

Goal: Extract the parameters (q, page, sort).

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
public class QueryStringParser {
    public static void main(String[] args) {
        String urlString = "https://www.example.com/search?q=java+programming&page=2&sort=desc&user=tom%40gmail.com";
        try {
            // 1. Create a URI object
            URI uri = new URI(urlString);
            // 2. Get the query string (the part after the '?')
            String query = uri.getQuery();
            System.out.println("Raw Query String: " + query); // q=java+programming&page=2&sort=desc&user=tom%40gmail.com
            // 3. Parse the query string into a Map<String, String>
            // We use a simple split for demonstration. For production, consider a library.
            Map<String, String> params = parseQueryString(query);
            // 4. Access the parameters
            String searchQuery = params.get("q");
            int pageNumber = Integer.parseInt(params.get("page"));
            String sortMethod = params.get("sort");
            String userEmail = params.get("user");
            System.out.println("\nParsed Parameters:");
            System.out.println("Search Query: " + searchQuery); // java programming (plus signs are decoded to spaces)
            System.out.println("Page Number: " + pageNumber);   // 2
            System.out.println("Sort Method: " + sortMethod);   // desc
            System.out.println("User Email: " + userEmail);     // tom@gmail.com (percent-encoding is decoded)
        } catch (URISyntaxException e) {
            System.err.println("Invalid URL: " + e.getMessage());
        }
    }
    /**
     * A simple method to parse a query string into a Map.
     * Note: This is a basic implementation. It doesn't handle multiple values for the same key.
     * For a more robust solution, see the "Using a Library" section below.
     */
    public static Map<String, String> parseQueryString(String query) {
        if (query == null || query.isEmpty()) {
            return Map.of(); // Return an empty immutable map
        }
        // Split by '&' to get key-value pairs
        return Arrays.stream(query.split("&"))
                .map(pair -> pair.split("=", 2)) // Split by '=' into max 2 parts
                .collect(Collectors.toMap(
                        arr -> URLDecoder.decode(arr[0], StandardCharsets.UTF_8), // Decode key
                        arr -> arr.length > 1 ? URLDecoder.decode(arr[1], StandardCharsets.UTF_8) : "" // Decode value
                ));
    }
}

Key Points:

  • URI.getQuery(): This method correctly extracts only the query part (e.g., q=java...).
  • URLDecoder.decode(): This is essential. It correctly handles URL-encoded characters like %40 (which becomes ) and (which becomes a space). Failing to decode this will lead to bugs.
  • Simple vs. Complex Values: The simple split() method works well for most cases where each key has a single value.

Building a Query String

Building a query string manually is error-prone. You must remember to encode special characters (&, , , space, etc.). The best practice is to build a Map of parameters and then format it.

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
public class QueryStringBuilder {
    public static void main(String[] args) {
        // 1. Create a map of your parameters
        Map<String, String> params = new HashMap<>();
        params.put("q", "java & spring");
        params.put("page", "1");
        params.put("sort", "date");
        params.put("lang", "en-US"); // Special characters like '-' are fine, but spaces are not
        // 2. Build the query string
        String queryString = buildQueryString(params);
        // The result will be: q=java+%26+spring&page=1&sort=date&lang=en-US
        System.out.println("Constructed Query String: " + queryString);
    }
    public static String buildQueryString(Map<String, String> params) {
        if (params == null || params.isEmpty()) {
            return "";
        }
        StringBuilder queryStringBuilder = new StringBuilder();
        params.forEach((key, value) -> {
            try {
                // Encode both key and value to handle special characters
                String encodedKey = URLEncoder.encode(key, StandardCharsets.UTF_8.name());
                String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.name());
                if (queryStringBuilder.length() > 0) {
                    queryStringBuilder.append("&");
                }
                queryStringBuilder.append(encodedKey).append("=").append(encodedValue);
            } catch (UnsupportedEncodingException e) {
                // StandardCharsets.UTF_8 is guaranteed to be supported, so this is safe.
                throw new RuntimeException("Failed to encode parameter", e);
            }
        });
        return queryStringBuilder.toString();
    }
}

Key Points:

  • URLEncoder.encode(): This is the counterpart to URLDecoder. It converts spaces to and special characters like & and into their percent-encoded form (%26, %3D).
  • StandardCharsets.UTF_8: Always specify the character encoding. UTF-8 is the standard for the web.

Handling Multiple Values for the Same Key

A query string can have the same key multiple times (e.g., colors=red&colors=blue). The Map approach from above will not work, as a map cannot hold duplicate keys.

In this case, you should parse the query string into a Map<String, List<String>>.

Parsing Multiple Values

import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
public class MultiValueQueryParser {
    public static void main(String[] args) throws URISyntaxException {
        String urlString = "https://example.com/filter?colors=red&colors=blue&size=large&colors=green";
        URI uri = new URI(urlString);
        String query = uri.getQuery();
        // Parse into a Map<String, List<String>>
        Map<String, List<String>> params = parseMultiValueQueryString(query);
        System.out.println("Parsed Multi-Value Parameters:");
        params.forEach((key, values) -> {
            System.out.println(key + " -> " + values);
        });
        // Accessing a specific list of values
        List<String> colors = params.get("colors");
        if (colors != null) {
            System.out.println("\nFirst color: " + colors.get(0)); // red
        }
    }
    public static Map<String, List<String>> parseMultiValueQueryString(String query) {
        if (query == null || query.isEmpty()) {
            return Collections.emptyMap();
        }
        return Arrays.stream(query.split("&"))
                .map(pair -> pair.split("=", 2))
                .collect(Collectors.groupingBy(
                        arr -> URLDecoder.decode(arr[0], StandardCharsets.UTF_8),
                        Collectors.mapping(
                                arr -> arr.length > 1 ? URLDecoder.decode(arr[1], StandardCharsets.UTF_8) : "",
                                Collectors.toList()
                        )
                ));
    }
}

Using a Third-Party Library (Recommended for Production)

While the standard library is good, a dedicated library can simplify your code significantly, handle edge cases, and provide a more fluent API. The most popular choice is Apache HttpClient.

Add the Dependency (Maven)

<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.3.1</version> <!-- Use the latest version -->
</dependency>

Parsing with URIBuilder

URIBuilder is an incredibly useful class that handles both parsing and building.

import org.apache.hc.client5.http.utils.URIBuilder;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
public class UriBuilderExample {
    public static void main(String[] args) throws URISyntaxException {
        // --- PARSING ---
        String urlString = "https://www.example.com/search?q=java+programming&page=2&colors=red&colors=blue";
        // The URIBuilder can parse a string directly
        URIBuilder uriBuilder = new URIBuilder(urlString);
        System.out.println("Host: " + uriBuilder.getHost());
        System.out.println("Path: " + uriBuilder.getPath());
        // Get a single parameter
        String searchQuery = uriBuilder.getQueryParams("q").get(0).getValue();
        System.out.println("Search Query: " + searchQuery); // java programming
        // Get all values for a multi-valued parameter
        List<String> colors = uriBuilder.getQueryParams("colors").stream()
                                       .map(param -> param.getValue())
                                       .toList();
        System.out.println("Colors: " + colors); // [red, blue]
        // --- BUILDING ---
        System.out.println("\n--- Building a new URL ---");
        URIBuilder newBuilder = new URIBuilder("https://api.example.com/data");
        newBuilder.addParameter("id", "123");
        newBuilder.addParameter("format", "json");
        newBuilder.addParameter("tags", "java,http");
        // Note: URIBuilder automatically adds '&' for you
        URI newUri = newBuilder.build();
        System.out.println("Constructed URL: " + newUri.toString());
        // Output: https://api.example.com/data?id=123&format=json&tags=java%2Chttp
    }
}

Why use a library like URIBuilder?

  • Robustness: Handles complex URL edge cases correctly.
  • Fluent API: The addParameter() method is very readable.
  • Automatic Encoding: You provide raw values, and the builder handles the encoding.
  • Multi-value Support: It's built-in and easy to use.
  • Easy Modification: It's trivial to add, remove, or change parameters on an existing URI.

Summary: Which Method to Use?

Scenario Recommended Approach
Simple Parsing (single value per key) URI.getQuery() + manual split() and URLDecoder.decode().
Simple Building (single value per key) Manual StringBuilder + URLEncoder.encode().
Multi-value Parameters URI.getQuery() + parse into Map<String, List<String>> with URLDecoder.
Production / Complex Applications Apache URIBuilder. It's the most robust, readable, and maintainable solution.
分享:
扫描分享到社交APP
上一篇
下一篇