【问题标题】:Query String Manipulation in JavaJava中的查询字符串操作
【发布时间】:2011-05-06 22:03:51
【问题描述】:

是否有人拥有或知道我可以用来操作查询字符串的 java 类?

基本上我想要一个类,我可以简单地给一个查询字符串,然后删除、添加和修改查询字符串 KVP。

提前致谢。

编辑

响应对此问题的评论,查询字符串将如下所示;

N=123+456+112&Ntt=koala&D=abc

所以我想将查询字符串传递给这个类,然后说类似;

String[] N = queryStringClass.getParameter("N");

然后也许

queryStringClass.setParameter("N", N);

也许queryStringClass.removeParameter("N");

或者类似的东西。

【问题讨论】:

标签: java string


【解决方案1】:

类似的东西

 public static Map<String, String> getQueryMap(String query)  
 {  
     String[] params = query.split("&");  
     Map<String, String> map = new HashMap<String, String>();  
     for (String param : params)  
     {  
         String name = param.split("=")[0];  
         String value = param.split("=")[1];  
         map.put(name, value);  
     }  
     return map;  
 }  

简单地迭代地图:

 String query = url.getQuery();  
 Map<String, String> map = getQueryMap(query);  
 Set<String> keys = map.keySet();  
 for (String key : keys)  
 {  
    System.out.println("Name=" + key);  
    System.out.println("Value=" + map.get(key));  
 }  

【讨论】:

  • 希望有一些预先构建的东西,但这很棒。 :) 谢谢你
  • param.split("=") 存储在变量中并重用结果比将相同的参数拆分两次更有效。
  • 此解决方案不考虑转义字符。
  • 这个解决方案也没有考虑到数组。
【解决方案2】:

您可以创建一个 util 方法并使用正则表达式对其进行解析。像“[;&]”这样的模式就足够了。

【讨论】:

    【解决方案3】:

    如果您使用的是 J2EE,则可以使用ServletRequest.getParameterValues()

    否则,我认为 Java 没有任何用于查询字符串处理的通用类。编写自己的代码应该不会太难,尽管存在某些棘手的边缘情况,例如意识到技术上相同的键可能在查询字符串中出现多次。

    一个实现可能如下所示:

    import java.util.*;
    import java.net.URLEncoder;
    import java.net.URLDecoder;
    
    public class QueryParams {
    private static class KVP {
        final String key;
        final String value;
        KVP (String key, String value) {
            this.key = key;
            this.value = value;
        }
    }
    
    List<KVP> query = new ArrayList<KVP>();
    
    public QueryParams(String queryString) {
        parse(queryString);
    }
    
    public QueryParams() {
    }
    
    public void addParam(String key, String value) {
        if (key == null || value == null)
            throw new NullPointerException("null parameter key or value");
        query.add(new KVP(key, value));
    }
    
    private void parse(String queryString) {
        for (String pair : queryString.split("&")) {
            int eq = pair.indexOf("=");
            if (eq < 0) {
                // key with no value
                addParam(URLDecoder.decode(pair), "");
            } else {
                // key=value
                String key = URLDecoder.decode(pair.substring(0, eq));
                String value = URLDecoder.decode(pair.substring(eq + 1));
                query.add(new KVP(key, value));
            }
        }
    }
    
    public String toQueryString() {
        StringBuilder sb = new StringBuilder();
        for (KVP kvp : query) {
            if (sb.length() > 0) {
                sb.append('&');
            }
            sb.append(URLEncoder.encode(kvp.key));
            if (!kvp.value.equals("")) {
                sb.append('=');
                sb.append(URLEncoder.encode(kvp.value));
            }
        }
        return sb.toString();
    }
    
    public String getParameter(String key) {
        for (KVP kvp : query) {
            if (kvp.key.equals(key)) {
                return kvp.value;
            }
        }
        return null;
    }
    
    public List<String> getParameterValues(String key) {
        List<String> list = new LinkedList<String>();
        for (KVP kvp : query) {
            if (kvp.key.equals(key)) {
                list.add(kvp.value);
            }
        }
        return list;
    }
    
    public static void main(String[] args) {
        QueryParams qp = new QueryParams("k1=v1&k2&k3=v3&k1=v4&k1&k5=hello+%22world");
        System.out.println("getParameter:");
        String[] keys = new String[] { "k1", "k2", "k3", "k5" };
        for (String key : keys) {
            System.out.println(key + ": " + qp.getParameter(key));
        }
        System.out.println("getParameters(k1): " + qp.getParameterValues("k1"));
    }
    }
    

    【讨论】:

    • +1,谢谢。已经实现了类似的东西。
    • @Achimnol:有什么问题? &是 XML 编码,它应该通过一个 URL 参数作为 %26amp;。如果要进一步对字符串进行 XML 解码,可以使用其他方法。
    • 请注意,ServletRequest.getParameterValues() 无法处理编码:stackoverflow.com/questions/469874/…
    【解决方案4】:

    您也可以使用 Google Guava 的 Splitter。

    String queryString = "variableA=89&variableB=100";
    Map<String,String> queryParameters = Splitter
        .on("&")
        .withKeyValueSeparator("=")
        .split(queryString);
    System.out.println(queryParameters.get("variableA"));
    

    打印出来

    89
    

    我认为这是一个非常易读的替代方法。

    编辑:正如@raulk 指出的那样,此解决方案不考虑转义字符。但是,这可能不是问题,因为在 URL 解码之前,查询字符串保证没有任何与 '=' 和 '&' 冲突的转义字符。您可以通过以下方式利用这一点。

    假设您必须解码以下查询字符串:

    a=%26%23%25!)%23(%40!&b=%23%24(%40)%24%40%40))%24%23%5E*%26
    

    它是 URL 编码的,那么您可以保证 '&' 和 '=' 分别专门用于将 pair 和 key 从 value 中分离出来,此时您可以使用 Guava 拆分器来获取:

    a = %26%23%25!)%23(%40!
    b = %23%24(%40)%24%40%40))%24%23%5E*%26
    

    获得键值对后,就可以分别进行 URL 解码了。

    a = &#%!)#(@!
    b = #$(@)$@@))$#^*&
    

    这应该涵盖所有情况。

    【讨论】:

    • 此解决方案不考虑转义字符。
    • @raulk 我添加了一些步骤,即使是转义字符也可以使用。谢谢!
    【解决方案5】:

    另一种方法是使用 apache http-components。这有点 hacky,但至少你利用了所有的解析极端情况:

    List<NameValuePair> params = 
        URLEncodedUtils.parse("http://example.com/?" + queryString, Charset.forName("UTF-8"));
    

    这将为您提供应该易于使用的 NameValuePair 对象列表。

    【讨论】:

    • 我发现奇怪的是这还没有被提议......这很hacky但是对现有库的良好使用......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 2014-10-01
    • 1970-01-01
    相关资源
    最近更新 更多