获取此HTTP查询字符串:
foo=fooValue&bar=barValue&phleem=phleemValue
或者这个:
bar=barValue&phleem=phleemValue&foo=someOtherFoo
删除foo
参数的最佳方式是什么?
欢迎所有Java解决方案,但是Guava更喜欢。
(没有可用的ServletContext,因此Servlet方法无济于事)
更新:该方法应处理多个要删除的参数。
答案 0 :(得分:3)
这不是最优雅的解决方案,但可以按预期工作:
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);
}
<强>更新强>
处理多个参数:
@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);
}
};
}
答案 1 :(得分:1)
这是我自己的解决方案(但它很丑陋):
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));
}
答案 2 :(得分:1)
我想在一端读取查询字符串作为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
并且您甚至不愿意编写特殊方法为了它。
答案 3 :(得分:0)
你可以使用番石榴
public static String toQueryString(final Map<String, Object> queryParameters) {
return "?" + Joiner.on('&').withKeyValueSeparator("=").join(queryParameters);
}