35

私の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>

皆さんありがとう

4

7 に答える 7

42

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

これは、 JSTL(ドロップjstl-1.2.jarインするだけ/WEB-INF/libコア関数taglibを使用した1対1の書き直しです。

<%@ 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再利用のために式の結果を「キャッシュ」していたことと<base>、すべてのリンクにコンテキストパスを配置しないようにHTMLタグを使用していることに注意してください(Webページ内のすべての相対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>

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

実際の質問に関しては、webappのに次のエントリを追加することで、スクリプトレットを無効にすることができます(そしてスクリプトレットの使用に関するランタイムエラーが発生します) web.xml。監視されているスクリプトレットを見つけるのに役立つ場合があります。

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

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

于 2010-02-03T01:48:01.010 に答える
10

余談ですが<%= request.getContextPath() %>、あまり眉をひそめないスクリプトレットの使用は受け入れられますか?

これは不評な意見かもしれませんが、単純な条件文とテキストの挿入だけを行う場合、スクリプトレットの使用に多くの誤りを見つけることはできません。( ifに注意してください)

私はおそらくJSTLと式言語を使用しますが、ほとんどの場合、入力が少なくて済み、IDEサポートの方が優れている可能性があります(ただし、優れたJSP IDEでは、閉じ括弧などが欠落していることもあります)。

しかし、基本的に(「ロジックをテンプレートから除外する」のように)私は

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

${fn:contains(pageContext.request.requestURI, '/events/') 
于 2010-02-03T01:29:24.567 に答える
7

スクリプトレットは世界で最悪のものではありません。重要な考慮事項は、誰がコードを保守するのかを考えることです。Javaの経験があまりないWebデザイナーの場合は、タグライブラリを使用する方がよいでしょう。ただし、Java開発者が保守を行っている場合は、スクリプトレットを使用する方が簡単な場合があります。

タグライブラリとJSTLを使用することになった場合は、メンテナがタグライブラリを学習し、JSTLを知っていることを期待しています。一部の開発者は、これが必要なスキルであるか、すでに持っているスキルであるため、これで問題ありませんが、数か月ごとにJSPを処理するだけでよい一部の開発者にとっては、きれいに書かれた明確に書かれたスクリプトレットを使用する方がはるかに苦痛が少なくなります。 、おなじみのJava。

于 2010-02-03T03:05:12.957 に答える
6

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

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

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

私は個人的に 、JSPで開発するときに、TerenceParrによるテンプレートエンジンでの厳密なモデルビュー分離の実施に規定されているルールに従うのが好きです。このホワイトペーパーでは、テンプレートエンジンの目的(モデルとビューを分離する)、および優れたテンプレートエンジンの特性について説明しています。それはJSPをよく見て、それが良いテンプレートエンジンではない方法を指摘します。当然のことながら、JSPは基本的に強力すぎて、開発者がやりすぎを許します。このペーパーを読むことを強くお勧めします。これは、JSPの「良い」部分に限定するのに役立ちます。

その論文の1つのセクションだけを読んだ場合は、次の規則を含む第7章を読んでください。

  1. ビューは、モデルデータオブジェクトを直接変更することによって、または副作用を引き起こすモデルのメソッドを呼び出すことによって、モデルを変更することはできません。 つまり、テンプレートはモデルのデータにアクセスしてメソッドを呼び出すことができますが、そのような参照には副作用がない必要があります。このルールは、データ参照が順序に依存しない必要があるために部分的に発生します。セクション7.1を参照してください。
  2. 計算は将来変更される可能性があり、いずれの場合もモデルに適切にカプセル化する必要があるため、ビューは依存データ値に基づいて計算を実行できません。たとえば、ビューは本の販売価格を「$ price*.90」として計算できません。モデルから独立しているため、ビューはデータの意味について推測することはできません。
  3. ビューは依存データ値を比較できませんが、複数値データ値の有無や長さなどのデータのプロパティをテストできます。$ bloodPressure <120のようなテストは、医師が私たちにかかる最大収縮期血圧を下げ続けたいので、モデルに移動する必要があります。ビュー内の式は、$ bloodPressureOk!= nullなどのブール値をシミュレートする値の存在のテストに置き換える必要があります。テンプレート出力はモデルデータと計算を条件とすることができ、条件はモデルで計算する必要があります。 。負の値を赤にする単純なテストでさえ、モデルで計算する必要があります。適切な抽象化レベルは、通常、「部門xがお金を失っている」などのより高いレベルです。</ li>
  4. ビューはデータ型を想定できません。たとえば、ビューがデータ値が日付であると想定する場合、一部の型の想定は明らかですが、より微妙な型の想定が表示されます。テンプレートが$ userIDが整数であると想定する場合、プログラマーはこの値を非整数に変更できません。 -テンプレートを壊さずにモデル内の数値。このルールは、colorCode[$topic]や$name[$ ID]などの配列のインデックス付けを禁止します。モデルを保証できない限り、(静的または動的に)想定される引数タイプがあるため、ビューはさらに引数を持つメソッドを呼び出すことができません。メソッドは単にそれらをオブジェクトとして扱いました。グラフィックデザイナーはプログラマーではありません。それらがメソッドを呼び出し、何を渡すかを知っていることを期待するのは非現実的です。
  5. モデルのデータには、表示情報やレイアウト情報を含めることはできません。 モデルは、データ値を装ったビューに表示情報を渡すことはできません。これには、他のデータ値に適用するテンプレートの名前を渡さないことも含まれます。

ちなみに、テレンスは文字列テンプレートと呼ばれる独自のテンプレートエンジンを作成しました。これは、これらのルールを適用するのに非常に優れていると思われます。個人的な経験はありませんが、次のプロジェクトでチェックしたいと思います。

于 2010-02-03T02:30:02.410 に答える
3

タグライブラリを使用することから始めたいと思うかもしれません。標準のタグライブラリJSTLを使用して、スクリプトレットが必要な一般的なことのほとんどを実行できます。struts2フレームワークやapacheのように使用される、より豊富なタグライブラリは他にもたくさんあります。

例えば

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

ifステートメントを置き換えます。

于 2010-02-03T00:10:38.160 に答える
3

スクリプトレットの推奨される代替手段は、JSTL式言語です。ここに良い概要があります。次のようにtaglibを追加する必要があります。

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

例として、JSTLは、必要なものを提供する一連の暗黙的なオブジェクトを提供します。あなたが欲しいのはですpageContext.request

<%request.getRequestURI%>したがって、に置き換えることができます${pageContext.request.requestURI}

タグを使用して条件を実行でき<c:if>ます。

于 2010-02-03T00:11:47.567 に答える
2

Webフレームワークを使用する必要があります。または、少なくともいくつかの便利なtaglib。または、FreeMarkerのようなテンプレートエンジン。

広告フレームワーク:

JSPのコーディング方法がお好きなら、Struts2をお勧めします。

<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でコーディングする場合は、Apache Wicket(私のお気に入り)またはGoogleWebToolkitを試してください

于 2010-02-03T00:04:06.477 に答える