我有一个下面的方法,它对使用charset传递的值进行URL解码。
public String decodeValue(String value, Charset charset) {
if (!Strings.isNullOrEmpty(value)) {
try {
value = URLDecoder.decode(value, charset.name());
} catch (UnsupportedEncodingException ex) {
// log error
return null;
}
}
return value;
}
现在,如果第一次URLDecoder.decode
行抛出UnsupportedEncodingException
,那么我想对下面三行运行相同的value
:
value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
value = value.replaceAll("\\+", "%2B");
value = URLDecoder.decode(value, charset.name());
如果然后再次URLDecoder.decode
行抛出异常第二次,那么我将记录错误但仅第二次并返回空值,否则返回被解码的值。
最好和最优雅的方法是什么?
答案 0 :(得分:1)
最简单的方法是创建一个包含额外标志的函数签名的私有版本。
private String decodeValue(String value, Charset charset, boolean isFirstTime) {
if (!Strings.isNullOrEmpty(value)) {
try {
value = URLDecoder.decode(value, charset.name());
} catch (UnsupportedEncodingException ex) {
if (isFirstTime) {
value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
value = value.replaceAll("\\+", "%2B");
return decodeValue(value, charset.name(), false);
} else {
// log error
return null;
}
}
}
return value;
}
然后,第一次传递true
并在递归调用中传递false
。在函数内部,只有在传递true
时才执行接下来的三行。
公开版可以通过true
。
public String decodeValue(String value, Charset charset) {
decodeValue(value, charset, true);
}
答案 1 :(得分:1)
虽然它不是递归的,但你可以使用while循环和标志。
public String decode(String value, Charset charset) {
boolean first = true;
while(!Strings.isNullOrEmpty(value)) {
try {
return value = URLDecoder.decode(value, charset);
} catch (UnsupportedEncodingException e) {
if(first == false) {
// Log error.
return null;
}
value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25").replaceAll("\\+", "%2B");
}
first = false;
}
return value;
}
答案 2 :(得分:0)
你走了:
public String decode(String value, Charset charset) {
if (!Strings.isNullOrEmpty(value)) {
try {
value = URLDecoder.decode(value, charset.name());
} catch (UnsupportedEncodingException ex) {
try {
value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
value = value.replaceAll("\\+", "%2B");
value = URLDecoder.decode(value, charset.name());
} catch (UnsupportedEncodingException ex) {
// log error
return null;
}
}
}
return value;
}
希望这能解决你的问题。
答案 3 :(得分:0)
添加标记是一个选项。是的,这是更容易的;但是很多人认为简单地说 flags :不好的做法。
你只是尽量减少这些事情。
换句话说:如果你有一个方法,对于第一次和后续的调用应该表现出不同;考虑在那里创建两个方法。当然,你尽可能地避免代码重复,但除非它变得昂贵,你至少应该考虑避免这样的标志参数。
答案 4 :(得分:0)
这是没有额外标志,重复代码,递归和循环的版本:
public String decodeValue(final String value, Charset charset) throws UnsupportedEncodingException {
String result;
if (!Strings.isNullOrEmpty(value)) {
UnsupportedEncodingException[] lastException = new UnsupportedEncodingException[1];
result = Stream.<Function<String, String>>of(
Function.identity(),
s -> {
s = s.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
s = s.replaceAll("\\+", "%2B");
return s;
})
.map(f -> f.apply(value))
.map(appliedValue -> {
try {
return URLDecoder.decode(appliedValue, charset.name());
} catch (UnsupportedEncodingException e) {
lastException[0] = e;
return null;
}
})
.filter(Objects::nonNull)
.findFirst()
.orElseThrow(() -> lastException[0]);
}
return result;
}
这里我只使用2个函数:身份和函数进行字符串校正。然后我将这些函数应用于初始字符串并尝试解码。如果第一次尝试成功,则代码将不会应用校正功能,只返回正确的结果。如果解码器在值修正后抛出异常,则“findFirst”将找不到任何值。然后我们抛出最后一次捕获的异常。