我有一个构造了表达式的HTTP请求。到目前为止,表达式仍然有效,我可以将请求拆分为字符串数组,但是我想看看是否可以通过匹配单个捕获组来简化它。
所以:
private void process(final String message) {
Pattern pattern = Pattern.compile("(GET|get){1}\\s(/.*)\\s(HTTP|http)(/1\\.0)");
Matcher matcher = pattern.matcher(message);
}
请求是这样的:
GET / HTTP/1.0
很简单。因此,有什么方法可以遍历每个捕获组以检查是否存在匹配项?假设请求使用POST而不是GET,是否可以检查第一个捕获组,然后返回501“未实现”响应?
我的第一个解决方案是简单地按空格分割消息,然后检查每个单独的数组元素。但这似乎有点“不好”。
编辑:
问题是,matches()匹配整个对象,如果一组失败,那么整个表达式就会失败,这是我不希望的。任何数量的组都应该可以失败/成功,而不会引发IllegalStateException。
最佳答案
为了即使某些组不匹配也要匹配,它们必须是可选的。
然后使用Matcher#find()
方法和Matcher#group(x)
来访问组(从1开始,因为0是整个匹配项)。
例:
String msg = "GET HTTP 200 OK"; //resource and protocol version are left out by purpose
Pattern pattern = Pattern.compile("(GET|get)?\\s(/[^\\s]*)?\\s(HTTP|http)?(/1\\.0)?");
Matcher matcher = pattern.matcher( msg );
while ( matcher.find() )
{
System.out.println(matcher.group( 1 )); //prints GET
System.out.println(matcher.group( 2 )); //prints null since there's no resource
System.out.println(matcher.group( 3 )); //prints HTTP
System.out.println(matcher.group( 4 )); //prints null since there's no version string
}
附带说明一下,我需要稍微调整一下您的表情,因为第二组
(/.*)
会在第一个斜杠之后贪婪地匹配任何内容。但是,它仍然远非完美。第二种方法可能是应用多个表达式/模式,并将它们一个接一个地应用于匹配器。
例:
Pattern methodPattern = Pattern.compile("GET|get");
Matcher matcher = methodPattern.matcher( msg );
if ( matcher.find() )
{
System.out.println("method: " + matcher.group());
}
if ( matcher.usePattern( Pattern.compile("\\s/([^\\s]*)") ).find() )
{
System.out.println("resource: " + matcher.group(1));
}
if ( matcher.usePattern( Pattern.compile("HTTP|http") ).find() )
{
System.out.println("protocol: " + matcher.group());
}
if ( matcher.usePattern( Pattern.compile("/(\\d\\.\\d)") ).find() )
{
System.out.println("version: " + matcher.group(1));
}
这利用了将匹配器的读取位置设置为匹配后的位置的事实,随后对
find()
的任何调用都将从该位置开始。如果模式不匹配,则位置保持不变。因此,必须按顺序应用这些模式,但这些模式是可选的。