首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类的EL表达式

类的EL表达式
EN

Stack Overflow用户
提问于 2015-10-22 14:17:13
回答 2查看 1.1K关注 0票数 0

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

我有一个EL函数,它以类作为参数(即Enum类)来返回可能的枚举值。

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

然而:

  • 以上语法将空作为参数传递。
  • 使用MyEnum.class引发无法计算表达式的异常。

如何在没有可能传递其字符串表示的情况下用EL表示类?

下面的工作

代码语言:javascript
复制
<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')}

我想要什么

代码语言:javascript
复制
    <function-signature>List enumer(java.lang.Class)</function-signature>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-10-22 15:00:47

您不能在普通EL中表示Class。如果它是像so ${myTld:enumer(bean.someEnumClass)}返回的Class<? extends Enum>那样的bean属性,或者是someEnum是实际Enum${myTld:enumer(bean.someEnum['class'])},则最多可以传递它,但仅此而已。以String的形式传递类名是最好的选择。

如果您已经使用了EL 3.0 (可以在Servlet3.1容器(如Tomcat 8、WildFly 8等)上使用),那么您的自定义函数的另一种选择是立即在JSP3.0中导入它,如下所示,使用新的El3.0 ImportHandler API:

代码语言:javascript
复制
${pageContext.ELContext.importHandler.importClass('com.example.enums.MyEnum')}

该枚举随后可由${MyEnum}获得。

代码语言:javascript
复制
<c:forEach items="${MyEnum.values()}" var="myEnumValue">
    ${myEnumValue}<br/>
</c:forEach>

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

代码语言:javascript
复制
@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());
            }
        });
    }

    // ...
}
票数 3
EN

Stack Overflow用户

发布于 2015-10-22 15:00:12

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

如果是这样的话,我想有个办法.如果预先知道将函数作为参数传递给您的类,请使用ServletContextListener将它们放入您的应用程序范围。这可能如下所示:

代码语言:javascript
复制
@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版本,请放弃上面的@WebListener注释并在web.xml文件中声明侦听器,如下所示:

代码语言:javascript
复制
<listener>
  <listener-class>mypackage.MyEnumListener</listener-class>
</listener>

如果您的函数接受Class,您可以如下所示使用它:

代码语言:javascript
复制
${tld:enumer(myEnums['MyEnum1'])}

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

此外,如果您需要在这个HashMap中添加一个在初始化应用程序时无法预见的类,那么您仍然可以在可以访问ServletContext的任何地方(HashMap不是不可变的)来实现它。例如,在接收作为参数的HttpServletRequest的任何方法中:

代码语言:javascript
复制
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);
  }
  // ...
}

干杯,

杰夫

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33283260

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档