8

たとえば、属性をHttpServletRequestに設定するサーブレットコードがあります。

request.setAttribute("someValue", someValue());
        RequestDispatcher rd = getServletContext().getRequestDispatcher("/SomeJsp.jsp");
        rd.forward(this.request, this.response);
        return;

上記のコードがスレッドセーフであることを確認するにはどうすればよいですか?

これは私が取得しているスタックトレースです:

java.lang.NullPointerException
    at org.apache.catalina.connector.Request.notifyAttributeAssigned(Request.java:1552)
    at org.apache.catalina.connector.Request.access$000(Request.java:105)
    at org.apache.catalina.connector.Request$3.set(Request.java:3342)
    at org.apache.catalina.connector.Request.setAttribute(Request.java:1504)
    at org.apache.catalina.connector.RequestFacade.setAttribute(RequestFacade.java:541)
    at org.apache.catalina.core.ApplicationHttpRequest.setAttribute(ApplicationHttpRequest.java:281)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:286)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:684)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:471)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:402)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:329)
    at com.mycompany.myapp.servlet.SomeServlet.doRequest(SomeServlet.java:103)
    at com.mycompany.myapp.servlet.SomeServlet.doGet(SomeServlet.java:159)
4

5 に答える 5

11
rd.forward(this.request, this.response);

これは(しゃれを意図した)、クラスのインスタンス変数として割り当てたものrequestであることを示しています。response次に、具体的な問題は、クラス自体のインスタンスがスレッドセーフではないことを示唆しています。

それが実際にはサーブレット自体であると仮定すると、問題の原因はそこにあります。サーブレットはスレッドセーフではありません。Webアプリの起動時に作成されたインスタンスは1つだけで、アプリケーション全体のすべてのリクエストで共有されます。

リクエストまたはセッションスコープのデータをサーブレットのインスタンス変数として割り当てないでください。別のHTTPリクエストが同時に発生した場合にのみオーバーライドされます。あなたが自分自身に遭遇したように、それはあなたのコードをスレッドセーフにしません。

これを説明するコードを次に示します。

public class MyServlet extends HttpServlet {

    private Object thisIsNOTThreadSafe;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object thisIsThreadSafe;

        thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
        thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
    } 
}

HTTPリクエスト自体をサーブレットのインスタンス変数として割り当てることは、実際には壮大な間違いです。サーブレットがユーザーXの要求を処理しているのと同時に、ユーザーYが別の要求を実行すると、ユーザーXはユーザーYのオブジェクトrequestとオブジェクトを即座に取得します。responseこれは間違いなくスレッドセーフではありません。NPEはrequest、その時点でユーザーYの処理が「終了」し、解放/破棄されたために発生します。

参照:

于 2012-12-20T11:57:32.243 に答える
2

リクエストは、その定義によりスレッドセーフです(SessionやServletContextとは異なります)。

例外について:使用しているTomcatのバージョンは何ですか?これはTomcatのバグのようです。

メソッドの戻り型であるクラスはsomeValue()実装されていHttpAttributeBindingListenerますか?そして、someValue()メソッドは返すことができnullますか?両方が「はい」の場合、それNullPointerExceptionは明らかです。

于 2012-12-20T11:35:51.233 に答える
1

これがスレッドセーフであることと何の関係があるのか​​わかりません。

発生している例外はNullPointerExceptionで、Tomcatがnullオブジェクトのメソッドを呼び出そうとしているように見えます。

Java Webアプリケーションでは、各リクエストに独自のHttpServletRequestインスタンスがあるため、リクエストに属性を設定して、そのユーザー専用であると確信することができます。

于 2012-12-20T11:36:40.680 に答える
1

この演算子なしで使用する

     RequestDispatcher rd = getServletContext().getRequestDispatcher("/SomeJsp.jsp");
    rd.forward(request, response);
    return;
于 2012-12-21T09:32:19.623 に答える
0

tomcatでのリクエストインターフェイスの実装を見ると、以下のコードのようになります。

public void setAttribute(String name, Object value) {

    // Name cannot be null
    if (name == null)
        throw new IllegalArgumentException
            (sm.getString("coyoteRequest.setAttribute.namenull"));

    // Null value is the same as removeAttribute()
    if (value == null) {
        removeAttribute(name);
        return;
    }

    if (name.equals(Globals.DISPATCHER_TYPE_ATTR)) {
        internalDispatcherType = (DispatcherType)value;
        return;
    } else if (name.equals(Globals.DISPATCHER_REQUEST_PATH_ATTR)) {
        requestDispatcherPath = value;
        return;
    }

キーがnullの場合、 IllegalArgumentExceptionがスローされますが、値がnullの場合、キーとそのキーに関連付けられている古いオブジェクトがリポジトリから削除されることがはっきりとわかります。ただし、それらのいずれもnullでない場合は、オブジェクトをそのキーに関連付け、リポジトリに追加します。

一時的な問題またはTomcatの問題のようです。

実装の詳細については、以下のリンクを参照してください 。tomcatによるリクエスト実装のソースコード

于 2012-12-21T06:20:04.807 に答える