私はJava EEを初めて使用し、次の3行のようなものを知っています
<%= x+1 %>
<%= request.getParameter("name") %>
<%! counter++; %>
は昔ながらのコーディング方法であり、JSPバージョン2には、JSPファイルでJavaコードを回避する方法が存在します。誰かが代替のJSP 2行を教えてもらえますか?このテクニックは何と呼ばれていますか?
私はJava EEを初めて使用し、次の3行のようなものを知っています
<%= x+1 %>
<%= request.getParameter("name") %>
<%! counter++; %>
は昔ながらのコーディング方法であり、JSPバージョン2には、JSPファイルでJavaコードを回避する方法が存在します。誰かが代替のJSP 2行を教えてもらえますか?このテクニックは何と呼ばれていますか?
回答:
使用スクリプトレット(それらの<% %>
中のもの)JSPは、確かに非常にの誕生以来推奨されてタグライブラリ(のようなJSTL)とEL(式言語、それらの${}
2001年のもの)ウェイ・バック。
スクリプトレットの主な欠点は次のとおりです。
Sun Oracle自体も、JSPコーディング規約で、(タグ)クラスによって同じ機能が可能である場合は常にスクリプトレットの使用を避けることを推奨しています。いくつかの関連する引用がここにあります:
JSP 1.2仕様から、JSP標準タグライブラリ(JSTL)をWebアプリケーションで使用して、ページ内のJSPスクリプトレットの必要性を減らすことを強くお勧めします。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.
}
}
<url-pattern>
対象となるJSPページをカバーする適切な場所にマッピングする場合、JSPページ全体に同じコードをコピーアンドペーストする必要はありません。
いくつかの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ページが表示され、とにかく<error-page>
inでカスタマイズできますweb.xml
。
フォーム送信の処理など、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}
、ELを使用してフォームを再表示できます)、成功した場合は目的のターゲットページに移動します。
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);
}
}
または、JSF、Spring MVC、WicketなどのMVCフレームワークを採用するだけで、カスタムサーブレットを必要とせずに、JSP / FaceletsページとJavaBeanクラスのみを使用できます。
JSPページ内のフローを制御する Javaコードを呼び出す場合は、JSTLコアのような(既存の)フロー制御taglibを取得する必要があります。たとえば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>
すべてのHTMLの中にうまく収まるXMLスタイルのタグを使用すると、コードは、さまざまな開き括弧と閉じ括弧を備えた一連のスクリプトレットよりも読みやすく(したがって、保守性が向上します)(「この終了括弧はどこに属しているのですか?」)。次のコードをに追加することにより、スクリプトレットがまだ使用されている場合は常に例外をスローするようにWebアプリケーションを構成するのが簡単ですweb.xml
。
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
Facelets、ジャワEEの一部であるJSPの後継は、MVCフレームワーク提供JSFを、すでに、しない使用することができるスクリプトレットを。この方法では、自動的に「正しい方法」で物事を実行する必要があります。
JSPページ内の「バックエンド」データにアクセスして表示するためにJavaコードを呼び出す場合は、EL(式言語)を使用する必要があります${}
。たとえば、送信された入力値を再表示します。
<input type="text" name="foo" value="${param.foo}" />
の${param.foo}
結果が表示されますrequest.getParameter("foo")
。
いくつかのユーティリティ JavaコードをJSPページ(通常はpublic static
メソッド)で直接呼び出す場合は、それらをEL関数として定義する必要があります。JSTLには標準の関数taglibがありますが、関数を自分で簡単に作成することもできます。XSS 攻撃fn:escapeXml
を防ぐためにJSTL がどのように役立つかの例を次に示します。
<%@ 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ホールについて心配する必要はありません。
<% response.getWriter().flush(); %>
間</head>
や<body>
ウェブブラウザでのWebページの解析性能を向上させるためには。ただし、サーバー側の出力バッファーサイズが小さい場合(1〜2KB)、この使用はまったく無視できます。こちらの記事もご覧ください。
安全対策として:スクリプトレットを永久に無効にする
別の質問を検討している、あなたは、常に自分の中でスクリプトレットを無効にする必要がありますすることができweb.xml
、Webアプリケーション記述子。
開発者がスクリプトレットを追加するのを防ぐために、特に遅かれ早かれ概要を失う大企業では、私は常にそうするつもりです。web.xml
設定は次のようになります。
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
<%-- comment that i don't want in the final HTML --%>
。HTMLコメントではなく、これらのコメントを使用すると便利です。
<% %>
によりスクリプトレット、スクリプトレット式<%! %>
、およびスクリプトレット宣言がオフになり<%= %>
ます。つまり、ディレクティブ<%@ %>
とコメント<%-- --%>
は引き続き有効で使用可能であるため、コメントやインクルードを実行できます。
JSTLは、条件、ループ、セット、取得などのタグを提供します。次に例を示します。
<c:if test="${someAttribute == 'something'}">
...
</c:if>
JSTLはリクエスト属性で動作します-それらは、ほとんどの場合、JSPに転送するサーブレットによってリクエストで設定されます。
JSTLタグをEL式と一緒に使用して、JavaコードとHTMLコードの混在を回避できます。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<html>
<head>
</head>
<body>
<c:out value="${x + 1}" />
<c:out value="${param.name}" />
// and so on
</body>
</html>
経験上、JSPにはいくつかの欠点があることが示されています。その1つは、マークアップと実際のコードの混合を避けるのが難しいことです。
可能であれば、必要な作業に特化したテクノロジーの使用を検討してください。Java EE 6にはJSF 2.0があり、この方法でJava BeanをJSFページと接着するなど、多くの優れた機能を提供します#{bean.method(argument)}
。
JSPでのJavaコーディングの欠点を単に回避したい場合は、スクリプトレットを使用しても可能です。JSPで最小限のJavaを使用し、JSPページで計算とロジックをほとんど使用しないように、いくつかの規則に従ってください。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%//instantiate a JSP controller
MyController clr = new MyController(request, response);
//process action if any
clr.process(request);
//process page forwaring if necessary
//do all variable assignment here
String showMe = clr.getShowMe();%>
<html>
<head>
</head>
<body>
<form name="frm1">
<p><%= showMe %>
<p><% for(String str : clr.listOfStrings()) { %>
<p><%= str %><% } %>
// and so on
</form>
</body>
</html>
JSTLを使用して独自のタグをカスタマイズおよび作成する方法を学ぶ
ELであることに注意悪(実行時例外、リファクタリング)
Wicketのは、あまりにも(パフォーマンス、小さなアプリケーションや簡単なビュー階層のためtoilsome)悪かもしれ
から例java2s、
これは、Webアプリケーションのweb.xmlに追加する必要があります
<taglib>
<taglib-uri>/java2s</taglib-uri>
<taglib-location>/WEB-INF/java2s.tld</taglib-location>
</taglib>
/ WEB-INF /にFile:java2s.tldを作成します。
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<!-- a tab library descriptor -->
<taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>Java2s Simple Tags</short-name>
<!-- this tag manipulates its body content by converting it to upper case
-->
<tag>
<name>bodyContentTag</name>
<tag-class>com.java2s.BodyContentTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>howMany</name>
</attribute>
</tag>
</taglib>
次のコードをWEB-INF \ classes \ com \ java2sにコンパイルします
package com.java2s;
import java.io.IOException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class BodyContentTag extends BodyTagSupport{
private int iterations, howMany;
public void setHowMany(int i){
this.howMany = i;
}
public void setBodyContent(BodyContent bc){
super.setBodyContent(bc);
System.out.println("BodyContent = '" + bc.getString() + "'");
}
public int doAfterBody(){
try{
BodyContent bodyContent = super.getBodyContent();
String bodyString = bodyContent.getString();
JspWriter out = bodyContent.getEnclosingWriter();
if ( iterations % 2 == 0 )
out.print(bodyString.toLowerCase());
else
out.print(bodyString.toUpperCase());
iterations++;
bodyContent.clear(); // empty buffer for next evaluation
}
catch (IOException e) {
System.out.println("Error in BodyContentTag.doAfterBody()" + e.getMessage());
e.printStackTrace();
} // end of catch
int retValue = SKIP_BODY;
if ( iterations < howMany )
retValue = EVAL_BODY_AGAIN;
return retValue;
}
}
サーバーを起動し、bodyContent.jspをブラウザーにロードします
<%@ taglib uri="/java2s" prefix="java2s" %>
<html>
<head>
<title>A custom tag: body content</title>
</head>
<body>
This page uses a custom tag manipulates its body content.Here is its output:
<ol>
<java2s:bodyContentTag howMany="3">
<li>java2s.com</li>
</java2s:bodyContentTag>
</ol>
</body>
</html>
あなたは良い質問をし、良い答えを得ましたが、JSPを取り除くことをお勧めします。それは最終的には死ぬ時代遅れの技術です。テンプレートエンジンのような最新のアプローチを使用します。ビジネスレイヤーとプレゼンテーションレイヤーが非常に明確に分離され、テンプレートにJavaコードがないため、ほとんどの場合WYSIWYGを利用して、Webプレゼンテーション編集ソフトウェアから直接テンプレートを生成できます。
また、フィルターや前処理と後処理は絶対に避けてください。そうしないと、変数がどこで値を取得するかが常にわからないため、サポートやデバッグの問題に対処できます。
どんなに避けようとも、他の開発者と共同で作業する場合、一部の開発者はスクリプトレットを優先して、邪悪なコードをプロジェクトに挿入します。したがって、スクリプトレットのコードを削減したい場合は、最初のサインでプロジェクトを設定することが非常に重要です。これを乗り越えるテクニックはいくつかあります(他のフレームワークを含む)。ただし、純粋なJSPを使用する場合は、JSTLタグファイルを使用します。これの良い点は、プロジェクトのマスターページを設定して、他のページがマスターページを継承できることです。
次のコンテンツを含むWEB-INF / tagsの下にbase.tagというマスターページを作成します。
<%@tag description="Overall Page template" pageEncoding="UTF-8"%> <%@attribute name="title" fragment="true" %> <html> <head> <title> <jsp:invoke fragment="title"></jsp:invoke> </title> </head> <body> <div id="page-header"> .... </div> <div id="page-body"> <jsp:doBody/> </div> <div id="page-footer"> ..... </div> </body> </html>
このページでは、「タイトル」というフラグメントを作成しました。これにより、子ページで、マスターページのこの場所にさらにコードを挿入できます。また、タグ<jsp:doBody/>
は子ページのコンテンツに置き換えられます
WebContentフォルダーに子ページ(child.jsp)を作成します。
<%@ taglib prefix="t" tagdir="/WEB-INF/tags" %> <t:base> <jsp:attribute name="title"> <bean:message key="hello.world" /> </jsp:attribute> <jsp:body> [Put your content of the child here] </jsp:body> </t:base>
<t:base>
は、使用するマスターページ(現時点ではbase.tag)を指定するために使用されます。<jsp:body>
ここのタグ内のすべてのコンテンツが<jsp:doBody/>
マスターページのを置き換えます。子ページには任意のタグlibを含めることもでき、通常は他のタグと同じように使用できます。ただし、ここでスクリプトレットコード(<%= request.getParameter("name") %>
...)を使用してこのページを実行しようとすると、が表示されますJasperException because Scripting elements ( <%!, <jsp:declaration, <%=, <jsp:expression, <%, <jsp:scriptlet ) are disallowed here
。したがって、他の人が邪悪なコードをjspファイルに含める方法はありません
コントローラからこのページを呼び出す:
コントローラーから簡単にchild.jspファイルを呼び出すことができます。これはStrutsフレームワークでもうまく機能します
JSTL Tag libraries
JSPで使用すると、完璧に動作します。
誰かが実際に複数の言語でのプログラミングに反対している場合は、GWTをお勧めします。理論的には、すべてのJS要素とHTML要素を回避できます。GoogleToolkitはすべてのクライアントと共有コードをJSに変換するため、問題は発生しません。あなたは他の言語でコーディングせずにウェブサービスを持っています。拡張機能(smartGWTまたはVaadin)によって提供されるため、どこからでもデフォルトのCSSを使用できます。何十ものアノテーションを学ぶ必要はありません。
もちろん、必要に応じて、コードの奥深くにハックしてJSを挿入し、HTMLページを充実させることができますが、実際には、必要に応じてそれを回避することができ、他のフレームワークで作成されたとおりの結果が得られます。私は試してみる価値があると言い、基本的なGWTは十分に文書化されています。
そしてもちろん、多くの仲間のプログラマーはここに他のいくつかの解決策を説明または推奨しました。GWTは、Webパーツを実際に処理したり最小限にしたりしたくない人のためのものです。
Pythonの世界からのすばらしいアイデアは、テンプレート属性言語です。TALはZope(したがって「Zopeページテンプレート」、ZPTとも呼ばれます)によって導入された標準であり、PHP、XSLT、Javaでも実装されています(Python / ZopeおよびPHPインカネーションを使用しました)。このテンプレート言語のクラスでは、上記の例は次のようになります。
<table>
<tr tal:repeat="product products">
<td tal:content="product/name">Example product</td>
<td tal:content="product/description">A nice description</td>
<td tal:content="product/price">1.23</td>
</tr>
</table>
コードは、通常のHTML(またはXHTML)に加えて、XML名前空間のいくつかの特別な属性に似ています。ブラウザで表示でき、設計者が安全に微調整できます。マクロとi18nのサポートもあります:
<h1 i18n:translate="">Our special offers</h1>
<table>
<tr tal:repeat="product products">
<td tal:content="product/name"
i18n:translate="">Example product</td>
<td tal:content="product/description"
i18n:translate="">A nice description</td>
<td tal:content="product/price">1.23</td>
</tr>
</table>
コンテンツの翻訳が利用可能な場合、それらが使用されます。
ただし、Javaの実装についてはあまり知りません。
ui:xxx
Facelts VDLのタグも参照してください。
tal:replace="structure (expression)"
いつも属性を使用するのと同じです。
JSPでスクリプトレットを使用することはお勧めできません。
代わりに、以下を使用できます。
以下を参照してください。
確かに、<%! counter++; %>
イベントプロデューサー/コンシューマーアーキテクチャーに置き換えてください。カウンターをインクリメントする必要があることをビジネスレイヤーに通知すると、カウンターはそれに応じて反応し、プレゼンターに通知してビューを更新します。多くのデータベーストランザクションが関係しています。将来的には、カウンターの新しい値と古い値を知っておく必要があるためです。明らかに層が完全に切り離されているため、シリアライゼーションが関係しています。RMI、IIOP、SOAPを介してカウンターをインクリメントできます。ただし、HTMLのみが必要であり、実装する必要はありません。これは、ありふれたケースであるためです。新しい目標は、新しい光沢のあるE7、64GB RAMサーバーで1秒あたり250の増分に到達することです。
私はプログラミングに20年以上携わっていますが、ほとんどのプロジェクトはセクステットの前に失敗します。他のプロジェクトは、機能性のみに関心がある人々によって運営され、非常に成功しました。また、プロジェクトの早い段階で実装された硬いオブジェクト構造は、仕様の大幅な変更(別名アジャイル)にコードを適合させることができなくなります。
そのため、プロジェクトの初期または特に必要がない場合に、「レイヤー」または冗長データ構造を定義するアクティビティを先延ばしと見なします。
JSPファイルでJavaコードを回避する方法
式言語(EL)に加えて、JSTLのようなタブライブラリタグを使用できます。しかし、ELはJSPではうまく機能しません。そのため、JSPを完全に削除し、Faceletsを使用する方が良いでしょう。
Faceletsは、JSF(Java Server Faces)用に設計された最初の非JSPページ宣言言語であり、JSP開発者に、JSPと比較してよりシンプルで強力なプログラミングモデルを提供します。Webアプリケーション開発用のJSPで発生するさまざまな問題を解決します。
スクリプトレットの使用は非常に古い方法であり、推奨されません。JSPページに何かを直接出力する場合は 、JSTLとともに式言語(EL)を使用します。
Velocity、Freemarker、Thymeleafなどのテンプレートエンジンを使用するなど、他のオプションもあります。しかし、ELとJSTLでプレーンJSPを使用すると、ほとんどの場合私の目的に役立ち、初心者にとっても最も簡単なようです。
また、ビューレイヤーでビジネスロジックを実行することはベストプラクティスではないことに注意してください。サービスレイヤーでビジネスロジックを実行し、コントローラーを介して出力結果をビューに渡す必要があります。
JSP 2.0には「タグファイル」と呼ばれる機能があり、外部java
コードなしでタグを記述できますtld
。あなたは、作成する必要がある.tag
ファイルをして、それを入れてWEB-INF\tags
も、あなたのタグをパッケージ化するためのディレクトリ構造を作成することができます。
例えば:
/WEB-INF/tags/html/label.tag
<%@tag description="Rensders a label with required css class" pageEncoding="UTF-8"%>
<%@attribute name="name" required="true" description="The label"%>
<label class="control-label control-default" id="${name}Label">${name}</label>
好きに使う
<%@ taglib prefix="h" tagdir="/WEB-INF/tags/html"%>
<h:label name="customer name" />
また、タグ本体が簡単に読み取れます
/WEB-INF/tags/html/bold.tag
<%@tag description="Bold tag" pageEncoding="UTF-8"%>
<b>
<jsp:doBody/>
</b>
これを使って
<%@ taglib prefix="h" tagdir="/WEB-INF/tags/bold"%>
<h:bold>Make me bold</h:bold>
サンプルは非常に単純ですが、ここでは多くの複雑なタスクを実行できます。あなたが他のタグを使用することができます考慮してください。(例JSTL
のようなタグを制御しているif/forEcah/chosen
ようなテキスト操作format/contains/uppercase
、あるいはSQLタグをselect/update
例えば、すべての種類のパラメータを渡す、) Hashmap
、アクセスsession
、request
、...あなたのタグファイルで、あまりにも。
タグファイル は、JSPファイルのようにタグを変更するときにサーバーを再起動する必要がなかったため、簡単に開発できます。これにより、開発が容易になります。
優れたタグがたくさんあるStruts 2のようなフレームワークを使用していても、独自のタグを使用するとコードを大幅に削減できる場合があります。タグパラメータをStrutsに渡して、フレームワークタグをカスタマイズできます。
タグを使用すると、Javaを回避するだけでなく、HTMLコードを最小限に抑えることができます。私は自分のページでコードの重複が始まるのを見てすぐに、HTMLコードを確認してタグを作成しようとしています。
(JSPコードでJavaを使用することになったとしても、そうではないと思いますが、そのコードをタグにカプセル化できます)