HttpServletRequestのgetReader()とgetInputStream()による読み出しは一度しか行えない

クライアントで、

curl http://localhost:8080/testWeb/testServlet -F hoge=atai

のようなコマンドを実行して、

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try{
        ServletInputStream is= request.getInputStream();
        while(!is.isFinished()){
            char hoge=(char)is.read();
            System.out.print(hoge);
        }
    }catch(Exception ex){
        System.out.println(ex.getMessage());
    }

    try{
        BufferedReader bf=request.getReader();
        while(bf.ready()){
            char hoge=(char)bf.read();
            System.out.print(hoge);
        }
    }catch(Exception ex){
        System.out.println(ex.getMessage());
    }
}

のようにリクエストをサーバー側で処理するとエラーになります。同時にBufferedReaderとServletInputStreamを受け取れないためのようです。

これと同じで、getReader()による読み出しとmultipart/form-dataによる読み出しでも同じエラーが出ます。

        try{
            request.getReader();
        }catch(Exception ex){
            System.out.println(ex.getMessage());
        }

        ServletFileUpload upload =
                  new ServletFileUpload(new DiskFileItemFactory());

                List items;
                try {
                  items = upload.parseRequest((RequestContext) rq );
                } catch(Exception ex){
                    System.out.println(ex.getMessage());
                    throw new ServletException(ex);
                }

                for (Object val : items) {
                  FileItem item = (FileItem) val;
                  if (item.isFormField()) {
                    System.out.println("form data ("
                      + item.getFieldName() + ": " + new String(item.get())
                      + ")");
                  } else {
                    System.out.println("file found!");
                  }
                }
        System.out.println(request.getContentType());

また、

        try{
            ServletInputStream is= request.getInputStream();
//          while(!is.isFinished()){
//              char hoge=(char)is.read();
//              System.out.print(hoge);
//          }

        }catch(Exception ex){
            System.out.println(ex.getMessage());
        }

        ServletFileUpload upload =
                  new ServletFileUpload(new DiskFileItemFactory());

                List items;
                try {
                  items = upload.parseRequest((RequestContext) rq );
                } catch(Exception ex){
                    System.out.println(ex.getMessage());
                    throw new ServletException(ex);
                }

                for (Object val : items) {
                  FileItem item = (FileItem) val;
                  if (item.isFormField()) {
                    System.out.println("form data ("
                      + item.getFieldName() + ": " + new String(item.get())
                      + ")");
                  } else {
                    System.out.println("file found!");
                  }
                }

のようなコードの場合では、multipart/form-dataの値を取得できますが、
コメントアウト部分を外すと、multipart/form-dataの値を取得できなくなることから、Streamによる読み出しは一度きりになっていることが確認できます。

このようなエラーが出た場合に、getReader()とgetInputStream()が実行されている箇所を特定したい場合には、EclipseでRequest.classのusingInputStreamとusingReaderの変更にブレークポイントを設定すれば、デバッグビューを見て調べることが出来ます。

参考にさせていただいたサイト:http://d.hatena.ne.jp/machi_pon/20090120/1232420325