class 的 EL 表达式

EL expression for class

我不明白如何在 EL 表达式中表示 Class

我有一个 EL 函数,它将 class 作为参数(即枚举 class)到 return 可能的枚举值。

我想将它作为 EL 表达式调用。例如。 ${myTld:enumer(com.example.enums.MyEnum)}

但是:

如何在 EL 中表达一个 class 而不可能通过它的字符串表示?

以下作品

<function>
    <description>
        Returns the list of enum values for the given enum class
    </description>
    <name>enumer</name>
    <function-class>com.example.Functions</function-class>
    <function-signature>List enumer(java.lang.String)</function-signature>
</function>

${tld:enumer('com.example.MyEnum')}

我想要什么

    <function-signature>List enumer(java.lang.Class)</function-signature>

我想您希望将 Class 参数传递给您的函数,以避免每次都使用 Class.forName() 解析字符串来提高性能...是吗?

如果是这样,我认为有一种方法...如果您事先知道 classes 您将函数作为参数传递,请使用 ServletContextListener 将它们放入您的应用程序范围。这可能如下所示:

@WebListener
public class MyEnumInitializer implements ServletContextListener {

  public void contextInitialized(ServletContextEvent sce) {
    Map<String, Class<?>> map = new HashMap<>();
    map.put("MyEnum1", MyEnum1.class);
    map.put("MyEnum2", MyEnum2.class);
    // etc.
    sce.getServletContext().addAttribute("myEnums", map);
  }

  public void contextDestroyed(ServletContextEvent sce) {}

}

如果您使用的是 3.0 之前的 Servlet API 版本,请丢弃上面的 @WebListener 注释并在您的 web.xml 文件中声明侦听器,如下所示:

<listener>
  <listener-class>mypackage.MyEnumListener</listener-class>
</listener>

如果您的函数接受 Class,您可以按如下方式使用它:

${tld:enumer(myEnums['MyEnum1'])}

仍然存在 StringClass 的映射,但它涉及使用 HashMap 中的 String 键定位 Class 对象,这比使用反射解析 Class 对象更快。

此外,如果您需要向此 HashMap 添加一个 class,您在初始化应用程序时无法预见,您仍然可以在任何可以访问 ServletContextHashMap 不是一成不变的)。例如,在任何接收 HttpServletRequest 作为参数的方法中:

public void aMethod(HttpServletRequest req, [other params]) {
  // ...
  Map<String, Class<?>> myEnums = (Map<String, Class<?>>) req.getSession().getServletContext().getAttribute("myEnums");
  if (!myEnums.containsKey("aNewEnum")) {
    myEnums.put("aNewEnum", NewEnum.class);
  }
  // ...
}

干杯,

杰夫

您不能在普通 EL 中表示 Class。如果它是一个 bean 属性,你最多可以通过它,就像这样 ${myTld:enumer(bean.someEnumClass)} 返回 Class<? extends Enum>,或者 ${myTld:enumer(bean.someEnum['class'])} 其中 someEnum 是实际的 Enum,但仅此而已。将 class 名称作为 String 传递确实是您最好的选择。

如果您已经在使用 EL 3.0(可在 Tomcat 8、WildFly 8 等 Servlet 3.1 容器上使用),自定义函数的替代方法是立即将其导入 JSP 像下面这样使用新的 EL 3.0 ImportHandler API:

${pageContext.ELContext.importHandler.importClass('com.example.enums.MyEnum')}

然后 ${MyEnum} 可以获得枚举。

<c:forEach items="${MyEnum.values()}" var="myEnumValue">
    ${myEnumValue}<br/>
</c:forEach>

或者,通过 servlet 上下文侦听器全局导入 ${MyEnum},如下所示:

@WebListener
public class Config implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) {
        JspFactory.getDefaultFactory().getJspApplicationContext(event.getServletContext()).addELContextListener(new ELContextListener() {
            @Override
            public void contextCreated(ELContextEvent event) {
                event.getELContext().getImportHandler().importClass(MyEnum.class.getName());
            }
        });
    }

    // ...
}