我有一个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。
答案 0 :(得分: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()
的任何调用都将从那里开始。如果模式不匹配,则位置保持不变。
因此,必须按顺序应用模式,但这些模式是可选的。
答案 1 :(得分:0)
您知道在执行matches()
后,Matcher
还允许您使用group()
方法提取特定组的匹配内容吗?但是,您需要调整模式以匹配GET和POST(以及其他任何方法)。一旦你检索到这样的相关字符串,你就可以再次匹配它上面的(nother)模式,或者在各种条件结构之一中使用它......(switch
语句现在也适用于String
( Java 7)。)
另一种策略是匹配分隔符,并允许任何字符串作为HTTP方法(甚至是垃圾)。然后检查实际的组值。
另一种策略是为每个要分别处理的错误条件设置一个单独的模式,然后查看哪个模式匹配(如果匹配,则适当地处理错误)。但是,通常存在一个未命中的情况,因此并非所有可以想到的错误都得到处理。你真的需要知道你在做什么......
但是,Java确实提供了许多网络库代码,因此您无需进行此类regexp检查。例如,请参阅javax.servlet.http.HttpServletRequest#getMethod()
...