JSP ページでスクリプトレットの使用を避けるにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/2188706

  •  25-09-2019
  •  | 
  •  

質問

スクリプトレット (<%= ... を使用するとよいと言われました)%>) を JSP ページに含めるのは、あまり良いアイデアではありません。

もう少し Java/JSP の経験がある人が、このコードをより「ベスト プラクティス」になるように変更する方法について、それが何であれ、いくつかのヒントを教えてもらえますか?

この JSP は、実際には私のサイトメッシュのメイン デコレータ ページです。基本的に私の Web デザインにはタブ ストリップとサブメニューがあり、現在のリクエスト URI を見て、何らかの方法で現在のタブを強調表示し、正しいサブメニューを表示したいと考えています。

<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>

<html>
<head>
  <title>My Events - <decorator:title /></title>
  <link href="<%= request.getContextPath() %>/assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>

<div class="tabs">
  <a 
    <%= request.getRequestURI().contains("/events/") ? "class='selected'" : "" %>
    href='<%= request.getContextPath() %>/events/Listing.action'>Events</a>
  <a 
    <%= request.getRequestURI().contains("/people/") ? "class='selected'" : "" %>
    href='<%= request.getContextPath() %>/people/Listing.action'>People</a>
</div>

<div class="submenu">
  <% if(request.getRequestURI().contains("/events/")) { %>
    <a href="Listing.action">List of Events</a>
    |<a href="New.action">New Event</a>
  <% } %>
  <% if(request.getRequestURI().contains("/people/")) { %>
    <a href="Listing.action">List of People</a>
    |<a href="New.action">New Person</a>
  <% } %>  
  &nbsp;
</div>

<div class="body">
  <decorator:body />
</div>

</body>
</html>

皆さんありがとう

役に立ちましたか?

解決

実際に完全に実行できることを自分の目で確認すると、さらに役立つと思います それなし スクリプトレット。

これは他の人の助けを借りて 1 対 1 で書き直したものです JSTL (ただ落とすだけ jstl-1.2.jar/WEB-INF/lib) そして 機能 タグライブラリ:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<html>
<head>
  <title>My Events - <decorator:title /></title>
  <link href="${pageContext.request.contextPath}/assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>

<div class="tabs">
  <a 
    ${fn:contains(pageContext.request.requestURI, '/events/') ? 'class="selected"' : ''}
    href="${pageContext.request.contextPath}/events/Listing.action">Events</a>
  <a 
    ${fn:contains(pageContext.request.requestURI, '/people/') ? 'class="selected"' : ''}
    href="${pageContext.request.contextPath}/people/Listing.action">People</a>
</div>

<div class="submenu">
  <c:if test="${fn:contains(pageContext.request.requestURI, '/events/')}">
    <a href="Listing.action">List of Events</a>
    |<a href="New.action">New Event</a>
  </c:if>
  <c:if test="${fn:contains(pageContext.request.requestURI, '/people/')}">
    <a href="Listing.action">List of People</a>
    |<a href="New.action">New Person</a>
  </c:if>
  &nbsp;
</div>

これは、より最適化された書き直しです。使用したことに注意してください。 c:set 再利用のために式の結果を「キャッシュ」し、HTML を使用する <base> タグを使用して、すべてのリンクにコンテキスト パスを配置しないようにします (Web ページ内のすべての相対 URL を、先頭のスラッシュなしで相対 URL にするだけです)。

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<c:set var="isEvents" value="${fn:contains(pageContext.request.requestURI, '/events/')}" />
<c:set var="isPeople" value="${fn:contains(pageContext.request.requestURI, '/people/')}" />

<html>
<head>
  <title>My Events - <decorator:title /></title>
  <base href="${pageContext.request.contextPath}">
  <link href="assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>

<div class="tabs">
  <a ${isEvents ? 'class="selected"' : ''} href="events/Listing.action">Events</a>
  <a ${isPeople ? 'class="selected"' : ''} href="people/Listing.action">People</a>
</div>

<div class="submenu">
  <c:if test="${isEvents}">
    <a href="Listing.action">List of Events</a>|<a href="New.action">New Event</a>
  </c:if>
  <c:if test="${isPeople}">
    <a href="Listing.action">List of People</a>|<a href="New.action">New Person</a>
  </c:if>
  &nbsp;
</div>

次のような「ハードコードされた」値をすべて収集すると、実際にはさらに最適化できます。 events そして people でテキストをリンクします Map アプリケーションスコープ内で各JSTLの下で使用します <c:forEach> タブを表示します。

あなたに関しては 実際の 質問、できます 無効にする Web アプリの web.xml. 。監視されているスクリプトレットを特定するのに役立つ場合があります。

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

EL について詳しくは、 Java EE チュートリアル パート II 第 5 章. 。暗黙的な EL オブジェクト (次のような) ${pageContext} 説明されています ここ. 。JSTL について詳しくは、 Java EE チュートリアル パート II 第 7 章. 。JSTL と EL は別のものであることに注意してください。JSTLは、 標準タグライブラリ EL はバックエンド データにプログラム的にアクセスできるようにするだけです。通常は JSTL などのタグライブラリで使用されますが、テンプレート テキストでスタンドアロンで使用することもできます。

他のヒント

  

はさておき、そんなに?

に眉をひそめていないスクリプトレットの<%= request.getContextPath() %>許容使用されたよう

このは不評の意見かもしれないが、あなたが行うすべては、単純な条件文とテキスト挿入されている場合、私はスクリプトレットの使用に多くの障害を見つけることができません。

(の場合はを注意してください)

私はおそらくJSTLと式言語を使用したいが、それはあまりタイピングすることができ、およびIDEのサポートが良いかもしれ(良いJSP IDEはまた、そのような閉じ括弧とスタッフが不足して見つけることができます)主な理由ます。

しかし、基本的に、私は間の違いを見ることができない(「テンプレートのうちキープロジック」のように)

<% if(request.getRequestURI().contains("/events/")) { %>

${fn:contains(pageContext.request.requestURI, '/events/') 

これはあなたの質問に対する直接の答えではありません(そして、すでにいくつかの良い答えがあるので、これに追加するつもりはありません)が、あなたは次のように述べました:

もう少しjava/jspの経験がある人は、このコードを変更する方法についていくつかの指針を教えてください。 その「ベストプラクティス」、それが何であれ?

私の意見では、JSP に関するベスト プラクティスは、厳密に JSP として使用されるべきであるということです。 テンプレートエンジン, 、そしてそれ以上はありません(つまり、そこにはビジネスロジックはありません)。多くの人が指摘しているように、JSTL を使用すると、そこに到達するのに確かに役立ちますが、JSTL を使用しても、JSP で多くのことを行うのは簡単です。

私は個人的には、に定められたルールに従いたいと思っています テンプレート エンジンでのモデルとビューの厳密な分離の強制 JSP で開発する際の Terence Parr による。この論文では、テンプレート エンジンの目的 (モデルとビューの分離) と、優れたテンプレート エンジンの特徴について述べています。JSP を詳しく調べ、JSP が適切なテンプレート エンジンではない点を指摘しています。当然のことですが、JSP は基本的に強力すぎるため、開発者はあまりにも多くのことを行うことができます。この文書を読むことを強くお勧めします。これは、JSP の「良い」部分に限定するのに役立ちます。

この論文の 1 つのセクションだけを読んだ場合は、次の規則が含まれる第 7 章を​​読んでください。

  1. ビューは、モデルデータオブジェクトを直接変更するか、副作用を引き起こすモデルにメソッドを呼び出すことでモデルを変更することはできません。つまり、テンプレートはモデルからデータにアクセスしてメソッドを呼び出すことができますが、そのような参照は副作用がない必要があります。このルールは、データ参照が順序感受性でなければならないため、部分的に発生します。セクション 7.1 を参照してください。
  2. ビューは、従属データ値に計算を実行できません 計算は将来変化する可能性があり、いずれにせよモデルにきちんとカプセル化されるべきであるためです。たとえば、このビューでは、帳簿販売の価格を「$ spric*.90」として計算することはできません。モデルとは独立しているため、このビューはデータの意味について仮定することはできません。
  3. ビューは依存するデータ値を比較できません, 、しかし、多値データ値の存在/不在、長さなどのデータのプロパティをテストできます。$ Bloodpressure <120などのテストは、医師が私たちへの最大収縮期の圧力を軽減し続けることを好むため、モデルに移動する必要があります。ビュー内の式は、$ BloodPressureokなどのブール値をシミュレートする値の存在のテストに置き換える必要があります! 。負の値を赤にする簡単なテストでさえ、モデルで計算する必要があります。適切なレベルの抽象化は、「部門Xがお金を失っている」などのより高いレベルのものです。
  4. ビューではデータ型を仮定することはできません。 いくつかのタイプの仮定は、ビューがデータ値が日付であると想定している場合、より微妙なタイプの仮定を想定している場合に明らかです。テンプレートが$ useridが整数であると想定している場合、プログラマーはこの値をテンプレートを破ることなくモデルの非数字に変えることはできません。このルールは、ColorCode [$ topic]や$ name [$ id]などのアレイインデックスを禁止しています。ビューは、モデルを保証できない限り、想定される引数タイプがあります。方法は、単にそれらをオブジェクトとして扱っただけです。グラフィックスデザイナーはプログラマーではありません。彼らが方法を呼び出して何を渡すべきかを知ることを期待することは非現実的です。
  5. モデルのデータには、表示情報やレイアウト情報が含まれていてはなりません。モデルは、データ値を偽装したビューに表示情報を渡すことはできません。これには、他のデータ値に適用するためにテンプレートの名前を渡さないことが含まれます。

ちなみに、Terence は独自のテンプレート エンジンを作成しました。 文字列テンプレート おそらくこれらのルールを強制するのに非常に優れた機能を果たします。私には個人的な経験はありませんが、次のプロジェクトでぜひチェックしてみたいと思っています。

スクリプトレットは、世界で最悪のものではありません。重要な考慮事項は、コードを維持しようとしている人について考えることです。多くのJavaの経験を持っていないそのWebデザイナー場合は、おそらくより良いタグライブラリと一緒に行くオフになっています。 Java開発者がメンテナンスを行っている場合は、スクリプトレットで行くことに彼らの方が簡単かもしれません。

あなたはタグライブラリとJSTLを使用して終了した場合、

、あなたはまた、タグライブラリを学び、JSTLを知っているにメンテナを期待しています。それは彼らが望むスキルですか、すでに持っているが、JSPのみで数カ月ごとかそこらを対処しなければならないいくつかの開発者のために、それは素敵で書か明確に書かれたスクリプトレットとはるかに少ない痛みを伴う作業になることができますように、一部の開発者は、この罰金となります、よく知られたJavaます。

あなたはタグライブラリを使用して起動することもできます。あなたがいることを共通のものの大半を行うには、標準タグライブラリ JSTL に使用することができます以下のためのスクリプトレットを必要としています。 Struts2のフレームワークの中でまたはApacheからのように使用されている他の多くの豊かなタグライブラリがあります。

例えばます。

  <c:if test="${your condition}">
       Your Content
  </c:if>

あなたのif文を置き換えます。

スクリプトレットの好ましい代替は、JSTL表現言語です。 ここをの良い概観。あなたがそうのようなタグライブラリを追加する必要があります:

<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c' %>
例として、JSTLはあなたが必要なものを与える暗黙オブジェクトの束を提供します。あなたが望む一つはpageContext.requestです。

あなたは<%request.getRequestURI%>${pageContext.request.requestURI}を交換できるようにます。

あなたは<c:if>タグを使用して条件文を行うことができます。

何らかの Web フレームワークを使用する必要があります。または少なくとも便利なタグリブ。または次のようなテンプレートエンジン フリーマーカー.

広告フレームワーク:

JSP のコーディング方法が好きなら、これをお勧めします ストラット2.

<s:if test="%{false}">
    <div>Will Not Be Executed</div>
</s:if>
<s:elseif test="%{true}">
    <div>Will Be Executed</div>
</s:elseif>
<s:else>
    <div>Will Not Be Executed</div>
</s:else>

次にコンポーネント指向です JSF.

OOP とすべてを Java でコーディングするのが好きなら、試してみてください。 アパッチウィケット (私のお気に入り) または Google ウェブ ツールキット.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top