JSPの補足:EL式とJSTLタグ

ディレクティブ

ディレクティブの役割は、JSPの翻訳エンジンにどのように動作するかを指示することです(現在のJSP翻訳エンジンに、JSPファイルをどのように翻訳するかを指示します)。

ディレクティブにはどのようなものがありますか?

  • includeディレクティブ:静的包含をJSP内で行います。現在はほとんど使用されません。(ここでは説明しません)
  • taglibディレクティブ:タグライブラリを導入するディレクティブです。これは**JSTLタグライブラリ**の学習時に扱います。今は気にしないでください。
  • pageディレクティブ:現在、pageディレクティブを重点的に学習します。

ディレクティブの使用構文は何ですか?

<%@ディレクティブ名 属性名=属性値 属性名=属性値 ...%>

pageディレクティブにはどのような一般的な属性がありますか?

<%@page session="true|false" %>
trueはJSPの組み込みオブジェクトsessionを有効にし、sessionオブジェクトが存在しない場合は作成します。
設定されていない場合、デフォルト値はsession="true"です。
session="false"は組み込みオブジェクトsessionを起動しません。現在のJSPページではsessionオブジェクトを使用できません。
<%@page contentType="text/json" %>
<%@page contentType="text/html" %>
contentType属性は応答のコンテンツタイプを設定するために使用されます。
<%@page contentType="text/json;charset=UTF-8" %>
同時に文字セットを設定することもできます。
<%@page pageEncoding="UTF-8" %>
pageEncoding="UTF-8"は、応答時に使用する文字セットを設定します。
<%@page import="java.util.List, java.util.Date, java.util.ArrayList" %>
<%@page import="java.util.*" %>
import文、パッケージのインポート。
<%@page errorPage="/error.jsp" %>
現在のページで例外が発生した後、error.jspページにジャンプします。
errorPage属性は、エラーが発生した後のジャンプ先を指定するために使用されます。
<%@page isErrorPage="true" %>
エラーページでは、JSPの9つの組み込みオブジェクトの1つであるexceptionを有効にできます(直前に発生した例外オブジェクト)。
デフォルト値はfalseです。
exception.printStackTrace(); // コンソールにエラー情報を出力します

9つの組み込みオブジェクト

  • jakarta.servlet.jsp.PageContext pageContext ページスコープ
  • jakarta.servlet.http.HttpServletRequest request リクエストスコープ
  • jakarta.servlet.http.HttpSession session セッションスコープ
  • jakarta.servlet.ServletContext application アプリケーションスコープ

pageContext < request < session < application
上記の4つのスコープには、setAttribute、getAttribute、removeAttributeメソッドがあります。
上記のスコープの使用原則:可能な限り小さいスコープを使用します。

  • java.lang.Throwable exception
  • jakarta.servlet.ServletConfig config
  • java.lang.Object page (実際にはthis、現在のservletオブジェクト)
  • jakarta.servlet.jsp.JspWriter out (出力を担当)
  • jakarta.servlet.http.HttpServletResponse response (応答を担当)
  1. PageContext(ページスコープ):ページ内のすべてのスコープへのアクセスを提供し、リクエスト(request)、セッション(session)、アプリケーション(application)スコープを含みます。
Object attribute = pageContext.getAttribute("attributeName");
pageContext.setAttribute("attributeName", attributeValue);
  1. HttpServletRequest(リクエストスコープ):クライアントから送信されたHTTPリクエストの情報をカプセル化し、リクエストパラメータやリクエストヘッダーの取得に使用できます。
String param = request.getParameter("param");
String header = request.getHeader("User-Agent");
  1. HttpSession(セッションスコープ):ユーザーのセッション状態を追跡するために使用され、セッション固有のデータを保存および取得できます。
HttpSession session = request.getSession();
session.setAttribute("username", "Alice");
String username = (String) session.getAttribute("username");
  1. ServletContext(アプリケーションスコープ):Webアプリケーションの全体のコンテキスト環境を表し、アプリケーション全体の初期化パラメータや共有データの取得に使用できます。
ServletContext application = request.getServletContext();
String initParam = application.getInitParameter("initParam");
application.setAttribute("attributeName", attributeValue);
  1. Throwable(例外オブジェクト):通常、例外処理で使用され、例外をキャッチして処理します。
try {
    // コードブロック
} catch (Throwable exception) {
    // 例外処理ロジック
}
  1. ServletConfig(Servlet設定):単一のServletの設定情報を表し、そのServletの初期化パラメータを取得できます。
String initParam = config.getInitParameter("initParam");
  1. Object(ページオブジェクト):JSPページでは、`page`は現在生成されたServletクラスのインスタンスオブジェクトを指します。
  1. JspWriter(出力ストリームオブジェクト):JSPページでの出力操作に使用され、コンテンツをクライアントに送信します。
out.println("Hello, JSP!");
  1. HttpServletResponse(HTTP応答):HTTP応答を生成するために使用され、ステータスコードの設定、応答ヘッダーの設定、クライアントへの応答コンテンツの送信などが含まれます。
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<h1>Hello, Servlet!</h1>");

EL式(式言語)

EL式は何のためにあるのですか?

  • Expression Language(式言語)
  • EL式はJSPのJavaコードに代わるもので、JSPファイル内のプログラムをよりクリーンで美しく見せるために使用できます。
  • JSPに様々なJavaコード(例:<% javaコード %>、<%= %>など)が混在すると、JSPファイルが乱雑で見づらく、保守が困難になります。そのため、後のEL式が登場しました。
  • EL式はJSP構文の一部と見なすことができます。EL式はJSPに属します。

EL式がJSPに登場する主な目的は:

  • 特定のスコープからデータを取得し、それを文字列に変換してブラウザに出力すること。これがEL式の効果です。

3つの主な効果:

  • 第一の効果:特定のスコープからデータを取得します。
    • 4つのスコープ:
      • pageContext
      • request
      • session
      • application
  • 第二の効果:取得したデータを文字列に変換します。
    • Javaオブジェクトの場合、JavaオブジェクトのtoStringメソッドが自動的に呼び出され、文字列に変換されます。
  • 第三の効果:文字列をブラウザに出力します。
    • <%= %>と同じで、ブラウザに出力されます。

EL式の基本的な構文形式:

${式}

EL式の使用:

<%
	// Productオブジェクトを作成
	Product product = new Product();
	product.setName("Super Gadget");
	product.setPrice(999.99);
	product.setInStock(true);

	// Productオブジェクトを特定のスコープに保存します。必ず保存してください。なぜなら、EL式はデータを特定の範囲からのみ取得できるからです。
	// データは必ず4つのスコープのいずれかに保存する必要があります。
	request.setAttribute("productInfo", product);
%>

<%--EL式を使用して取得--%>
${productInfo.name} は現在利用可能です。
<%=request.getAttribute("productInfo")%>と同等です。

${productInfo} の内部動作はどのように行われますか?

スコープからデータを取得し、productオブジェクトを取得し、そのtoStringメソッドを呼び出して文字列に変換し、ブラウザに出力します。

${productInfo.name} の構文は、実際には底層のgetName()メソッドを呼び出しています。
注意:対応するgetメソッドがない場合、500エラーが発生します。

面接問題:${abc} と ${"abc"} の違いは何ですか?

${abc}は、特定のスコープからデータを取得することを意味し、取得されるデータの名前は"abc"です。以前にこのようなコードがあったはずです: スコープ.setAttribute("abc", オブジェクト);
${"abc"}は、"abc"を通常の文字列としてブラウザに出力することを意味します。スコープからデータを取得しません。

注意点:

  • EL式は小さいスコープから優先してデータを読み取ります。
    範囲の大きさの関係:pageContext < request < session < application
  • EL式には4つの暗黙のスコープがあります:
    pageScope は pageContextスコープに対応します。
    requestScope は requestスコープに対応します。
    sessionScope は sessionスコープに対応します。
    applicationScope は applicationスコープに対応します。
  • EL式はnullを事前に処理します。nullの場合、ブラウザには空の文字列が出力されます。
  • EL式でデータを取得するには2つの形式があります:
    - 第一:. (この方法が最もよく使用されます)
    - 第二:[ ] (スコープに保存する際にnameに特殊文字が含まれている場合、[ ]を使用できます)
    例:request.setAttribute("abc.def", "zhangsan");
    ${requestScope.abc.def} このように値を取得することはできません。
    このようにする必要があります:${requestScope["abc.def"]}
  • Mapコレクションからデータを取得する方法をマスターしてください:
    ${map.key}
  • 配列やListコレクションからデータを取得する方法をマスターしてください:
    ${配列[0]}
    ${list[0]}
  • pageディレクティブには、EL式を無視する属性があります:
    <%@page contentType="text/html;charset=UTF-8" isELIgnored="true" %>
    isELIgnored="true" はEL式を無視することを意味します。
    isELIgnored="false" はEL式を無視しないことを意味します。(これはデフォルト値です)
    isELIgnored="true" これはグローバルな制御です。
    バックスラッシュを使用してローカルな制御を行うこともできます:
    \${username}
  • アプリケーションのルートをEL式で取得する:
    ${pageContext.request.contextPath}
  • EL式の他の暗黙のオブジェクト:
    pageContext
    param
    paramValues
    initParam

requestオブジェクトがない場合、取得するにはpageContextオブジェクトのgetRequest()メソッドを介する必要があります。

  • pageContext(ページコンテキスト):JSP(JavaServer Pages)では、`pageContext`はオブジェクトであり、現在のJSPページ環境へのアクセスを提供するメソッドを提供します。リクエストと応答オブジェクトの取得、属性の保存と共有、セッションの操作などに使用できます。
  • param(パラメータ):Servletでは、`param`は通常、HTTPリクエストのパラメータ情報を指します。クライアントがサーバーにHTTPリクエストを送信する際、パラメータを使用してデータを渡すことができます。Servletでは、`request.getParameter(name)`メソッドを使用して特定の名前のパラメータ値を取得できます。
  • paramValues(パラメータ値):同じ名前の複数のパラメータがある場合、`paramValues`は、これらのパラメータのすべての値を含む配列です。Servletでは、`request.getParameterValues(name)`メソッドを使用して同じ名前のパラメータ値の配列を取得できます。
  • initParam(初期パラメータ):Servletのデプロイメント記述子(web.xml)で、いくつかの初期化パラメータ(init-param)を定義できます。これらのパラメータはServletの初期化時に読み取られ、その動作を構成するために使用できます。Servletでは、`getInitParameter(name)`メソッドを使用して特定の名前の初期化パラメータ値を取得できます。

以下は、通常のコードとEL式を一緒に記述した例です:

  • 1. pageContextオブジェクトの取得:
    通常のコード:
    String contextPath = request.getContextPath();
    EL式:
    ${pageContext.request.contextPath}
  • 2. 単一のリクエストパラメータparamの値の取得:
    通常のコード:
    String paramValue = request.getParameter("param");
    EL式:
    ${param.paramName}
  • 3. 複数のリクエストパラメータparamの値の取得(同じ名前のパラメータが複数存在する場合):
    通常のコード:
    String[] paramValues = request.getParameterValues("param");
    EL式:
    ${paramValues.paramName[0]}
    ${paramValues.paramName[1]}
  • 4. 初期化パラメータinitParamの値の取得:
    通常のコード:
    // ServletContextオブジェクトを取得 ServletContext servletContext = getServletContext(); // パラメータ名でパラメータ値を取得 String initParamValue = servletContext.getInitParameter("initParam");
    EL式:
    ${initParam.initParamName}

EL式を使用することで、データを取得する通常のコードを簡素化できます。EL式は、ページコンテキスト、リクエストパラメータ、初期化パラメータの値にアクセスして操作するためのより簡潔で読みやすい方法を提供します。EL式をJSPページに直接埋め込むことで、コードをより明確で簡潔にし、開発効率を向上させることができます。

EL式の演算子

  1. 算術演算子:
    ${5 + 3}  // 出力結果:8
    ${5 + "3"}  // 出力結果:8
    ${10 - 2}  // 出力結果:8
    ${4 * 2}  // 出力結果:8
    ${16 / 2}  // 出力結果:8
    ${17 % 3}  // 出力結果:2
    
    EL式の+記号は文字列の連結ではなく、常に加算を行います。
    +記号の両側が数字でない場合、それらを数字に変換しようとします。変換できない場合は、NumberFormatException(数値形式例外)がスローされます。
  2. 関係演算子:
    ${5 == 5}  // 出力結果:true
    ${10 != 5}  // 出力結果:true
    ${8 > 5}  // 出力結果:true
    ${3 < 2}  // 出力結果:false
    ${4 >= 4}  // 出力結果:true
    ${7 <= 4}  // 出力結果:false
    
    ${5 eq 5}  // 出力結果:true
    ${10 eq 5}  // 出力結果:false
    ${'Hello' eq 'Hello'}  // 出力結果:true
    ${user.name eq 'John Doe'}  // userオブジェクトにname属性があり、その値が"John Doe"の場合、出力結果はtrue
    
    <%@ page contentType="text/html;charset=UTF-8"%>
    
    <%
        String s1 = new String("hehe");
        String s2 = new String("hehe");
        request.setAttribute("s1",s1);
        request.setAttribute("s2",s2);
    %>
    
    ${s1 == s2}<br>
    <%--true--%>
    
    <%
        Object o = new Object();
    
        request.setAttribute("o0",o);
        request.setAttribute("o00",o);
    
    %>
    
    ${o0 == o00}<br>
    <%--true--%>
    
    
    
    <%
        Object o1 = new Object();
        Object o2 = new Object();
    
        request.setAttribute("o1",o1);
        request.setAttribute("o2",o2);
    %>
    
    ${o1 == o2}<br>
    <%--false--%>
    
    ==記号は、EL式ではequals()メソッドを呼び出します。
    !=記号は、EL式ではequals()メソッドを呼び出します。
  3. 論理演算子:
    ${true && false}  // 出力結果:false
    ${true || false}  // 出力結果:true
    ${!true}  // 出力結果:false
    
  4. empty演算子:
    empty演算子
    
    empty演算子の結果はboolean型です
    
    ${empty param.username}
    ${not empty param.username}
    ${!empty param.password}
    
  5. Nullセーフ演算子:
    ${user?.username}     // userオブジェクトがnullでない場合、ユーザーの名前を出力します。そうでない場合、空の文字列を出力します
    ${empty param.username}
    
  6. 文字列連結演算子:
    ${'Hello' + 'World'}  // 出力結果:HelloWorld
    ${firstName + ' ' + lastName}  // firstNameが"John"、lastNameが"Doe"の場合、出力結果:John Doe
    
  7. コレクション演算子:
    ${array[0]}  // arrayが整数配列の場合、配列の最初の要素を出力します
    ${list.size()}  // listがコレクションの場合、コレクションのサイズを出力します
    ${person.name.length()}  // personオブジェクトにname属性があり、name属性値の長さを出力します
    

JSTLタグライブラリ

JSTLタグライブラリとは何ですか?

  • Java Standard Tag Lib(Java標準タグライブラリ)
  • JSTLタグライブラリは通常、EL式と一緒に使用されます。目的は、JSPのJavaコードを消去することです。
  • タグはJSPに書かれていますが、最終的には対応するJavaプログラムが実行されます。(Javaプログラムはjarファイル内にあります。)

JSTLタグライブラリを使用する手順:

  1. 第一歩:JSTLタグライブラリに対応するjarファイルを導入します。
    tomcat10以降に導入するjarファイルは:
    jakarta.servlet.jsp.jstl-2.0.0.jar
    jakarta.servlet.jsp.jstl-api-2.0.0.jar
    IDEAでどのように導入しますか?
    WEB-INF下にlibディレクトリを新規作成し、jarファイルをlibにコピーして「Add Lib...」します。
    mysqlのデータベースドライバと同様に、すべてWEB-INF/libディレクトリに配置する必要があります。
    どのようなjarファイルをWEB-INF/libディレクトリに配置する必要がありますか?このjarがtomcatサーバーにない場合。
  2. 第二歩:JSPで使用するタグライブラリを導入します。(taglibディレクティブを使用してタグライブラリを導入します。)
    JSTLは多くの種類のタグを提供しています。どのタグを導入するか????核心タグライブラリを重点的に学習します。
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    これが核心タグライブラリです。prefix="ここは好きな名前を付けます。核心タグライブラリは、一般的にcと呼ばれます。"
  3. 第三歩:タグを使用する必要がある場所で使用します。表面はタグを使用していますが、実際には底層ではJavaプログラムが実行されます。

JSTLタグの原理

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
上記のuriの後のパスは、実際にはxxx.tldファイルを指しています。
tldファイルは実際にはxml設定ファイルです。
tldファイルでは、「タグ」と「javaクラス」の関係が記述されています。
上記の核心タグライブラリに対応するtldファイルは:c.tldファイル。どこにありますか?
jakarta.servlet.jsp.jstl-2.0.0.jar内のMETA-INFディレクトリに、c.tldファイルがあります。

ソースコード解析:設定ファイルtldの解析

 <tag>
 <description>タグの説明</description>
 <name>catch</name> タグの名前
 <tag-class>org.apache.taglibs.standard.tag.common.core.CatchTag</tag-class> タグに対応するjavaクラス。
 <body-content>JSP</body-content> タグボディ内に現れることができる内容。JSPの場合、タグボディ内にJSPのすべての構文が現れることを意味します。例えばEL式。
 <attribute>
     <description>この属性の説明</description>
     <name>var</name> 属性名
     <required>false</required> falseはこの属性が必須ではないことを意味します。trueはこの属性が必須であることを意味します。
     <rtexprvalue>false</rtexprvalue> この記述は、この属性がEL式をサポートするかどうかを示しています。falseはサポートしません。trueはサポートします。
 </attribute>
 
 </tag>

JSTLの核心タグライブラリcoreにはどのような一般的なタグがありますか?

  • c:if
    <c:if test="${empty param.username}">
        <h1>ユーザー名は空にできません。</h1>
    </c:if>
    
    <c:if test="${not empty param.username}">
        <h1>ようこそ。</h1>
        ${param.username}
        <%=request.getParameter("username")%>
    </c:if>
    
  • c:forEach
    <c:forEach var="i" begin="1" end="10" step="2">
        ${i}<br>
    </c:forEach>
    
    <c:forEach items="コレクション、EL式をサポート" var="コレクションの要素" varStatus="要素の状態オブジェクト">
        ${要素の状態オブジェクト.count}
    </c:forEach>
    
    <!-- c:forEachタグを使用してstuListリストを反復処理 -->
    <!-- varはループ変数sを指定し、varStatusはループ状態stuStatus(カウントに使用)を指定 -->
    <c:forEach items="${productList}" var="p" varStatus="prodStatus">
         商品番号: ${prodStatus.count} , 価格: ${p.price}, 在庫状況: ${p.inStock ? 'あり' : 'なし'}<br>
    </c:forEach>
    
  • c:choose when otherwise
    <c:choose>
        <c:when test=""></c:when>
        <c:when test=""></c:when>
        <c:when test=""></c:when>
        <c:otherwise></c:otherwise>
    </c:choose>
    
    <!-- これは次のようになります:
        if(){
        }else if(){
        }else if(){
        }else if(){
        }else{
        }
    --%>
    
    <c:choose>
        <c:when test="${param.age < 18}">
            青少年
        </c:when>
        <c:when test="${param.age < 35}">
            青年
        </c:when>
        <c:when test="${param.age < 55}">
            中年
        </c:when>
        <c:otherwise>
            老年
        </c:otherwise>
    </c:choose>
    

タグ: JSP EL式 JSTL サーブレット Java

6月12日 00:30 投稿