2010-11-08 17 views
17

Czy ktoś ma lub zna klasę Java, której można użyć do manipulowania ciągami zapytania?Sterowanie ciągami kwerend w języku Java

Zasadniczo chciałbym klasy, która może po prostu podać ciąg kwerendy do, a następnie usuwać, dodawać i modyfikować ciąg kwerendy KVP.

Z góry dziękuję.

EDIT

W odpowiedzi na komentarz dokonane na to pytanie, ciąg kwerendy będzie wyglądać następująco;

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

Chciałbym przekazać tej klasie ciąg zapytania i powiedzieć coś takiego;

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

a następnie może

queryStringClass.setParameter("N", N); 

a może queryStringClass.removeParameter("N");

Albo coś w tym rodzaju.

+3

Nie podano wystarczającego kontekstu, aby ktokolwiek mógł udzielić odpowiedzi. Jakie rodzaje ciągów zapytań? Proszę ponownie sformułować pytanie. –

+1

http://stackoverflow.com/questions/1667278/parsing-query-strings-in-java –

Odpowiedz

16

coś takiego

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; 
} 

iteracyjne mapę prosto:

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)); 
} 
+0

Chciałbym mieć coś z góry zbudowanego, ale to jest świetne. :) dziękuję – griegs

+1

Byłoby bardziej wydajne przechowywanie 'param.split (" = ")' w zmiennej i ponowne użycie wyniku, w przeciwieństwie do dwukrotnego dzielenia tego samego paramu. – LeastOne

+7

To rozwiązanie nie uwzględnia znaków zbiegów. – raulk

0

Można utworzyć metodę util i używać wyrażeń regularnych, aby je przeanalizować. Wzór taki jak "[; &]" powinien wystarczyć.

5

Jeśli używasz J2EE, możesz użyć ServletRequest.getParameterValues().

W przeciwnym razie nie wydaje mi się, aby Java posiadała jakiekolwiek wspólne klasy do obsługi ciągów znaków zapytania. Pisanie własne nie powinno być zbyt trudne, choć istnieją pewne trudne przypadki krawędzi, takie jak zrozumienie, że technicznie ten sam klucz może pojawić się więcej niż jeden raz w ciągu zapytania.

Jedna realizacja może wyglądać następująco:

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")); 
} 
} 
+0

+1, dziękuję za to. Już zaimplementowałeś coś takiego. – griegs

+0

Jak pracować z "&" w środku ciągów zapytania? – Achimnol

+0

@Achimnol: W czym problem? & jest kodowaniem XML, powinien przechodzić przez parametr adresu URL jako% 26amp ;. Jeśli chcesz dalej dekodować ciąg znaków XML, możesz użyć innych metod. – Avi

12

Można również użyć Splitter Google guawy jest.

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

drukuje się

89 

To moim zdaniem jest bardzo czytelna alternatywa do analizowania go samodzielnie.

Edytuj: Jak zauważyła firma @raulk, to rozwiązanie nie uwzględnia znaków zbiegów. Jednak może to nie być problemem, ponieważ przed dekodowaniem adresu URL ciąg znaków zapytania nie zawiera znaków zbiegających, które kolidują z "=" i "&". Możesz użyć tego na swoją korzyść w następujący sposób.

Powiedzmy, że trzeba zdekodować następujący ciąg kwerendy:

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

który jest zakodowany w adresie URL, wtedy masz gwarancję, że „&” i „=” są wykorzystywane do rozdzielania pary i klucz od wartości, odpowiednio, w którym momencie można użyć, aby uzyskać splitter Guava:

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

po uzyskaniu par klucz-wartość, a następnie można je zdekodować URL oddzielnie.

a = &#%!)#(@! 
b = #$(@)[email protected]@))$#^*& 

Powinno to obejmować wszystkie przypadki.

+6

To rozwiązanie nie uwzględnia znaków ewakuowanych. – raulk

+0

Masz rację. –

+0

@raulk Dodałem kilka kroków, które można wykorzystać nawet w przypadku znaków zbiegów. Dzięki! –

1

Innym sposobem jest użycie komponentów HTTP apache. Jest to nieco hacky, ale przynajmniej wykorzystać wszystkie analizowania przypadków narożne:

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

To da ci listę obiektów NameValuePair że powinien być łatwy w użyciu.

+0

Znalazłem dziwne, że nie zostało to już zaproponowane ... to jest hacky, ale dobre wykorzystanie istniejącej biblioteki ... – AxelH