38

instanceof有没有办法在 EL中进行检查?

例如

<h:link rendered="#{model instanceof ClassA}">      
    #{errorMessage1}
</h:link>
<h:link rendered="#{model instanceof ClassB}">      
    #{errorMessage2}
</h:link>
4

7 回答 7

57

您可以比较Class#getName(),或者可能更好,Class#getSimpleName()String.

<h:link rendered="#{model['class'].simpleName eq 'ClassA'}">      
    #{errorMessage1}
</h:link>
<h:link rendered="#{model['class'].simpleName eq 'ClassB'}">      
    #{errorMessage2}
</h:link>

Object#getClass()请注意使用大括号表示法指定的重要性,['class']因为class它是保留的 Java 文字,否则会在 EL 2.2+ 中引发 EL 异常。

类型安全的替代方法是在模型的公共基类中添加public enum Type { A, B }一些public abstract Type getType()

<h:link rendered="#{model.type eq 'A'}">      
    #{errorMessage1}
</h:link>
<h:link rendered="#{model.type eq 'B'}">      
    #{errorMessage2}
</h:link>

任何无效值都会在 EL 2.2+ 的运行时引发 EL 异常。

如果您使用的是OmniFaces,从 3.0 版开始,您可以使用#{of:isInstance()}.

<h:link rendered="#{of:isInstance('com.example.ClassA', model)}">      
    #{errorMessage1}
</h:link>
<h:link rendered="#{of:isInstance('com.example.ClassB', model)}">      
    #{errorMessage2}
</h:link>
于 2012-04-25T13:47:39.250 回答
6

这在EL. 为此使用支持 bean:

public class MyBean {

    public boolean getIsClassA() {
        if(model instanceof ClassA) {
            return true;
        }
        return false;
    }


}

然后通过调用支持 bean 进行检查:

<h:link outcome="#{PageNameA}?faces-redirect=true&amp;" rendered="#{myBean.isClassA}">      
    #{errorMessage}
</h:link>

于 2012-04-25T11:01:52.603 回答
4

有用:

rendered="#{node.getClass().getSimpleName() == 'Logt_anno'}"
于 2013-10-18T16:34:14.273 回答
3

定义一个静态函数,如:

public boolean isInstanceOf( Object obj, Class targetClass) {
        return targetClass.isInstance(obj);
    }

为它定义一个自定义的 EL 函数,并使用它。我们还可以传递一个字符串名称并forName()在方法内部进行操作。

于 2015-11-18T13:48:13.173 回答
2

有办法,看

JSF EL:instanceof 保留但尚未实现?

但是,该instanceof运算符仍然没有实现,至少在 Mojarra 2.1 中是这样。请在此处为错误投票:

http://java.net/jira/browse/JSP_SPEC_PUBLIC-113

目前最好的解决方法可能是将类名存储在支持 bean getter 中,而不是为每个类创建一个布尔测试方法:

public String getSelectedNodeClassName()
{
    return selectedNode.getClass().getSimpleName();
}

所以它将是 BalusC 和 flash 解决方案的混合体。然而,它在 JSF 中的可读性比 BalusC 的要高得多,而且它非常类似于未来的instanceof运算符使用:

rendered="#{nodeManager.selectedNodeClassName eq 'ChapterNode'}"

这不会像 flash 建议的那样在支持 bean 上为每个类测试生成一个方法。不过,这可能比 Flash 慢。

于 2012-05-03T05:36:37.730 回答
1

不是很优雅,因为它混合了JSP EL和早期的表达式语法,但不需要任何额外的Java代码:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<c:set var="interfaceClass" value="<%=com.example.ClassA.class%>"/>
<c:set var="implementationClass" value="${model['class']}"/>
<c:if test="${interfaceClass.isAssignableFrom(implementationClass)}">
    <%-- Your logic here. --%>
</c:if>
于 2017-05-31T14:31:05.557 回答
0

您可以为此使用辅助 bean:

@ManagedBean
public class Helper {
  public boolean isInstance(Object bean, String fullyQualifiedClassName) {
    return Class.forName(fullyQualifiedClassName).isInstance(bean);
  }
}

用法:

<h:link rendered="#{helper.isInstance(model, 'package.ClassA')}">
  #{errorMessage1}
</h:link>

这样做的好处是考虑了继承,并且您可以测试您无法修改的类(BalusC 解决方案的两个缺点)。

如果您喜欢使用简单的类名(并且不担心名称冲突),您可以使用手动填写的查找图或使用类路径扫描器(如org.reflections)

@ManagedBean
@ApplicationScoped
public class Helper {
  private Map<String, Class<? extends MyBaseClass>> classes = 
      new Reflections("myrootpackage").getSubTypesOf(MyBaseClass.class).stream()
      .collect(Collectors.toMap(Class::getSimpleName, Function.identity()));

  public boolean isInstance(Object bean, String simpleClassName) {
    final Class<? extends MyBaseClass> c = this.classes.get(simpleClassName);
    return c != null && c.isInstance(bean);
  }
}

您甚至可以将辅助函数移动到 ELResolver:

public class InstanceOfELResolver extends ELResolver {

  public Object invoke(final ELContext context, final Object base, 
      final Object method, final Class<?>[] paramTypes, final Object[] params) {
    if ("isInstanceOf".equals(method) && params.length == 1) {
      context.setPropertyResolved(true);
      try {
        return params[0] != null && Class.forName(params[0].toString()).isInstance(base);
      } catch (final ClassNotFoundException e) {
        return false;
      }
    }
    return null;
  }

  // ... All other methods with default implementation ...
}

用法:

<h:link rendered="#{model.isInstanceOf('package.ClassA')}">
  #{errorMessage1}
</h:link>
于 2018-06-01T09:40:24.347 回答