如何将查询参数附加到现有 URL?

Posted

技术标签:

【中文标题】如何将查询参数附加到现有 URL?【英文标题】:How can I append a query parameter to an existing URL? 【发布时间】:2014-11-28 10:35:28 【问题描述】:

我想将键值对作为查询参数附加到现有 URL。虽然我可以通过检查 URL 是否存在查询部分或片段部分并通过跳过一堆 if 子句来执行附加来做到这一点,但我想知道如果通过 Apache 执行此操作是否有干净的方法公共库或类似的东西。

http://example.com 将是 http://example.com?name=John

http://example.com#fragment 将是 http://example.com?name=John#fragment

http://example.com?email=john.doe@email.com 将是 http://example.com?email=john.doe@email.com&name=John

http://example.com?email=john.doe@email.com#fragment 将是 http://example.com?email=john.doe@email.com&name=John#fragment

我之前已经多次运行过这个场景,我希望在不以任何方式破坏 URL 的情况下执行此操作。

【问题讨论】:

相关:A good library to do URL Query String manipulation in Java @Mridang Agarwalla 我的回答能解决你的问题吗?如果您需要更多信息,请告诉我。 What is the idiomatic way to compose a URL or URI in Java?的可能重复 【参考方案1】:

这可以通过使用java.net.URI 类来使用现有实例的部分构造一个新实例来完成,这应确保它符合 URI 语法。

查询部分将为空或现有字符串,因此您可以决定使用 & 附加另一个参数或开始一个新查询。

public class ***26177749 

    public static URI appendUri(String uri, String appendQuery) throws URISyntaxException 
        URI oldUri = new URI(uri);

        String newQuery = oldUri.getQuery();
        if (newQuery == null) 
            newQuery = appendQuery;
         else 
            newQuery += "&" + appendQuery;  
        

        return new URI(oldUri.getScheme(), oldUri.getAuthority(),
                oldUri.getPath(), newQuery, oldUri.getFragment());
    

    public static void main(String[] args) throws Exception 
        System.out.println(appendUri("http://example.com", "name=John"));
        System.out.println(appendUri("http://example.com#fragment", "name=John"));
        System.out.println(appendUri("http://example.com?email=john.doe@email.com", "name=John"));
        System.out.println(appendUri("http://example.com?email=john.doe@email.com#fragment", "name=John"));
    

较短的选择

public static URI appendUri(String uri, String appendQuery) throws URISyntaxException 
    URI oldUri = new URI(uri);
    return new URI(oldUri.getScheme(), oldUri.getAuthority(), oldUri.getPath(),
            oldUri.getQuery() == null ? appendQuery : oldUri.getQuery() + "&" + appendQuery, oldUri.getFragment());

输出

http://example.com?name=John
http://example.com?name=John#fragment
http://example.com?email=john.doe@email.com&name=John
http://example.com?email=john.doe@email.com&name=John#fragment

【讨论】:

@Charlie 正确的三元组会减少行数,但也可能会降低可读性 它也消除了一些变量,这意味着更少的复杂性。 @Charlie 我已经用三元添加了替代答案。 甚至更简单,不要费心拉出这些位,你真的只需要知道你是否应该使用 ?或者一个&,三元组会这样做:return uri + new URI(uri).getQuery() == null ? “?” : "&" + appendQuery; 这里假设appendQuery被正确转义,而不是像uri = appendUri(uri, "foo=" + bar)这样调用。我强烈希望使用具有不同 namevalue 参数的 API,然后在 inside appendQuery 完成转义【参考方案2】:

使用URI 类。

用您现有的String 创建一个新的URI 以将其“分解”为多个部分,并实例化另一个以组装修改后的 url:

URI u = new URI("http://example.com?email=john@email.com&name=John#fragment");

// Modify the query: append your new parameter
StringBuilder sb = new StringBuilder(u.getQuery() == null ? "" : u.getQuery());
if (sb.length() > 0)
    sb.append('&');
sb.append(URLEncoder.encode("paramName", "UTF-8"));
sb.append('=');
sb.append(URLEncoder.encode("paramValue", "UTF-8"));

// Build the new url with the modified query:
URI u2 = new URI(u.getScheme(), u.getAuthority(), u.getPath(),
    sb.toString(), u.getFragment());

【讨论】:

【参考方案3】:

有很多库可以帮助您构建 URI(不要重新发明***)。以下三个可以帮助您入门:


Java EE 7

import javax.ws.rs.core.UriBuilder;
...
return UriBuilder.fromUri(url).queryParam(key, value).build();

org.apache.httpcomponents:httpclient:4.5.2

import org.apache.http.client.utils.URIBuilder;
...
return new URIBuilder(url).addParameter(key, value).build();

org.springframework:spring-web:4.2.5.RELEASE

import org.springframework.web.util.UriComponentsBuilder;
...
return UriComponentsBuilder.fromUriString(url).queryParam(key, value).build().toUri();

另请参阅: GIST > URI Builder Tests

【讨论】:

【参考方案4】:

我建议改进 Adam 的答案,接受 HashMap 作为参数

/**
 * Append parameters to given url
 * @param url
 * @param parameters
 * @return new String url with given parameters
 * @throws URISyntaxException
 */
public static String appendToUrl(String url, HashMap<String, String> parameters) throws URISyntaxException

    URI uri = new URI(url);
    String query = uri.getQuery();

    StringBuilder builder = new StringBuilder();

    if (query != null)
        builder.append(query);

    for (Map.Entry<String, String> entry: parameters.entrySet())
    
        String keyValueParam = entry.getKey() + "=" + entry.getValue();
        if (!builder.toString().isEmpty())
            builder.append("&");

        builder.append(keyValueParam);
    

    URI newUri = new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), builder.toString(), uri.getFragment());
    return newUri.toString();

【讨论】:

警告:正确转义parameters 的所有组件。想象一下,我带来了像 foo&amp;bar=45... 这样的值【参考方案5】:

Kotlin & clean,因此您不必在代码审查之前进行重构:

private fun addQueryParameters(url: String?): String? 
        val uri = URI(url)

        val queryParams = StringBuilder(uri.query.orEmpty())
        if (queryParams.isNotEmpty())
            queryParams.append('&')

        queryParams.append(URLEncoder.encode("$QUERY_PARAM=$param", Xml.Encoding.UTF_8.name))
        return URI(uri.scheme, uri.authority, uri.path, queryParams.toString(), uri.fragment).toString()
    

【讨论】:

有点晚了,但无论如何。尽量不要对等号进行编码。否则客户理解键和值可能会有问题 为什么要对参数进行编码?它会抛出:'java.io.UnsupportedEncodingException: UTF_8'。【参考方案6】:

考虑到 tryp 的回答,对亚当的回答进行了更新。不必在循环中实例化字符串。

public static URI appendUri(String uri, Map<String, String> parameters) throws URISyntaxException 
    URI oldUri = new URI(uri);
    StringBuilder queries = new StringBuilder();

    for(Map.Entry<String, String> query: parameters.entrySet()) 
        queries.append( "&" + query.getKey()+"="+query.getValue());
    

    String newQuery = oldUri.getQuery();
    if (newQuery == null) 
        newQuery = queries.substring(1);
     else 
        newQuery += queries.toString();
    

    URI newUri = new URI(oldUri.getScheme(), oldUri.getAuthority(),
            oldUri.getPath(), newQuery, oldUri.getFragment());

    return newUri;

【讨论】:

【参考方案7】:

对于安卓,使用: https://developer.android.com/reference/android/net/Uri#buildUpon()

URI oldUri = new URI(uri);
Uri.Builder builder = oldUri.buildUpon();
 builder.appendQueryParameter("newParameter", "dummyvalue");
 Uri newUri =  builder.build();

【讨论】:

这正是我所期待的解决方案,谢谢

以上是关于如何将查询参数附加到现有 URL?的主要内容,如果未能解决你的问题,请参考以下文章

HTML Urls - 如何附加到现有 url

如何将参数附加到 KNP 分页器 url

如何将现有参数从报表传递到查询

PHP如何在页面加载之前将查询字符串附加到URL

javascript 将查询参数附加到URL

如何创建浏览器快捷方式以将参数附加到当前 URL,然后加载生成的 url?