ChatGPT解决这个技术问题 Extra ChatGPT

如何在 JSP/EL 中调用静态方法?

我是 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 标记中插入小脚本。


B
BalusC

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

至于你失败的 scriptlet 尝试,你不能混合 scriptlet 和 EL。使用其中之一。由于 scriptlet discouraged 已有十年之久,因此您应该坚持仅使用 EL 的解决方案。

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

只需将其包装在实例方法中即可。 public double getAmount() { return Calculate.getAmount(balance);并改用它: Amount: ${row.amount} 或者,将 Calculate#getAmount() 声明为 EL 函数。首先创建一个/WEB-INF/functions.tld 文件: 自定义函数 1.0 http: //example.com/functions calculateAmount com.example.Calculate double getAmount(double) 并使用如下: <%@taglib uri="http://example.com/functions" prefix="f" %> ... 金额:${f :calculateAmount(row.balance)}">


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

另一种方法是使用 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",那么 <s:eval> 会将表达式的结果打印到输出。


这更好!对于其他人,您可以通过添加“the_string_argument”(而不是 row.balance 部分)在静态方法中提供一个字符串。仅当您的方法不包含字符串时。 ;) 干杯!
您可以在单引号中传递字符串,例如 'the_string_argument' - 无需转义。
很酷,这在 Spring 中对我有用......我很好奇是否可以做 2 个类......只需要在 clas 前面加上一个 T() 我假设......这对我正在做的事情有用:< s:eval expression="T(org.jsoup.Jsoup).clean(orig_text, T(org.jsoup.safety.Whitelist).none() )" var="text_stripped_html" /> 相当于:String text_stripped_html = Jsoup。 clean(orig_text, Whitelist.none());
@msangel:检查本主题中的其他答案。
S
Sahan Marasinghe

如果您的 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>

这对我很有帮助。伟大的!!
L
Lukas

也可以使用像 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 调用它。这是一个有效的解决方案。
m
msangel

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


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

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

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

然后将 html 或 html 标记属性中的“myVar”引用为 ${myVar}


像提问者所说的那样,Struts 不是 JSP。
J
Juan

基于@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 的那个方法。它可以用来传递一个数组作为最后一个参数。在这种情况下,它不是必需的,因为只有一个对象作为最后一个参数传递。
a
ash9
<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 中获取该变量的值。


s
sendon1982

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

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

然后在您的 jsp 中引用 #tourLanguage