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

とてもシンプルです。では、各キャプチャ グループを調べて、一致するかどうかを確認する方法はありますか? リクエストに GET ではなく POST があったとします。最初のキャプチャ グループを確認してから、501 の「実装されていません」という応答を返すことは可能ですか?

私の最初の解決策は、単純にメッセージを空白で分割し、個々の配列要素をチェックすることでした。しかし、それは少し「悪い」ようです。

編集:

問題は、matches() が全体に一致し、1 つのグループが失敗すると、式全体が失敗することです。これは望ましくありません。IllegalStateException をスローすることなく、任意の数のグループが失敗/成功する可能性があります。

4

2 に答える 2

1

特定のグループが一致しない場合でも一致するには、それらをオプションにする必要があります。

次に、このMatcher#find()メソッドを使用しMatcher#group(x)てグループにアクセスします (0 は完全な一致であるため、1 から開始します)。

例:

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
}

(/.*)補足として、2 番目のグループは最初のスラッシュの後の任意のものに貪欲に一致するため、表現を少し調整する必要がありました。とはいえ、まだ完璧にはほど遠いです。



2 番目のアプローチは、複数の式/パターンを適用し、それらをマッチャーに次々と適用することです。

例:

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 (およびその他のメソッド) の両方に一致するようにパターンを調整する必要があります。このように関連する文字列を取得したら、(別の) パターンに再度一致させるか、さまざまな条件付き構造の 1 つでそれを使用できます... (最近ではswitchステートメントも機能しStringます (Java 7))。

別の戦略は、区切り文字を一致させ、任意の文字列を HTTP メソッドとして許可することです (ガベージも)。その後、実際のグループ値を確認します。

さらに別の戦略は、個別に処理したいエラー条件ごとに個別のパターンを用意し、どのパターンが一致するかを確認することです (一致する場合は、エラーを適切に処理します)。ただし、見逃す条件がよくあるため、考えられるすべてのエラーが処理されるわけではありません。あなたは本当に自分が何をしているのかを知る必要があります...

ただし、Java には多くのネットワーク ライブラリ コードが用意されているため、この種の正規表現チェックを行う必要はありません。たとえば、javax.servlet.http.HttpServletRequest#getMethod()...を参照してください。

于 2013-03-07T14:02:12.873 に答える