コンテキストパスなしでリクエストURIを取得するにはどうすればよいですか?


127

メソッドrequest.getRequestURI()は、コンテキストパスとともにURIを返します。

たとえば、アプリケーションのベースURLがであるhttp://localhost:8080/myapp/(つまり、コンテキストパスがmyappである)場合、を呼び出すrequest.getRequestURI()http://localhost:8080/myapp/secure/users、が返され/myapp/secure/usersます。

この部分/secure/users、つまりコンテキストパスのないURI のみを取得する方法はありますか?


回答:


158

プレフィックスパターンにマッピングされたフロントコントローラーサーブレット内にいる場合は、を使用できますHttpServletRequest#getPathInfo()

String pathInfo = request.getPathInfo();
// ...

例のサーブレットがにマッピングされていると仮定すると、/secureこれは/users典型的なフロントコントローラーサーブレット内の唯一の情報となる情報を返します。

ただし、サーブレットがサフィックスパターンにマッピングされている場合(ただし、URLの例ではこれが当てはまらないことが示されています)、または実際にフィルター内にいる場合(呼び出されるサーブレットがまだ決定されていない場合)。getPathInfo())を返す可能性がありnullます。次に、通常のString方法を使用して、コンテキストパスの長さに基づいてリクエストURIを自分でサブストリング化するのが最善の策です。

HttpServletRequest request = (HttpServletRequest) req;
String path = request.getRequestURI().substring(request.getContextPath().length());
// ...

代わりにこれを使用する理由はありgetServletPath()ますか?フィルターを作成していgetPathInfo()ますがnull、がgetServletPath()返されることに気付きましたが、パスからコンテキストを差し引いたものを返します(リクエストディスパッチャーに渡すのに適しています)。
Jason C

@JasonC:回答どおりgetPathInfo()、フロントコントローラサーブレットがプレフィックスパターンにマッピングされていない場合はnullを返します。
BalusC 2017年

うん。つまり、getServletPathよりもgetPathInfoを好む理由はありますか?ここで他の多くの高得点の回答でもgetServletPathを使用していません。現在取り組んでいるサーブレットプロジェクトがあり、スキルを少し磨き上げようとしています。
Jason C

1
@JasonC:JSFやSpring MVCなどのサーブレットベースのMVCフレームワークがインストールされている場合、サーブレットパスは変更される可能性があります。次に、MVCフレームワークの内部パス(たとえばの/foo.xhtml代わりに/foo.jsf)を表し、実際のリクエストURI(エンドユーザーがブラウザーのアドレスバーに表示するもの)ではありません。そのような場合、元のサーブレットパスはキーを持つリクエスト属性として解決できますRequestDispatcher.FORWARD_SERVLET_PATH。いずれにせよ、質問は明示的に要求URIを要求するため(ブラウザーのアドレスバーの場合と同様)、回答はそれに基づいています。
BalusC 2017年

74
request.getRequestURI().substring(request.getContextPath().length())

驚くばかり!これはまさに私が探していたものです。
職人が

4
+1これは、getPathInfoがnullやその他の奇妙なものになる可能性があるため、getPathInfoよりも良い答えだと思います。さまざまなSpringコードがgetContextPathを実行し、getPathInfoの代わりに行ったようにURIから削除します。
アダム・ゲント

32

Springでできること:

String path = new UrlPathHelper().getPathWithinApplication(request);

1
もちろん、例えばクラスメンバー変数としてUrlPathHelperのインスタンスを保持することは理にかなっています...
James

実際のリクエストマッピングURLを取得するにはどうすればよいですか?ここに案内してください:stackoverflow.com/questions/60446807/...
Pra_A

14

getPathInfo()がnullを返す場合があります。ドキュメントHttpServletRequest

追加のパス情報がない場合、このメソッドはnullを返します。

Filterのコンテキストパスなしでファイルへのパスを取得する必要があり、getPathInfo()はnullを返します。だから私は別のメソッドを使用します:httpRequest.getServletPath()

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    String newPath = parsePathToFile(httpRequest.getServletPath());
    ...

}

8

Filter内でrequest.getPathInfo()を使用すると、常にnullを取得するようになります(少なくとも突堤がある場合)。

この簡潔な無効なバグ+応答は、私が思う問題を暗示しています:

https://issues.apache.org/bugzilla/show_bug.cgi?id=28323

サーブレットがリクエストを取得する前にフィルターが実行されるという事実に関連していると思います。コンテナのバグか、私が特定できなかった予期された動作の可能性があります。

ただし、contextPathを使用できるため、fforwsソリューションはフィルターでも機能します。手作業で行う必要はありませんが、実装が壊れているか、


5

これを行う方法は、リクエストURIからサーブレットコンテキストパスをリセットすることです。

String p = request.getRequestURI();
String cp = getServletContext().getContextPath();

if (p.startsWith(cp)) {
  String.err.println(p.substring(cp.length());
}

こちらをお読みください


-1

たとえば、splitメソッドを使用して '/ myapp'を削除できます。

string[] uris=request.getRequestURI().split("/");
string uri="/"+uri[1]+"/"+uris[2];

3
アプリケーションをrootとしてデプロイし、そのベースURLがlocalhost:8080になると、問題が発生します。この場合、request.getRequestURI()は "/ secure / user"を返し、splitメソッドはここで問題を引き起こします。コードはデプロイメントに依存すべきではありません。
職人が
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.