私はそのように定義されたステータスと呼ばれる列挙型を持っています:
public enum Status {
VALID("valid"), OLD("old");
private final String val;
Status(String val) {
this.val = val;
}
public String getStatus() {
return val;
}
}
JSTLタグからVALID
の値にアクセスしたいと思います。具体的には、<c:when>
タグのtest
属性。例えば。
<c:when test="${dp.status eq Status.VALID">
これが可能かどうかはわかりません。
文字列との簡単な比較は次のとおりです。
<c:when test="${someModel.status == 'OLD'}">
Spring MVCを使用している場合、Spring Expression Language(SpEL)が役立ちます。
<spring:eval expression="dp.status == T(com.example.Status).VALID" var="isValid" />
<c:if test="${isValid}">
isValid
</c:if>
ここには3つの選択肢がありますが、どれも完璧ではありません。
test
属性でスクリプトレットを使用できます。
<c:when test="<%= dp.getStatus() == Status.VALID %>">
これは列挙型を使用しますが、JSP 2.0の「正しい方法」ではないスクリプトレットも使用します。しかし、最も重要なことは、${}
を使用して同じwhen
に別の条件を追加する場合、これは機能しません。これは、テストするすべての変数をスクリプトレットで宣言するか、リクエストまたはセッションで保持する必要があることを意味します(pageContext
変数は.tag
ファイルでは使用できません)。
文字列と比較できます:
<c:when test="${dp.status == 'VALID'}">
これはきれいに見えますが、列挙値を複製し、コンパイラによって検証できない文字列を導入しています。そのため、enumからその値を削除したり、名前を変更したりしても、コードのこの部分にアクセスできないことはわかりません。基本的には、毎回コードを検索/置換する必要があります。
使用する各列挙値をページコンテキストに追加できます。
<c:set var="VALID" value="<%=Status.VALID%>"/>
そして、あなたはこれを行うことができます:
<c:when test="${dp.status == VALID}">
スクリプトレットも使用しますが、最後のオプション(3)を好みます。これは、値を設定するときにのみ使用されるためです。後で、他のEL条件とともに、より複雑なEL式で使用できます。オプション(1)では、単一のtest
タグのwhen
属性でスクリプトレットとEL式を使用できません。
したがって、私の問題を完全に解決するには、次のことを行う必要がありました。
<% pageContext.setAttribute("old", Status.OLD); %>
それから私はできました:
<c:when test="${someModel.status == old}"/>...</c:when>
期待どおりに機能しました。
さらに2つの可能性があります。
少なくともバージョン3.0のELを使用している限り、次のようにページに定数をインポートできます。
<%@ page import="org.example.Status" %>
<c:when test="${dp.status eq Status.VALID}">
ただし、一部のIDEはこれをまだ理解していないため(たとえば IntelliJ )、タイプミスを犯しても実行時まで警告が表示されません。
これが適切なIDEサポートを取得したら、これが私の好みの方法です。
列挙型にゲッターを追加できます。
public enum Status {
VALID("valid"), OLD("old");
private final String val;
Status(String val) {
this.val = val;
}
public String getStatus() {
return val;
}
public boolean isValid() {
return this == VALID;
}
public boolean isOld() {
return this == OLD;
}
}
次に、JSPで:
<c:when test="${dp.status.valid}">
これはすべてのIDEでサポートされており、EL 3.0をまだ使用できない場合にも機能します。これは、列挙型にすべてのロジックをラップしたままにするため、現時点で行っていることです。
また、enumを格納する変数がnullになる可能性がある場合も注意してください。コードがnullでないことを保証していない場合は、まずそれを確認する必要があります。
<c:when test="${not empty db.status and dp.status.valid}">
このメソッドは、JSPで中間値を設定する方法よりも優れていると思います。列挙を使用する必要がある各ページでそれを行う必要があるからです。ただし、このソリューションでは、ゲッターを1回宣言するだけで済みます。
この目的のために、私は次のことを行います。
<c:set var="abc">
<%=Status.OLD.getStatus()%>
</c:set>
<c:if test="${someVariable == abc}">
....
</c:if>
見苦しいですが、動作します!
Kornelの質問に対する答えはありませんが、他のスクリプトの例については発言しています。式の大部分はtoString()
を暗黙的に信頼しますが、Enum.valueOf()
はEnum.name()
プロパティに由来する/一致する値を期待します。そのため、たとえば以下を使用する必要があります。
<% pageContext.setAttribute("Status_OLD", Status.OLD.name()); %>
...
<c:when test="${someModel.status == Status_OLD}"/>...</c:when>
次のようなメソッドを列挙に追加します。
public String getString() {
return this.name();
}
例えば
public enum MyEnum {
VALUE_1,
VALUE_2;
public String getString() {
return this.name();
}
}
次に使用できます:
<c:if test="${myObject.myEnumProperty.string eq 'VALUE_2'}">...</c:if>
MVCフレームワークを使用する場合、コントローラーに次のものを追加します。
request.setAttribute(RequestParameterNamesEnum.INBOX_ACTION.name(), RequestParameterNamesEnum.INBOX_ACTION.name());
これにより、JSPページで以下を使用できます。
<script> var url = 'http://www.nowhere.com/?${INBOX_ACTION}=' + someValue;</script>
比較にも使用できます
<c:when test="${someModel.action == INBOX_ACTION}">
文字列リテラルを入れるよりも好きです。
<%@ page import="com.example.Status" %>
1. ${dp.status eq Title.VALID.getStatus()}
2. ${dp.status eq Title.VALID}
3. ${dp.status eq Title.VALID.toString()}