valor Enum acesso usando EL com JSTL
Pergunta
Eu tenho um Enum chamado Estado definido como tal:
public enum Status {
VALID("valid"), OLD("old");
private final String val;
Status(String val) {
this.val = val;
}
public String getStatus() {
return val;
}
}
Eu gostaria de acessar o valor de VALID
de uma tag JSTL. Especificamente o atributo test
da etiqueta <c:when>
. Por exemplo.
<c:when test="${dp.status eq Status.VALID">
Eu não tenho certeza se isso é possível.
Solução
Uma comparação simples contra obras de cordas:
<c:when test="${someModel.status == 'OLD'}">
Outras dicas
Se estiver usando Spring MVC, o Expression Primavera Language (SPEL) pode ser útil:
<spring:eval expression="dp.status == T(com.example.Status).VALID" var="isValid" />
<c:if test="${isValid}">
isValid
</c:if>
Você tem 3 opções aqui, nenhum dos quais é perfeito:
-
Você pode usar um scriptlet no atributo
test
:<c:when test="<%= dp.getStatus() == Status.VALID %>">
Este usa o enum, mas também utiliza um scriptlet, o que não é o "caminho certo" em JSP 2.0. Mas o mais importante, isso não funciona quando você quiser adicionar outra condição para o mesmo
when
usando${}
. E isso significa todas as variáveis ??que você deseja teste têm de ser declaradas em um scriptlet, ou mantidos em pedido, ou sessão (variávelpageContext
não está disponível nos arquivos.tag
). -
Você pode comparar contra string:
<c:when test="${dp.status == 'VALID'}">
Isso parece limpo, mas você está introduzindo uma cadeia que duplica o valor de enumeração e não pode ser validada pelo compilador. Então, se você remover esse valor a partir da enumeração ou renomeá-lo, você não vai ver que esta parte do código não é mais acessível. Você basicamente tem que fazer uma pesquisa / substituir o código de cada vez.
-
Você pode adicionar cada um dos valores de enumeração que você usa no contexto da página:
<c:set var="VALID" value="<%=Status.VALID%>"/>
e, em seguida, você pode fazer isso:
<c:when test="${dp.status == VALID}">
Eu prefiro a última opção (3), embora também utiliza um scriptlet. Isso é porque ele só usa-lo quando você definir o valor. Mais tarde, você pode usá-lo em expressões EL mais complexos, em conjunto com outras condições EL. Enquanto na opção (1) você não pode usar um scriptlet e uma expressão EL no atributo test
de uma única tag when
.
Assim, para obter o meu problema totalmente resolvido que eu precisava para fazer o seguinte:
<% pageContext.setAttribute("old", Status.OLD); %>
Então eu era capaz de fazer:
<c:when test="${someModel.status == old}"/>...</c:when>
que funcionou como esperado.
Aqui estão mais duas possibilidades:
JSP EL 3,0 Constantes
Enquanto você estiver usando pelo menos a versão 3.0 do EL, em seguida, você pode importar constantes em sua página da seguinte forma:
<%@ page import="org.example.Status" %>
<c:when test="${dp.status eq Status.VALID}">
No entanto, algumas IDEs não entendem isso ainda (por exemplo IntelliJ ), assim você não terá quaisquer avisos se você cometer um erro de digitação, até a execução.
Este seria o meu método preferido, uma vez que recebe o apoio IDE adequada.
Métodos de Ajuda
Você poderia apenas adicionar getters à sua enumeração.
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;
}
}
Então em seu JSP:
<c:when test="${dp.status.valid}">
Este é suportado em todas as IDEs e também irá funcionar se você não pode usar EL 3.0 ainda. Isto é o que eu faço no momento, pois ele mantém toda a lógica embrulhado em meu enum.
Também deve ter cuidado se é possível para a variável armazenando o enum para ser nulo. Você precisa verificar para que primeiro se o seu código não garante que não é nulo:
<c:when test="${not empty db.status and dp.status.valid}">
Eu acho que este método é superior aos onde você definir um valor intermediário no JSP, porque você tem que fazer isso em cada página onde você precisa usar a enumeração. No entanto, com esta solução só precisa declarar o getter uma vez.
Para este fim eu faço o seguinte:
<c:set var="abc">
<%=Status.OLD.getStatus()%>
</c:set>
<c:if test="${someVariable == abc}">
....
</c:if>
É olha feio, mas funciona!
Eu não tenho uma resposta para a questão de Kornel, mas eu tenho uma observação sobre os outros exemplos de scripts. A maior parte da confiança expressão implicitamente na toString()
, mas o Enum.valueOf()
espera um valor que vem de / corresponde a propriedade Enum.name()
. Portanto, deve-se usar por exemplo:.
<% pageContext.setAttribute("Status_OLD", Status.OLD.name()); %>
...
<c:when test="${someModel.status == Status_OLD}"/>...</c:when>
Adicionar um método para o enum como:
public String getString() {
return this.name();
}
Por exemplo
public enum MyEnum {
VALUE_1,
VALUE_2;
public String getString() {
return this.name();
}
}
Em seguida, você pode usar:
<c:if test="${myObject.myEnumProperty.string eq 'VALUE_2'}">...</c:if>
Ao usar um framework MVC Eu coloquei o seguinte no meu controlador.
request.setAttribute(RequestParameterNamesEnum.INBOX_ACTION.name(), RequestParameterNamesEnum.INBOX_ACTION.name());
Isso me permite usar o seguinte no meu JSP página.
<script> var url = 'http://www.nowhere.com/?${INBOX_ACTION}=' + someValue;</script>
Ele também pode ser usado em sua comparação
<c:when test="${someModel.action == INBOX_ACTION}">
O que eu prefiro mais colocando em um literal string.
<%@ 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()}
- Coloque a importação no top , no cabeçalho da página JSP
- Se você quiser trabalhar com método getStatus , use # 1
- Se você quiser trabalhar com o elemento enum em si, use um # 2 ou # 3
- Você pode usar == em vez de eq
I geralmente consideram má prática de misturar código java em JSPs arquivos / tag. Usando 'eq' deve fazer o truque:
<c:if test="${dp.Status eq 'OLD'}">
...
</c:if>
Eu fazê-lo desta forma, quando há muitos pontos para usar ...
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}">
...
Em Java Class:
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
}
Então, agora POJO e enum obj é criado. Agora EnumTest você irá definir no objeto de sessão usando na classe servlet ou controlador session.setAttribute ( "enumTest", EnumTest);
Em JSP página
<c:if test="${enumTest.statusobj == 'ACTIVE'}">
//TRUE??? THEN PROCESS SOME LOGIC