JSTL で EL を使用して Enum 値にアクセスする
質問
Status という列挙型が次のように定義されています。
public enum Status {
VALID("valid"), OLD("old");
private final String val;
Status(String val) {
this.val = val;
}
public String getStatus() {
return val;
}
}
の値にアクセスしたいのですが、 VALID
JSTLタグから。具体的には、 test
の属性 <c:when>
鬼ごっこ。例えば。
<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'}">
これはきれいに見えますが、列挙値を複製する文字列を導入しているため、コンパイラで検証できません。したがって、その値を列挙型から削除するか、名前を変更しても、コードのこの部分にアクセスできなくなることはわかりません。基本的には毎回コードを介して検索/置換を行う必要があります。
使用する各列挙値をページ コンテキストに追加できます。
<c:set var="VALID" value="<%=Status.VALID%>"/>
そして、これを行うことができます:
<c:when test="${dp.status == VALID}">
スクリプトレットも使用しますが、私は最後のオプション (3) を好みます。これは、値を設定する場合にのみ使用されるためです。後で、これを他の EL 条件と一緒に、より複雑な EL 式で使用できます。オプション (1) では、スクリプトレットと EL 式を使用できません。 test
単一の属性 when
鬼ごっこ。
したがって、問題を完全に解決するには、次のことを行う必要がありました。
<% pageContext.setAttribute("old", Status.OLD); %>
その後、次のことができました。
<c:when test="${someModel.status == old}"/>...</c:when>
期待どおりに機能しました。
さらに 2 つの可能性があります。
JSP EL 3.0 定数
EL のバージョン 3.0 以降を使用している限り、次のように定数をページにインポートできます。
<%@ page import="org.example.Status" %>
<c:when test="${dp.status eq Status.VALID}">
ただし、一部の IDE はこれをまだ理解していません (例: インテリJ) そのため、タイプミスをしても、実行時まで警告は表示されません。
適切な 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()}
- インポートを次の場所に置きます 上, 、JSPページヘッダー内
- 一緒に働きたいなら getStatus メソッド, 、 使用 #1
- 一緒に働きたい場合は、 列挙型要素 それ自体は、どちらかを使用します #2 または #3
- 使用できます == の代わりに 等価
私は一般に、Java コードを jsps/tag ファイルに混ぜるのは悪い習慣だと考えています。「eq」を使用するとうまくいくはずです。
<c:if test="${dp.Status eq 'OLD'}">
...
</c:if>
使うポイントが多いときはこうするんですが…
public enum Status {
VALID("valid"), OLD("old");
private final String val;
Status(String val) {
this.val = val;
}
public String getStatus() {
return val;
}
public static void setRequestAttributes(HttpServletRequest request) {
Map<String,String> vals = new HashMap<String,String>();
for (Status val : Status.values()) {
vals.put(val.name(), val.value);
}
request.setAttribute("Status", vals);
}
}
JSP
<%@ page import="...Status" %>
<% Status.setRequestAttributes(request) %>
<c:when test="${dp.status eq Status.VALID}">
...
Java クラスの場合:
public class EnumTest{
//Other property link
private String name;
....
public enum Status {
ACTIVE,NEWLINK, BROADCASTED, PENDING, CLICKED, VERIFIED, AWARDED, INACTIVE, EXPIRED, DELETED_BY_ADMIN;
}
private Status statusobj ;
//Getter and Setters
}
これで、POJO と enum obj が作成されました。今 EnumTest サーブレットまたはコントローラークラスセッションで使用してセッションオブジェクトを設定します。SetAttribute( "enumtest"、enumtest);
JSPページ内
<c:if test="${enumTest.statusobj == 'ACTIVE'}">
//TRUE??? THEN PROCESS SOME LOGIC