簡體   English   中英

從查詢字符串中過濾參數(使用Guava?)

[英]Filter parameters from query String (using Guava?)

拿這個HTTP查詢字符串:

foo=fooValue&bar=barValue&phleem=phleemValue

或者這一個:

bar=barValue&phleem=phleemValue&foo=someOtherFoo

刪除foo參數的最佳方法是什么?

歡迎所有Java解決方案,但番石榴更喜歡。

(沒有ServletContext可用,因此Servlet方法無濟於事)

更新:該方法應處理要刪除的多個參數。

這不是最優雅的解決方案,但可以按預期工作:

private String removeParameter(String string, final String parameterName) {
    List<String> list = newArrayList(string.split("&"));

    Collection<String> filtered = Collections2.filter(list, new Predicate<String>() {
        public boolean apply(String s) {
            return !s.startsWith(parameterName + "=");
        }
    });

    return Joiner.on("&").join(filtered);
}

UPDATE

要處理多個參數:

@Test
public void removesMultipleParametersFromQuery() throws Exception {
    String result = removeParameters("foo=fooValue&zee=lalal&bar=barValue&phleem=phleemValue", "foo", "bar");
    assertThat(result, is("zee=lalal&phleem=phleemValue"));
}

private String removeParameters(String query, final String...parameterNames) {
    List<String> list = newArrayList(query.split("&"));
    return Joiner.on("&").join(filter(list, startsWithAnyOf(parameterNames)));
}

private Predicate<String> startsWithAnyOf(final String[] parameterNames) {
    return new Predicate<String>() {
        public boolean apply(String s) {
            return !Iterables.any(newArrayList(parameterNames), isPrefixOf(s));
        }
    };
}

private Predicate<String> isPrefixOf(final String string){
    return new Predicate<String>() {
        public boolean apply(String candidate) {
            return string.startsWith(candidate);
        }
    };
}

這是我自己的解決方案(但它很丑陋):

public static String removeParameters(final String queryString,
    final String... paramNames){
    Iterable<Predicate<CharSequence>> innerPredicates;
    if(paramNames.length == 0){
        innerPredicates = Collections.emptySet();
    } else{
        innerPredicates =
            Iterables.transform(
            Arrays.asList(paramNames),
                new Function<String, Predicate<CharSequence>>(){

                    @Override
                    public Predicate<CharSequence> apply(
                        final String input){

                        return Predicates.contains(
                            Pattern.compile("^"
                            + Pattern.quote(input) + "=")
                        );
                    }
                });
    }

    final Predicate<CharSequence> predicate =
        Predicates.not(Predicates.or(innerPredicates));
    return Joiner.on("&").join(
        Iterables.filter(Splitter.on('&').split(queryString), predicate));
}

我想在一端讀取查詢字符串作為Multimap<String, String> ,另一端讀取字符串格式的Multimap<String, String> 然后執行此操作就像為要從查詢字符串中刪除的每個參數調用removeAll(parameter)一樣簡單。 除了在你絕對需要的地方之外,不要將它作為原始String處理。

這是一些代碼:

private static final Splitter QUERY_SPLITTER = Splitter.on(CharMatcher.anyOf("&;"));
private static final Joiner QUERY_JOINER = Joiner.on('&');
private static final EntrySplitFunction ENTRY_SPLITTER = 
    new EntrySplitFunction(Splitter.on('='));
private static final EntryJoinFunction ENTRY_JOINER = 
    new EntryJoinFunction(Joiner.on('=').useForNull(""));

public static Multimap<String, String> parseQueryString(String queryString) {
  Multimap<String, String> result = HashMultimap.create();
  Iterable<String> entryStrings = QUERY_SPLITTER.split(queryString);
  for (Map.Entry<String, String> entry : transform(entryStrings, ENTRY_SPLITTER)) {
    result.put(entry.getKey(), entry.getValue());
  }
  return result;
}

public static String toQueryString(Multimap<String, String> multimap) {
  return QUERY_JOINER.join(transform(multimap.entries(), ENTRY_JOINER));
}

private static class EntrySplitFunction 
    implements Function<String, Map.Entry<String, String>> {
  private final Splitter keyValueSplitter;

  private EntrySplitFunction(Splitter keyValueSplitter) {
    this.keyValueSplitter = keyValueSplitter;
  }

  @Override public Map.Entry<String, String> apply(String input) {
    Iterator<String> keyAndValue = keyValueSplitter.split(input).iterator();
    return Maps.immutableEntry(keyAndValue.next(), keyAndValue.next());
  }
}

private static class EntryJoinFunction 
    implements Function<Map.Entry<String, String>, String> {
  private final Joiner keyValueJoiner;

  private EntryJoinFunction(Joiner keyValueJoiner) {
    this.keyValueJoiner = keyValueJoiner;
  }

  @Override public String apply(Map.Entry<String, String> input) {
    return keyValueJoiner.join(input.getKey(), input.getValue());
  }
}

有了這個,你需要做的就是實現你的方法:

public static String removeParameters(String queryString, String... parameters) {
  Multimap<String, String> query = parseQueryString(queryString);
  for (String parameter : parameters) {
    query.removeAll(parameter);
  }
  return toQueryString(query);
}

更好的是,假設您對查詢有任何其他操作,那么當您達到需要執行此操作的點時,您就已經擁有了Multimap ,您甚至無需為此編寫特殊方法。

你可以使用番石榴

public static String toQueryString(final Map<String, Object> queryParameters) {
        return "?" + Joiner.on('&').withKeyValueSeparator("=").join(queryParameters);
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM