Java ServletのHttpServletRequestWrapperとgetRequestURIの使い方を徹底解説!初心者でもわかるリクエストURLの取得方法
生徒
「JavaのServletで、ユーザーがアクセスしたページのURLを調べることはできますか?」
先生
「できますよ。JavaのServletでは、getRequestURIメソッドを使うと、ブラウザから要求されたURLのパス部分を取得できます。」
生徒
「HttpServletRequestWrapperというクラスでも、そのメソッドを使えるんですか?」
先生
「はい。HttpServletRequestWrapperは、元のリクエストを包み込んで扱うためのクラスです。元のリクエストの情報を取得したり、必要に応じて動作を変更したりできます。」
生徒
「普通のリクエストとの違いや、具体的なプログラムの書き方も知りたいです。」
先生
「それでは、Servletの基本から、getRequestURIの使い方、URLの判定方法、リクエストを加工する方法まで順番に確認していきましょう。」
1. Java ServletのHttpServletRequestWrapperとは?
JavaのHttpServletRequestWrapperは、Webアプリケーションで受け取ったHTTPリクエストを包み込んで扱うためのクラスです。Javaのパッケージでは、javax.servlet.httpに含まれています。
まず、Servletとは何かを理解しておきましょう。Servletは、Javaを使ってWebサイトやWebアプリケーションの処理を行う仕組みです。例えば、ログイン画面で入力された情報を受け取ったり、商品一覧を表示したり、問い合わせフォームの内容を処理したりするときに使われます。
利用者がブラウザでWebページを開くと、ブラウザからサーバーへリクエストという要求が送信されます。サーバーは、その要求に応じた処理を行い、結果をブラウザへ返します。
このとき、ブラウザから送られてきた情報をJavaで扱うためのインターフェースがHttpServletRequestです。
HttpServletRequestWrapperは、このリクエストを包み込むことで、元の情報を利用しながら必要な処理を追加できるようにします。
初心者向けのイメージ
リクエストを手紙に例えると、HttpServletRequestは届いた手紙そのものです。HttpServletRequestWrapperは、その手紙を透明な封筒に入れて扱うような仕組みです。手紙の内容を確認できるだけでなく、必要に応じて封筒側で情報の見せ方を変更することもできます。
HttpServletRequestWrapperは、元のリクエストを受け取るコンストラクタを持っています。コンストラクタとは、クラスからオブジェクトを作成するときに実行される特別な処理のことです。
なお、この記事ではjavax.servlet.httpを使用する従来のJava Servlet環境を対象とします。新しいJakarta Servletでは、パッケージ名がjakarta.servlet.httpに変更されています。使用するServletのバージョンによって、インポートするパッケージが異なるため注意してください。
2. getRequestURIメソッドとは?URLのどこを取得するの?
getRequestURIは、HTTPリクエストで指定されたURIのパス部分を取得するメソッドです。URIとは、インターネット上のページやファイルなどの場所を識別するための文字列です。
普段ブラウザで入力しているURLも、URIの仕組みを利用しています。URLには、通信方法、ドメイン名、パス、検索条件など、複数の情報が含まれています。
例えば、次のURLを考えてみましょう。
https://example.com/shop/products/detail?id=100
このURLに対してgetRequestURIを実行すると、通常は次の文字列が取得されます。
/shop/products/detail
URLの先頭にある通信方法のhttpsや、ドメイン名のexample.comは含まれません。また、疑問符から始まる検索条件も含まれません。
つまり、getRequestURIは、Webサイトの中でどの場所が要求されたのかを調べたいときに便利なメソッドです。
| URLの部分 | 具体例 | 取得対象 |
|---|---|---|
| 通信方法 | https | 含まれない |
| ドメイン名 | example.com | 含まれない |
| パス | /shop/products/detail | 含まれる |
| クエリ文字列 | id=100 | 含まれない |
クエリ文字列とは、URLの疑問符より後ろに指定される追加情報のことです。例えば、商品番号や検索キーワードをサーバーへ渡す場合に利用されます。
クエリ文字列を取得したい場合は、getQueryStringメソッドを使用します。URL全体を取得したい場合は、getRequestURLメソッドを利用する方法もあります。
ただし、getRequestURIが返す文字列には、Webアプリケーションのコンテキストパスも含まれます。コンテキストパスとは、サーバー上でWebアプリケーションを識別するための先頭部分です。
また、getRequestURIの戻り値は、URLに含まれるパーセントエンコードされた文字列を自動的に復号したものではありません。この点は、日本語を含むURLを扱う場合などに知っておくと役立ちます。
3. HttpServletRequestWrapperでgetRequestURIを使う基本プログラム
それでは、JavaのHttpServletRequestWrapperを使って、ブラウザからアクセスされたURIを取得するサンプルプログラムを作成してみましょう。
ここでは、Servletクラスを作成し、ブラウザからアクセスされたときにリクエストURIを表示します。
Servletでは、doGetメソッドを使うことで、ブラウザから送られてきたGETリクエストを処理できます。GETリクエストは、Webページを開いたり、検索結果を表示したりするときによく使われる通信方法です。
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/sample")
public class SampleServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
HttpServletRequestWrapper wrapper =
new HttpServletRequestWrapper(request);
String uri = wrapper.getRequestURI();
response.setContentType("text/plain; charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("リクエストURI: " + uri);
}
}
このプログラムでは、最初にHttpServletRequestWrapperのオブジェクトを作成しています。オブジェクトとは、クラスをもとにして作られた、実際に利用できるデータや機能のまとまりです。
コンストラクタへrequestを渡すことで、Servletが受け取ったリクエストをラップしています。その後、wrapper.getRequestURI()を実行して、アクセスされたURIを文字列として取得しています。
取得した文字列は、String型の変数に保存しています。変数とは、プログラムの中で値を保存しておくための名前付きの入れ物です。
最後にPrintWriterを使って、ブラウザへ文字列を返しています。PrintWriterは、文字を出力するために使用するJavaのクラスです。
Webアプリケーションのコンテキストパスが/myappで、ブラウザから/myapp/sampleへアクセスした場合、次のように表示されます。
リクエストURI: /myapp/sample
このように、HttpServletRequestWrapperのgetRequestURIを使えば、現在アクセスされているリクエストのパスを簡単に確認できます。
なお、URIを取得するだけであれば、HttpServletRequestWrapperを作成せずに、request.getRequestURI()を直接実行しても同じ情報を取得できます。Wrapperを使うメリットは、後から処理を追加したり、取得結果を変更したりできる点にあります。
4. getRequestURIを使ってアクセス先のページを判定する方法
getRequestURIメソッドは、現在のページを調べるだけでなく、アクセスされたURLに応じて処理を分ける場合にも利用できます。
例えば、会員向けページ、商品一覧ページ、管理画面など、Webアプリケーションにはさまざまなページがあります。アクセス先によって表示するメッセージを変更したい場合、URIを使った条件分岐が役立ちます。
条件分岐とは、条件が成立するかどうかによって、実行する処理を切り替える仕組みです。Javaではif文を使用します。
次のプログラムでは、アクセスされたURIに応じて表示するメッセージを変更しています。
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
@WebServlet({"/products", "/members"})
public class PageCheckServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
HttpServletRequestWrapper wrapper =
new HttpServletRequestWrapper(request);
String uri = wrapper.getRequestURI();
String contextPath = wrapper.getContextPath();
String page = uri.substring(contextPath.length());
response.setContentType("text/plain; charset=UTF-8");
if (page.equals("/products")) {
response.getWriter().println("商品一覧ページです");
} else if (page.equals("/members")) {
response.getWriter().println("会員ページです");
} else {
response.getWriter().println("その他のページです");
}
}
}
このプログラムでは、getContextPathメソッドも使用しています。getContextPathは、Webアプリケーションのコンテキストパスを取得するメソッドです。
例えば、URIが/myapp/productsで、コンテキストパスが/myappの場合、先頭部分を取り除くと/productsになります。
substringメソッドは、文字列の指定した位置から一部分を取り出すためのメソッドです。ここでは、コンテキストパスの文字数を指定して、その後ろにあるパスを取り出しています。
このようにしておくと、Webアプリケーションの配置場所が変わっても、ページを判定する処理を再利用しやすくなります。
コンテキストパスが/myappで、/myapp/productsへアクセスした場合は、次の結果になります。
商品一覧ページです
また、/myapp/membersへアクセスした場合は、次の結果になります。
会員ページです
この方法は、Servletでアクセス先のURLを調べたい場合や、簡単なページ判定を行いたい場合に便利です。ただし、ログイン認証やアクセス権限の判定を、単純な文字列比較だけで実装するのは適切ではありません。
特に管理画面や会員専用ページでは、認証済みかどうか、利用者に必要な権限があるかどうかを、別途確認する必要があります。
5. getRequestURIをオーバーライドしてURIを変更する方法
HttpServletRequestWrapperの大きな特徴は、元のリクエストを利用しながら、特定のメソッドの動作を変更できることです。
Javaでは、親クラスから受け継いだメソッドを、子クラスで書き直すことをオーバーライドと呼びます。オーバーライドを利用すると、同じメソッド名でも、独自の処理を実行できるようになります。
例えば、元のリクエストURIを取得した後に、特定の文字列を追加したり、別のURIとして返したりする処理を作成できます。
次のプログラムでは、HttpServletRequestWrapperを継承した独自のクラスを作成し、getRequestURIの戻り値を変更しています。
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class CustomRequestWrapper
extends HttpServletRequestWrapper {
public CustomRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getRequestURI() {
String originalUri = super.getRequestURI();
return originalUri + "/custom";
}
}
このプログラムでは、extendsを使ってHttpServletRequestWrapperを継承しています。継承とは、既存のクラスが持つ機能を引き継いで、新しいクラスを作る仕組みです。
super(request)は、親クラスのコンストラクタを呼び出しています。これによって、元のHttpServletRequestを親クラスへ渡しています。
また、@Overrideは、親クラスのメソッドをオーバーライドしていることを示すアノテーションです。アノテーションとは、Javaのプログラムに追加情報を付けるための仕組みです。
super.getRequestURI()を実行すると、親クラスが持つgetRequestURIの処理を呼び出せます。この場合、包み込まれている元のリクエストからURIを取得します。
最後に、取得したURIの末尾へ/customを追加して返しています。
例えば、元のURIが/myapp/sampleであれば、この独自クラスのgetRequestURIは、次の文字列を返します。
/myapp/sample/custom
ただし、この処理はgetRequestURIメソッドが返す文字列を変更しているだけです。実際にブラウザがアクセスしたURLを書き換えたり、サーバー上の別のページへ自動的に移動したりするわけではありません。
また、getRequestURIだけを変更しても、getRequestURLやgetServletPathなどの関連情報が自動的に変更されるわけではありません。実際のWebアプリケーションでURIを変更して扱う場合は、関連するメソッドとの整合性にも注意する必要があります。
6. 独自のHttpServletRequestWrapperをServletから利用する方法
前の項目では、getRequestURIをオーバーライドした独自クラスを作成しました。ここでは、そのクラスをServletから利用する方法を確認します。
独自のHttpServletRequestWrapperを作成しただけでは、Servletの処理が自動的に変更されるわけではありません。作成したクラスのオブジェクトを使って、メソッドを呼び出す必要があります。
次のサンプルプログラムでは、元のURIと、独自のWrapperによって変更されたURIを比較して表示します。
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/compare")
public class CompareServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
String originalUri = request.getRequestURI();
CustomRequestWrapper wrapper =
new CustomRequestWrapper(request);
String customUri = wrapper.getRequestURI();
response.setContentType("text/plain; charset=UTF-8");
response.getWriter().println(
"元のURI: " + originalUri);
response.getWriter().println(
"変更後のURI: " + customUri);
}
}
このプログラムは、前の項目で作成したCustomRequestWrapperクラスが、同じJavaパッケージ内に存在することを前提としています。
最初に、通常のHttpServletRequestからgetRequestURIを実行して、元のURIを取得しています。
次に、CustomRequestWrapperのオブジェクトを作成して、独自に変更したgetRequestURIを呼び出しています。
同じリクエストを扱っていても、どちらのオブジェクトからメソッドを呼び出すかによって、取得する文字列が異なります。
コンテキストパスが/myappで、/myapp/compareへアクセスした場合は、次のように表示されます。
元のURI: /myapp/compare
変更後のURI: /myapp/compare/custom
この結果から、元のHttpServletRequestが返すURIと、独自のHttpServletRequestWrapperが返すURIの違いを確認できます。
HttpServletRequestWrapperは、単にURLを取得するだけでなく、リクエスト情報を加工して別の処理へ渡したい場合にも役立ちます。
実際のWebアプリケーションでは、Servlet Filterと組み合わせて利用することがあります。Filterとは、Servletが処理を実行する前後に、共通の処理を追加できる仕組みです。
例えば、アクセスログの記録、リクエスト情報の確認、入力内容の加工などに利用できます。WrapperをFilterから次の処理へ渡すことで、後続のServletなどが独自のリクエスト情報を利用できるようになります。
7. getRequestURIとgetRequestURLやgetServletPathの違い
Java Servletには、URLに関する情報を取得するメソッドが複数あります。初心者が混同しやすいのが、getRequestURI、getRequestURL、getContextPath、getServletPath、getQueryStringの違いです。
これらのメソッドは、それぞれ取得する情報が異なります。WebアプリケーションでURLを正しく扱うためには、目的に合ったメソッドを選ぶことが大切です。
例えば、次のURLへアクセスした場合を考えてみましょう。
https://example.com/myapp/products?id=100
ここでは、Webアプリケーションのコンテキストパスを/myapp、ServletのURLマッピングを/productsとします。
| メソッド | 取得する情報 |
|---|---|
| getRequestURI | /myapp/products |
| getRequestURL | https://example.com/myapp/products |
| getContextPath | /myapp |
| getServletPath | /products |
| getQueryString | id=100 |
getRequestURIは、リクエストされたURIのパスを取得するためのメソッドです。アクセスされたページの場所を調べる場合に向いています。
getRequestURLは、通信方法やホスト名を含むURLを取得するメソッドです。ただし、クエリ文字列は含まれません。また、戻り値はStringではなくStringBufferです。
getContextPathは、Webアプリケーションが配置されている場所を取得するメソッドです。アプリケーションの配置先によって値が変わるため、URLを組み立てる際に役立ちます。
getServletPathは、ServletのURLマッピングに関係するパスを取得するメソッドです。ただし、マッピング方法によって取得結果が異なり、常にgetRequestURIからコンテキストパスを除いた値になるとは限りません。
getQueryStringは、検索条件などのクエリ文字列を取得します。クエリ文字列が存在しない場合は、nullが返されます。
このように、似た名前のメソッドでも取得する範囲が違います。ServletでURLを扱う際は、何を取得したいのかを先に考えると、適切なメソッドを選びやすくなります。
8. HttpServletRequestWrapperとgetRequestURIを使うときの注意点
HttpServletRequestWrapperとgetRequestURIは便利な仕組みですが、実際のWebアプリケーション開発では、いくつか注意しておきたい点があります。
URIにはクエリ文字列が含まれない
getRequestURIでは、URLの疑問符以降にあるクエリ文字列を取得できません。例えば、商品番号や検索キーワードを調べたい場合は、getParameterやgetQueryStringなどを使用します。
特にgetParameterは、指定した名前のパラメータ値を取得できるため、フォームの入力内容を受け取る処理でもよく使われます。
コンテキストパスを考慮する
getRequestURIで取得する文字列には、通常、コンテキストパスが含まれます。開発環境では問題なく動いていても、本番環境でアプリケーションの配置場所が変わると、文字列比較の結果が変わることがあります。
そのため、ページの判定ではgetContextPathを利用したり、ServletのURLマッピングを考慮したりすることが重要です。
Wrapperを作成しただけでは元のリクエストは変わらない
HttpServletRequestWrapperは、元のリクエストを包み込んで利用するためのクラスです。独自のメソッドを追加しても、元のHttpServletRequestオブジェクトの動作が自動的に変更されるわけではありません。
独自の動作を利用するには、作成したWrapperのオブジェクトを使う必要があります。また、後続のServletで利用したい場合は、FilterなどからWrapperを渡す仕組みが必要になります。
URLの文字列だけでセキュリティを判断しない
リクエストURIを利用すると、アクセス先のページを調べられます。しかし、URIの文字列だけを見て、ログイン済みかどうかや、管理者権限を持っているかどうかを判断するのは危険です。
アクセス制御を行う場合は、セッション情報や認証の仕組みを利用し、適切な権限確認を実装する必要があります。
また、URIは外部から送られてくるリクエスト情報のため、画面へ表示したり、別の処理へ渡したりするときは、安全な取り扱いを意識してください。
Servletのバージョンとパッケージ名を確認する
Java Servletのサンプルプログラムをインターネットで調べると、javax.servletとjakarta.servletの両方が見つかることがあります。
これは、Servletのバージョンによって使用するパッケージ名が変更されているためです。Java EEやServlet 4.0以前を使用する環境ではjavax.servletが使われ、Jakarta Servlet 5.0以降ではjakarta.servletが使われます。
例えば、Tomcat 9ではjavax.servletを使用しますが、Tomcat 10以降ではjakarta.servletを使用します。異なるパッケージを混在させると、コンパイルエラーや実行時の問題が発生する場合があります。
初心者のうちは、使用しているTomcatのバージョンと、教材やサンプルプログラムのパッケージ名が一致しているか確認すると、エラーの原因を見つけやすくなります。
学習するときのポイント
最初はHttpServletRequestから直接getRequestURIを実行して、どのような文字列が取得できるか確認してみましょう。その後、HttpServletRequestWrapperを使って同じURIを取得し、最後にオーバーライドで戻り値を変更すると、それぞれの役割の違いを理解しやすくなります。
まとめ
今回は、Java Servletのjavax.servlet.httpパッケージに含まれるHttpServletRequestWrapperクラスと、getRequestURIメソッドの使い方について学習しました。JavaでWebアプリケーションを開発するときには、ブラウザから送られてくるリクエストを正しく理解することが大切です。特に、利用者がどのページへアクセスしたのかを取得する処理は、ページの表示切り替えやアクセスログの記録、リクエストの確認など、さまざまな場面で利用できます。
Servletは、ブラウザから送信された要求をサーバー側で処理するためのJavaの仕組みです。例えば、商品一覧を表示するページ、会員情報を確認するページ、ログイン画面、問い合わせフォームなどを作成するときに使用します。ブラウザからの要求はHTTPリクエストと呼ばれ、JavaではHttpServletRequestというインターフェースを通して、その情報を取得できます。
HttpServletRequestWrapperは、元のHttpServletRequestを包み込んで利用するためのクラスです。元のリクエストが持っている情報をそのまま利用することもできますし、必要に応じて特定のメソッドをオーバーライドして、取得する値や処理内容を変更することもできます。単純にリクエスト情報を取得するだけならHttpServletRequestで十分ですが、リクエストの動作を拡張したい場合にはHttpServletRequestWrapperが役立ちます。
getRequestURIで取得できる情報を理解しよう
getRequestURIメソッドは、ブラウザから要求されたURIのパス部分を取得するためのメソッドです。例えば、利用者が商品詳細ページへアクセスした場合、そのページを識別するためのパスを文字列として取得できます。
ここで覚えておきたいのは、getRequestURIで取得できるのはURL全体ではないという点です。通信方法を表すhttpsやドメイン名は含まれず、疑問符以降のクエリ文字列も含まれません。一方、Webアプリケーションのコンテキストパスは含まれます。
コンテキストパスとは、サーバー上でWebアプリケーションが配置されている場所を表す文字列です。例えば、アプリケーションをmyappという名前で配置している場合、取得するURIの先頭にその名前が含まれることがあります。
Java ServletでURLの取得方法を調べると、getRequestURIとgetRequestURLの違いがわからなくなることがあります。getRequestURIはパス部分を取得し、getRequestURLは通信方法やホスト名を含むURLを取得します。ただし、getRequestURLにもクエリ文字列は含まれません。検索条件などを取得したい場合には、getQueryStringやgetParameterを利用します。
この違いを理解しておくと、Javaで現在のページのURLを取得したい場合や、アクセス先のServletを判定したい場合に、適切なメソッドを選びやすくなります。
HttpServletRequestWrapperを使う基本的な流れ
HttpServletRequestWrapperを利用するときは、Servletが受け取ったHttpServletRequestをコンストラクタへ渡します。コンストラクタとは、クラスからオブジェクトを作成するときに呼び出される処理です。
作成したWrapperオブジェクトからgetRequestURIを呼び出すと、元のリクエストが持っているURIを取得できます。特別なオーバーライドをしていない場合、基本的には元のHttpServletRequestから取得する値と同じになります。
次のサンプルプログラムでは、HttpServletRequestWrapperを利用してアクセスされたURIを取得し、ブラウザへ表示します。Java Servletを初めて学習する場合は、このような短いプログラムから確認すると理解しやすくなります。
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/url")
public class UrlServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
HttpServletRequestWrapper wrapper =
new HttpServletRequestWrapper(request);
String uri = wrapper.getRequestURI();
response.setContentType("text/plain; charset=UTF-8");
response.getWriter().println("アクセス先: " + uri);
}
}
このプログラムでは、最初にHttpServletRequestWrapperのオブジェクトを作成しています。続いて、getRequestURIメソッドを実行し、取得したURIをString型の変数に保存しています。
String型とは、文字列を扱うためのJavaのデータ型です。取得したURIを変数へ保存しておくことで、後から表示したり、文字列を比較したりする処理に利用できます。
最後に、responseのgetWriterメソッドを使って、取得したURIをブラウザへ出力しています。responseは、サーバーからブラウザへ返す情報を扱うためのオブジェクトです。
Webアプリケーションのコンテキストパスがmyappで、urlというServletへアクセスした場合、次のような結果が表示されます。
アクセス先: /myapp/url
このように、getRequestURIを使えば、アクセスされたページの場所を簡単に確認できます。Servletの動作を確認するときや、どのURLへリクエストが送信されているのかを調べたいときにも便利です。
取得したURIを使ってページごとの処理を変更する
getRequestURIで取得した文字列は、Javaのif文と組み合わせることで、アクセス先に応じた条件分岐にも利用できます。条件分岐とは、指定した条件が成立するかどうかによって、実行する処理を切り替える仕組みです。
例えば、商品一覧ページへアクセスした場合は商品に関するメッセージを表示し、お問い合わせページへアクセスした場合は別のメッセージを表示する、といった処理を作成できます。
ただし、getRequestURIにはコンテキストパスが含まれるため、文字列を比較するときには注意が必要です。アプリケーションの配置場所が変わると、取得するURIも変わる場合があります。
そのような場合は、getContextPathメソッドでコンテキストパスを取得し、必要な部分だけを取り出して比較すると、環境の違いに対応しやすくなります。
また、URIを使ったページ判定と、利用者の認証やアクセス権限の確認は別の処理です。管理画面や会員専用ページを作成するときは、URIの比較だけでなく、ログイン状態や利用者の権限を適切に確認する必要があります。
オーバーライドによって独自の処理を追加できる
HttpServletRequestWrapperを学習するうえで重要なのが、オーバーライドという仕組みです。オーバーライドとは、親クラスから受け継いだメソッドを、子クラスで書き直すことです。
例えば、HttpServletRequestWrapperを継承した独自クラスを作成し、getRequestURIメソッドをオーバーライドすると、元のURIを取得した後に独自の文字列を追加することができます。
次のサンプルプログラムでは、取得したURIの先頭にあるコンテキストパスを除いた文字列を返す独自のWrapperクラスを作成しています。
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class SimpleRequestWrapper
extends HttpServletRequestWrapper {
public SimpleRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getRequestURI() {
String uri = super.getRequestURI();
String contextPath = super.getContextPath();
return uri.substring(contextPath.length());
}
}
このプログラムでは、extendsを使ってHttpServletRequestWrapperを継承しています。継承とは、既存のクラスが持っている機能を引き継いで、新しいクラスを作成する仕組みです。
super.getRequestURIを実行すると、元のリクエストからURIを取得できます。また、super.getContextPathを実行すると、Webアプリケーションのコンテキストパスを取得できます。
その後、substringメソッドを使って、コンテキストパスの文字数に相当する先頭部分を取り除いています。substringは、文字列の指定した位置から必要な部分を取り出すためのメソッドです。
例えば、元のURIがmyappから始まる商品一覧ページのパスだった場合、この独自クラスのgetRequestURIを呼び出すと、商品一覧ページを表す部分だけを取得できます。
ただし、この方法はWrapperのgetRequestURIが返す文字列を変更しているだけで、ブラウザがアクセスしたURLそのものを変更するわけではありません。また、getServletPathやgetRequestURLなどの関連するメソッドが自動的に変更されるわけでもありません。
そのため、実際のWebアプリケーションで独自のURIを扱う場合には、他のメソッドとの整合性を考えることが大切です。単純にコンテキストパスを取り除きたいだけであれば、元のURIを別の変数へ保存して加工する方法でも対応できます。
Servlet Filterと組み合わせる場合の考え方
HttpServletRequestWrapperは、Servlet Filterと組み合わせて利用されることもあります。Filterとは、Servletの処理が実行される前後に、共通の処理を追加できる仕組みです。
例えば、Webアプリケーション内の複数のページについて、アクセスされたURIを記録したい場合があります。このような処理を各Servletに個別に記述すると、同じプログラムを何度も書くことになります。
Filterを使えば、Servletへ処理が渡される前にリクエストを確認できます。さらに、HttpServletRequestWrapperを利用すれば、リクエストの情報を加工して、後続の処理へ渡すこともできます。
ただし、アクセスされたURIを記録するだけなら、必ずしもHttpServletRequestWrapperを作成する必要はありません。通常のHttpServletRequestからgetRequestURIを呼び出すだけでも、アクセス先を取得できます。
Wrapperが特に役立つのは、後続の処理から見えるリクエスト情報を変更したい場合です。例えば、特定の入力値を加工したり、リクエストヘッダーの取得結果を変更したりする場合に利用できます。
Servletのバージョンとパッケージ名にも注意する
Java Servletの学習では、javax.servletとjakarta.servletの違いにも注意しましょう。この記事で使用しているHttpServletRequestWrapperは、javax.servlet.httpパッケージに含まれるクラスです。
Tomcat 9などの従来のServlet環境ではjavax.servletを使用します。一方、Tomcat 10以降ではJakarta Servletに対応しており、jakarta.servletというパッケージ名を使用します。
インターネットでJava Servletのサンプルコードを調べると、両方の書き方が見つかります。使用している開発環境とサンプルコードのパッケージ名が一致していないと、クラスを読み込めないエラーやコンパイルエラーが発生することがあります。
そのため、Eclipseなどの開発環境でServletを作成するときは、使用しているTomcatのバージョンや、プロジェクトに設定されているServletのライブラリを確認することが大切です。
Java Servletの初心者は、最初から複雑なWrapperやFilterを作成する必要はありません。まずはHttpServletRequestからgetRequestURIを使ってURIを取得し、その後にHttpServletRequestWrapperを使って同じ情報を取得してみましょう。
さらに、getContextPathやgetServletPathとの違いを確認し、最後にオーバーライドを試すことで、Servletのリクエスト処理を段階的に理解できます。
今回学習したgetRequestURIの使い方は、アクセス先の確認、ページごとの条件分岐、リクエスト情報の調査など、JavaによるWebアプリケーション開発の基本となる知識です。HttpServletRequestとHttpServletRequestWrapperの役割を区別できるようになると、Servlet Filterやリクエスト処理の仕組みも理解しやすくなります。
生徒
「今回の学習で、getRequestURIを使うと、ブラウザからアクセスされたページのパスを取得できることがわかりました。URL全体を取得するメソッドだと思っていましたが、そうではないんですね。」
先生
「その通りです。getRequestURIは、アクセスされたURIのパス部分を取得します。ドメイン名やクエリ文字列は含まれません。URL全体に近い情報が必要ならgetRequestURL、検索条件を取得したいならgetQueryStringやgetParameterなど、目的によって使い分けます。」
生徒
「HttpServletRequestWrapperを使わなくても、HttpServletRequestから直接getRequestURIを呼び出せるんですよね。それなら、Wrapperはどんなときに使うのでしょうか?」
先生
「URIを取得するだけなら、通常のHttpServletRequestで十分です。HttpServletRequestWrapperは、元のリクエストを包み込み、必要なメソッドの動作を変更したいときに使います。例えば、取得するリクエスト情報を加工して、別の処理へ渡すような場面です。」
生徒
「オーバーライドすると、getRequestURIで返す文字列を変更できることもわかりました。ただし、実際にブラウザのURLが変更されるわけではないんですね。」
先生
「そうです。オーバーライドは、メソッドの動作を変更する仕組みです。ブラウザを別のURLへ移動させるリダイレクトとは異なります。また、getRequestURIだけを変更しても、他のURL関連メソッドが自動的に変更されるわけではないことも覚えておきましょう。」
生徒
「getContextPathを使う理由も理解できました。アプリケーションの配置場所が変わる場合は、コンテキストパスを考えて処理を書いたほうがいいんですね。」
先生
「はい。開発環境と本番環境でアプリケーションの配置場所が異なることもあります。URIを文字列で比較するときは、コンテキストパスやServletのURLマッピングを意識すると、間違いを防ぎやすくなります。」
生徒
「まずはServletでgetRequestURIを実行して、アクセス先のパスを表示するプログラムを自分で作ってみます。その後、HttpServletRequestWrapperを使って、取得結果を比較してみたいです。」
先生
「その順番で練習すると理解しやすいですよ。最初は短いプログラムで動作を確認し、慣れてきたら条件分岐やオーバーライドにも挑戦してみましょう。今回の知識は、Java ServletのURL処理やリクエスト管理を学ぶときの基礎になります。」
ChatGPTなどの生成AIをこれから学びたい方に向けて、AIスキルアカデミーの口コミ・評判、料金、無料セミナーの内容を詳しくまとめています。
AIスキルアカデミーの口コミ・評判を詳しく見る