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


88

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

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

似乎不可能在JSTL标签中插入scriptlet。

Answers:


133

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

对于失败的scriptlet尝试,您不能将scriptlet和EL混合使用。使用一个或另一个。由于小脚本劝阻了十多年,你应该坚持的EL-唯一的解决办法。

您基本上有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 2012年

7
@Sriram:首先,您确定不会将JSP与HTML / JS混淆吗?提出问题的方式表明您似乎认为JSP在Web浏览器中运行,而这是完全不正确的。JSP是HTML / CSS / JS代码生产者。就这样。那应该给您一些关于您的问题和方法的思考。
BalusC

我在寻找什么:)
aliopi

@PhilipRego:答案代码仅基于有问题的代码。
BalusC

61

另一种方法是使用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部分)在静态方法中提供一个字符串。仅当您的方法除外字符串时。;)干杯!
专心

3
您可以将字符串用单引号引起来,例如'the_string_argument'-无需转义即可跳舞。
dma_k 2012年

太酷了,这在春季对我有用...我很好奇是否可以做2个类...只需要在Class前面加上一个T()就可以了... s:eval expression =“ T(org.jsoup.Jsoup).clean(orig_text,T(org.jsoup.safety.Whitelist).none())” var =“ text_stripped_html” />等效于:字符串text_stripped_html = Jsoup。 clean(orig_text,Whitelist.none());
Armyofda12mnkeys

@msangel:检查此主题中的其他答案。
dma_k 2013年

5

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

这对我有帮助。大!!
阿布·巴卡尔·西迪克

4

也可以使用像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();
    }
}

除了类名称中的“静态”外,我在代码中看不到任何静态关键字。
Uluk Biy 2013年

2
@UlukBiy,Settings.reset()是静态方法调用。Lukas建议使用一个非静态方法为每个要从EL调用的静态方法创建一个类似于包装器的ManagedBean。这是一个有效的解决方案。
Vsevolod Golovanov 2014年

3

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


1
我会说EL 2.2确实增加了对调用静态方法的内置支持。该解决方案基于将bean放入请求上下文中,并且(丑陋的)仿真在取消引用期间传递了map +必需的参数。这种方法的额外负担是,需要按摩请求上下文(例如<web-app> → <filter>)。
dma_k 2013年

2

如果您使用的是struts2,则可以使用

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

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


1
Struts不是JSP,就像询问者所说的那样。
bogdan.mustiata '16

2

基于@Lukas答案,您可以通过反射使用该bean和call方法:

@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使用该方法。可以使用它作为最后一个参数传递数组。在这种情况下,这不是必需的,因为只有一个对象作为最后一个参数传递。
胡安

1
<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中获取该变量的值。


0

在Struts2或Webwork2中,可以使用以下命令:

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

然后#tourLanguage在你的jsp中引用

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.