0

我有一个单独的 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。

4

2 回答 2

1

即使在某些组不需要时仍然匹配,它们需要是可选的。

然后使用该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()都将从那里开始。如果模式不匹配,则位置保持不变。

因此,这些模式必须按顺序应用,但是是可选的。

于 2013-03-07T13:56:40.910 回答
0

你知道做完之后matches()Matcher还可以用group()方法提取特定组的匹配内容吗?但是,您需要调整模式以匹配 GET 和 POST(以及任何其他方法)。像这样检索相关字符串后,您可以再次在其上匹配(另一个)模式,或在各种条件构造之一中使用它......(现在也可以使用switch语句String(Java 7)。)

另一种策略是匹配分隔符,并允许任何字符串作为 HTTP 方法(甚至是垃圾)。然后检查实际的组值。

还有一种策略是为您要单独处理的每个错误条件设置一个单独的模式,然后查看哪个模式匹配(如果匹配,则适当地处理错误)。但是,经常会出现遗漏的情况,因此并非所有可能的错误都得到处理。你真的需要知道你在做什么......

但是,Java 确实提供了很多网络库代码,因此您不需要进行这种类型的正则表达式检查。例如,参考javax.servlet.http.HttpServletRequest#getMethod()...

于 2013-03-07T14:02:12.873 回答