JSP 2 を使用して、JSP ファイル内の Java コードを回避するにはどうすればよいでしょうか? 質問する

JSP 2 を使用して、JSP ファイル内の Java コードを回避するにはどうすればよいでしょうか? 質問する

私は次の3行のようなものを知っています

<%= x+1 %>
<%= request.getParameter("name") %>
<%! counter++; %>

は古いコーディング方法であり、JSP バージョン 2 では JSP ファイルで Java コードを回避する方法が存在します。代替の JSP 2 行とは何ですか。また、このテクニックは何と呼ばれますか。

ベストアンサー1

スクリプトレット(それら<% %>の使用JSPタグライブラリの誕生以来、これは非常に推奨されていませんJSTL) そしてエル表現言語、それらの${}もの)は2001年に遡ります。

スクリプトレットの主な欠点は次のとおりです。

  1. 再利用性:スクリプトレットを再利用することはできません。
  2. 置き換え可能性:スクリプトレットを抽象化することはできません。
  3. OO 機能:継承/合成を利用することはできません。
  4. デバッグ可能性:スクリプトレットが途中で例外をスローした場合、空白のページのみが表示されます。
  5. テスト可能性:スクリプトレットは単体テストできません。
  6. 保守性:混在/乱雑/重複したコード ロジックを保守するには、より多くの時間が必要になります。

Sun Oracle自身も、JSPコーディング規約同じ機能が (タグ) クラスで可能な場合は、スクリプトレットの使用を避けます。関連するいくつかの引用を次に示します。

JSP 1.2 仕様では、ページ内のJSP スクリプトレットの必要性を減らすために、Web アプリケーションで JSP 標準タグ ライブラリ (JSTL) を使用することを強くお勧めします。一般に、JSTL を使用するページは読みやすく、保守も簡単です。

...

可能な限り、タグ ライブラリが同等の機能を提供している場合は、 JSP スクリプトレットの使用を避けてください。これにより、ページの読み取りと保守が容易になり、ビジネス ロジックとプレゼンテーション ロジックを分離するのに役立ち、ページを JSP 2.0 スタイルのページに簡単に展開できるようになります (JSP 2.0 仕様では、スクリプトレットの使用はサポートされていますが、あまり重視されていません)。

...

モデル ビュー コントローラ (MVC) 設計パターンを採用してプレゼンテーション層とビジネス ロジックの結合を減らすという考え方から、ビジネス ロジックの記述にはJSP スクリプトレットを使用しないでください。JSP スクリプトレットは、クライアントの要求の処理から返されたデータ (「値オブジェクト」とも呼ばれます) を適切なクライアント対応形式に変換する必要がある場合に使用します。その場合でも、フロント コントローラ サーブレットまたはカスタム タグを使用して行う方が適切です。


スクリプトレットを置き換える方法は、コード/ロジックの目的によって完全に異なります。多くの場合、このコードは完全な Java クラスに配置されます。

  • リクエストされたページに関係なく、すべてのリクエストで同じJavaコードを呼び出したい場合(たとえば、ユーザーがログインしているかどうかを確認する場合)、フィルターそれに応じてコードを記述しますdoFilter()方法。例:

      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
          if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {
              ((HttpServletResponse) response).sendRedirect("login"); // Not logged in, redirect to login page.
          } else {
              chain.doFilter(request, response); // Logged in, just continue request.
          }
      }
    

    対象の JSP ページを適切にカバーするようにマップすると<url-pattern>、JSP ページ全体に同じコードをコピーして貼り付ける必要がなくなります。


  • GETリクエストを処理するJavaコードを呼び出したい場合、例えば、データベースからリストを事前にロードしてテーブルに表示する場合、必要に応じてクエリパラメータに基づいて、サーブレットそれに応じてコードを記述しますdoGet()方法。例:

      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          try {
              List<Product> products = productService.list(); // Obtain all products.
              request.setAttribute("products", products); // Store products in request scope.
              request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response); // Forward to JSP page to display them in a HTML table.
          } catch (SQLException e) {
              throw new ServletException("Retrieving products failed!", e);
          }
      }
    

    この方法だと例外の処理が簡単になります。DB は JSP レンダリングの最中ではなく、JSP が表示されるずっと前にアクセスされます。DB アクセスで例外がスローされるたびに応答を変更する可能性はあります。上記の例では、デフォルトのエラー 500 ページが表示されますが、これは in でカスタマイズでき<error-page>ますweb.xml


  • 送信されたHTMLフォームからデータを収集し、それを使ってビジネス処理(変換、検証、DBへの保存など)を行うなど、POSTリクエストを処理するJavaコードを呼び出したい場合は、サーブレットそれに応じてコードを記述しますdoPost()方法。例:

      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          String username = request.getParameter("username");
          String password = request.getParameter("password");
          User user = userService.find(username, password);
    
          if (user != null) {
              request.getSession().setAttribute("user", user); // Login user.
              response.sendRedirect("home"); // Redirect to home page.
          } else {
              request.setAttribute("message", "Unknown username/password. Please retry."); // Store error message in request scope.
              request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to JSP page to redisplay login form with error.
          }
      }
    

    この方法により、異なる結果ページの宛先を扱うのが簡単になります。エラーが発生した場合は検証エラーを含むフォームを再表示します(この特定の例では${message}エル)、または成功した場合は目的のターゲット ページに移動します。


  • 実行計画やリクエストとレスポンスの宛先を制御するためにJavaコードを呼び出したい場合は、サーブレットによるMVC のフロント コントローラー パターン例:

      protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          try {
              Action action = ActionFactory.getAction(request);
              String view = action.execute(request, response);
    
              if (view.equals(request.getPathInfo().substring(1)) {
                  request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
              } else {
                  response.sendRedirect(view);
              }
          } catch (Exception e) {
              throw new ServletException("Executing action failed.", e);
          }
      }
    

    または、MVCフレームワークを採用するだけですJSFスプリングMVCウィケットなどにより、カスタム サーブレットを必要とせずに、JSP/Facelets ページと JavaBean クラスだけが作成されます。


  • JSPページ内のフローを制御するためにJavaコードを呼び出したい場合は、次のような(既存の)フロー制御タグライブラリを取得する必要があります。JSTLコアたとえば、List<Product>表に表示すると次のようになります。

      <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
      ...
      <table>
          <c:forEach items="${products}" var="product">
              <tr>
                  <td>${product.name}</td>
                  <td>${product.description}</td>
                  <td>${product.price}</td>
              </tr>
          </c:forEach>
      </table>
    

    XML スタイルのタグは HTML 全体にうまく収まるため、さまざまな開き括弧と閉じ括弧 ( 「この閉じ括弧は一体どこに属しているのだろう?」 ) を含むスクリプトレットの束よりもコードが読みやすく (したがって保守性も向上します) なります。簡単な支援としては、次のコードを に追加して、スクリプトレットがまだ使用されている場合は常に例外をスローするように Web アプリケーションを構成することですweb.xml

      <jsp-config>
          <jsp-property-group>
              <url-pattern>*.jsp</url-pattern>
              <scripting-invalid>true</scripting-invalid>
          </jsp-property-group>
      </jsp-config>
    

    フェイスレット、JSPの後継であり、Java EEが提供するMVCフレームワークの一部である。JSFスクリプトレットを使用することはできませ。この方法では、自動的に「正しい方法」で作業を行うように強制されます。


  • JSP ページ内の「バックエンド」データにアクセスして表示するために Java コードを呼び出したい場合は、EL (式言語) を使用する必要があります${}。たとえば、送信された入力値を再表示するには、次のようにします。

      <input type="text" name="foo" value="${param.foo}" />
    

    ${param.foo}は の結果を表示しますrequest.getParameter("foo")


  • JSPページ内で直接Javaのユーティリティコード(通常はメソッド)を呼び出す場合はpublic static、EL関数として定義する必要があります。標準の関数タグライブラリJSTLでは、しかし関数を自分で簡単に作成することもできますfn:escapeXmlJSTLが次のようなことを防ぐのに役立つ例を示します。XSS攻撃

      <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
      ...
      <input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />
    

    XSS の感度は、Java/JSP/JSTL/EL などに特に関係するものではないことに注意してください。この問題は、開発するすべてのWeb アプリケーションで考慮する必要があります。スクリプトレットの問題は、少なくとも標準の Java API を使用する場合、組み込みの防止策が提供されないことです。JSP の後継である Facelets には、暗黙的な HTML エスケープが既に備わっているため、Facelets の XSS ホールについて心配する必要はありません。

参照:

おすすめ記事