【问题标题】:How to call a static method in JSP/EL?如何在 JSP/EL 中调用静态方法?
【发布时间】:2011-09-17 17:54:35
【问题描述】:

我是 JSP 的新手。我尝试连接 MySQL 和我的 JSP 页面,它工作正常。但这是我需要做的。 我有一个名为“平衡”的表属性。检索它并使用它来计算一个名为“金额”的新值。 (我没有打印“余额”)。

 <c:forEach var="row" items="${rs.rows}">
        ID: ${row.id}<br/>
        Passwd: ${row.passwd}<br/>
        Amount: <%=Calculate.getAmount(${row.balance})%>
 </c:forEach>

似乎无法在 JSTL 标记中插入小脚本。

【问题讨论】:

    标签: java jsp el


    【解决方案1】:

    您不能直接在 EL 中调用静态方法。 EL 只会调用实例方法。

    对于你失败的 scriptlet 尝试,你不能混合 scriptlet 和 EL。使用其中之一。由于 scriptletdiscouraged 超过十年,因此您应该坚持使用 EL-only 解决方案。

    您基本上有 2 个选项(假设 balanceCalculate#getAmount() 都是 double)。

    1. 只需将其包装在实例方法中即可。

      public double getAmount() {
          return Calculate.getAmount(balance);
      }
      

      改用它:

      Amount: ${row.amount}
      

    2. 或者,将 Calculate#getAmount() 声明为 EL 函数。首先创建一个/WEB-INF/functions.tld文件:

      <?xml version="1.0" encoding="UTF-8" ?>
      <taglib 
          xmlns="http://java.sun.com/xml/ns/javaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
          version="2.1">
      
          <display-name>Custom Functions</display-name>    
          <tlib-version>1.0</tlib-version>
          <uri>http://example.com/functions</uri>
      
          <function>
              <name>calculateAmount</name>
              <function-class>com.example.Calculate</function-class>
              <function-signature>double getAmount(double)</function-signature>
          </function>
      </taglib>
      

      并按如下方式使用:

      <%@taglib uri="http://example.com/functions" prefix="f" %>
      ...
      Amount: ${f:calculateAmount(row.balance)}">
      

    【讨论】:

    • @BalusC 如果我的 jsp 有(计算)某个值并且我想将其作为参数发送怎么办??
    • @Sriram:首先,您确定您没有将 JSP 与 HTML/JS 混淆吗?您提出问题的方式表明您似乎认为 JSP 在网络浏览器中运行,而这完全不正确。 JSP 是一个 HTML/CSS/JS 代码生成器。就这样。这应该让你思考你的问题和方法。
    • 我在找什么 :)
    • @PhilipRego:答案中的代码只是基于有问题的代码。
    【解决方案2】:

    另一种方法是使用 Spring SpEL:

    <%@taglib prefix="s" uri="http://www.springframework.org/tags" %>
    
    <s:eval expression="T(org.company.Calculate).getAmount(row.balance)" var="rowBalance" />
    Amount: ${rowBalance}
    

    如果您跳过可选的var="rowBalance",那么&lt;s:eval&gt; 会将表达式的结果打印到输出。

    【讨论】:

    • 这样更好!对于其他人,您可以通过添加“the_string_argument”(而不是 row.balance 部分)在静态方法中提供一个字符串。仅当您的方法不包含字符串时。 ;) 干杯!
    • 您可以在单引号中传递字符串,例如'the_string_argument' - 无需与逃避共舞。
    • 酷,这在春天对我有用...我很好奇是否可以做 2 个课程...只需要在 clas 前面加上一个 T() 我假设...这个为我正在做的事情工作: 相当于: String text_stripped_html = Jsoup.clean(orig_text, Whitelist.none());
    • @msangel:查看本主题中的其他答案。
    【解决方案3】:

    也可以使用像StaticInterface这样的Bean

    <h:commandButton value="reset settings" action="#{staticinterface.resetSettings}"/>
    

    和豆子

    package com.example.common;
    
    import com.example.common.Settings;
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.ViewScoped;
    
    @ManagedBean(name = "staticinterface")
    @ViewScoped
    public class StaticInterface {
    
        public StaticInterface() {
        }
    
        public void resetSettings() {
            Settings.reset();
        }
    }
    

    【讨论】:

    • 我在代码中看不到任何静态关键字,除了类名中的“静态”。
    • @UlukBiy,Settings.reset() 是一个静态方法调用。 Lukas 建议创建一个类似包装器的 ManagedBean,其中每个静态方法都有一个非静态方法,人们希望从 EL 调用该方法。这是一个有效的解决方案。
    【解决方案4】:

    EL 2.2 具有调用方法的内置机制。更多信息:oracle site。 但它无法访问静态方法。尽管您仍然可以通过对象引用来调用它。但我使用了另一种解决方案,如本文所述:Calling a Static Method From EL

    【讨论】:

    • 我认为 EL 2.2 确实为调用静态方法添加了内置支持。该解决方案基于将 bean 放入请求上下文中,并且(丑陋的)模拟 map + 在取消引用期间传递必要的参数。这种方法的额外负担是需要按摩请求上下文(例如在&lt;web-app&gt; → &lt;filter&gt;)。
    【解决方案5】:

    如果你使用 struts2,你可以使用

    <s:var name='myVar' value="%{@package.prefix.MyClass#myMethod('param')}"/>
    

    然后在html或html标签属性中引用'myVar'为${myVar}

    【讨论】:

    • Struts 不是 JSP,就像提问者说的那样。
    【解决方案6】:

    根据@Lukas 的回答,您可以使用该 bean 并通过反射调用方法:

    @ManagedBean (name = "staticCaller")
    @ApplicationScoped
    public class StaticCaller {
    private static final Logger LOGGER = Logger.getLogger(StaticCaller.class);
    /**
     * @param clazz
     * @param method
     * @return
     */
    @SuppressWarnings("unchecked")
    public <E> E call(String clazz, String method, Object... objs){
        final ClassLoader loader = Thread.currentThread().getContextClassLoader();
        final List<Class<?>> clasesparamList = new ArrayList<Class<?>>();
        final List<Object> objectParamList = new ArrayList<Object>();
        if (objs != null && objs.length > 0){
            for (final Object obj : objs){
                clasesparamList.add(obj.getClass());
                objectParamList.add(obj);
            }
        }
        try {           
            final Class<?> clase = loader.loadClass(clazz);
            final Method met = clase.getMethod(method, clasesparamList.toArray(new Class<?>[clasesparamList.size()]));
                return (E) met.invoke(null, objectParamList.toArray());
            } catch (ClassNotFoundException e) {
                LOGGER.error(e.getMessage(), e);
            } catch (InvocationTargetException e) {
                LOGGER.error(e.getMessage(), e);
            } catch (IllegalAccessException e) {
                LOGGER.error(e.getMessage(), e);
            } catch (IllegalArgumentException e) {
                LOGGER.error(e.getMessage(), e);
            } catch (NoSuchMethodException e) {
                LOGGER.error(e.getMessage(), e);
            } catch (SecurityException e) {
                LOGGER.error(e.getMessage(), e);
            }
            return null;
        }
    }
    

    xhtml,例如变成一个命令按钮:

    <p:commandButton action="#{staticCaller.call('org.company.Calculate', 'getAmount', row.balance)}" process="@this"/>
    

    【讨论】:

    • EL(2.2)方法表达式中不能使用可变参数。
    • 嗨罗伯特,对不起,你到底是什么意思,我已经使用该代码很长时间了,我相信它可以工作。我的错在哪里?
    • 我没有找到实际的规范,但正如 BalusC 在这里提到的 stackoverflow.com/questions/15560508/… 这就是 SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (http-localhost/127.0.0.1:8080-5) java.lang.IllegalArgumentException: wrong number of arguments 的原因。
    • 是的,你不能在 EL 上使用可变参数。但是你可以使用 EL 的那个方法。它可以用来传递一个数组作为最后一个参数。在这种情况下,它不是必需的,因为只有一个对象作为最后一个参数传递。
    【解决方案7】:

    在 Struts2 或 Webwork2 中,你可以使用这个:

    <s:set name="tourLanguage" value="@foo.bar.TourLanguage@getTour(#name)"/>
    

    然后在你的jsp中引用#tourLanguage

    【讨论】:

      【解决方案8】:

      如果您的 Java 类是:

      package com.test.ejb.util;
      
      public class CommonUtilFunc {
      
          public static String getStatusDesc(String status){
      
              if(status.equals("A")){
                  return "Active";
              }else if(status.equals("I")){
                  return "Inactive";
              }else{
                  return "Unknown";
              }
          }
      }
      

      然后您可以在 JSP 页面中调用静态方法“getStatusDesc”,如下所示。

      使用 JSTL useBean 获取 JSP 页面顶部的类:

      <jsp:useBean id="cmnUtilFunc" class="com.test.ejb.util.CommonUtilFunc"/>
      

      然后使用表达式语言在您需要的地方调用函数:

      <table>
          <td>${cmnUtilFunc.getStatusDesc('A')}</td>
      </table>
      

      【讨论】:

      • 这对我很有帮助。太好了!!
      【解决方案9】:
      <c:forEach var="row" items="${rs.rows}">
              ID: ${row.id}<br/>
              Passwd: ${row.passwd}<br/>
      <c:set var="balance" value="${row.balance}"/>
              Amount: <%=Calculate.getAmount(pageContext.getAttribute("balance").toString())%>
       </c:forEach>
      

      在这个解决方案中,我们将值(通过核心标签)分配给一个变量,然后我们在 scriplet 中获取该变量的值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-17
        • 2011-10-28
        • 1970-01-01
        • 1970-01-01
        • 2021-04-09
        • 1970-01-01
        相关资源
        最近更新 更多