Java ServletのWebConnection#getInputStreamメソッド完全ガイド!初心者でもわかる低レベルストリーム処理の基本
生徒
「Servletで通信の中身を直接読み取る方法ってあるんですか?」
先生
「ありますよ。ServletのWebConnectionインターフェースのgetInputStream()メソッドを使えば、クライアントからのデータを直接読み取ることができます。」
生徒
「それって普通のHttpServletRequestのgetReaderとは違うんですか?」
先生
「用途が異なります。より低レベルなバイナリ通信を扱いたい場合にgetInputStreamが使われるんですよ。詳しく見ていきましょう。」
1. WebConnectionとgetInputStreamの関係
javax.servlet.http.WebConnectionは、HTTP接続をアップグレードした後にサーバーとクライアント間のデータ通信を制御するためのインターフェースです。
このWebConnectionインターフェースには、通信の入力を処理するgetInputStream()メソッドが含まれており、HTTPリクエストのバイナリデータを直接読み込むことができます。
通常のServletではrequest.getReader()を使ってテキストを読み取りますが、getInputStream()はもっと低レベルで、バイト単位の処理が可能です。
2. getInputStreamメソッドの役割と戻り値
getInputStream()メソッドは、クライアントから送信されたバイナリデータを読み込むためのServletInputStreamオブジェクトを返します。
このストリームを使用することで、画像ファイルや音声データ、バイナリ形式のリクエストボディなど、テキストではない形式のデータも受け取ることができます。
以下のように使うことで、クライアントからのデータを受信できます。
ServletInputStream input = webConnection.getInputStream();
byte[] buffer = new byte[1024];
int length = input.read(buffer);
このように、入力ストリームからデータを読み込み、必要に応じて処理を行います。
3. 実践的な使用例
以下に、ServletでWebConnectionのgetInputStream()を使った基本的な例を示します。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@WebServlet("/stream")
public class StreamServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.upgrade(MyStreamHandler.class);
}
}
class MyStreamHandler implements HttpUpgradeHandler {
@Override
public void init(WebConnection webConnection) {
try (InputStream in = webConnection.getInputStream();
OutputStream out = webConnection.getOutputStream()) {
byte[] buffer = new byte[1024];
int len = in.read(buffer);
if (len != -1) {
out.write(("受信したデータ:" + new String(buffer, 0, len)).getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void destroy() {
// クリーンアップ処理
}
}
この例では、HTTP通信をアップグレードして、ストリームベースの双方向通信を実現しています。クライアントから送られたデータをgetInputStream()で受信し、その内容をクライアントにそのまま返しています。
4. getInputStreamの読み込みと注意点
getInputStream()で取得したInputStreamは、必ず正しく閉じる必要があります。try-with-resources構文を使うことで、自動的にストリームを閉じることができ、安全です。
また、read()メソッドが返す-1は、ストリームの終端を意味するため、ループで処理する場合には注意して使いましょう。
int len;
while ((len = in.read(buffer)) != -1) {
// 読み取ったデータを処理
}
データのサイズが不明な場合や長いストリームを読み込むときには、このようにループ処理を使ってデータをすべて読み込むことが基本です。
5. getInputStreamとセキュリティの観点
getInputStream()で読み込むデータは、クライアントから直接送られたものであるため、不正な入力やバイナリ攻撃への対策が必要です。
たとえば、読み込むデータのサイズを制限したり、特定の形式でなければ無視するなどのバリデーション処理が必要になります。
また、データの読み取り時には、ファイルの種類やエンコーディングにも注意して処理しましょう。
6. getInputStreamが活躍する具体的なシーン
getInputStream()は、次のようなユースケースで役立ちます。
- WebSocketによるバイナリ通信
- 画像や音声ファイルのリアルタイム受信
- カスタムプロトコルの実装
たとえば、IoTデバイスやストリーミングサービスなどで、リアルタイムにデータを送受信したい場合、getInputStream()を使ってバイナリデータを直接扱うことができます。