[英]Filter object only when predicate input is not the empty string using 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.