如何在 JSP/EL 中调用静态方法?
Posted
技术标签:
【中文标题】如何在 JSP/EL 中调用静态方法?【英文标题】:How to call a static method in 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 标记中插入小脚本。
【问题讨论】:
【参考方案1】:您不能直接在 EL 中调用静态方法。 EL 只会调用实例方法。
对于你失败的 scriptlet 尝试,你不能混合 scriptlet 和 EL。使用其中之一。由于 scriptlet 是 discouraged 超过十年,因此您应该坚持使用 EL-only 解决方案。
您基本上有 2 个选项(假设 balance
和 Calculate#getAmount()
都是 double
)。
只需将其包装在实例方法中即可。
public double getAmount()
return Calculate.getAmount(balance);
改用它:
Amount: $row.amount
或者,将 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"
,那么<s:eval>
会将表达式的结果打印到输出。
【讨论】:
这样更好!对于其他人,您可以通过添加“the_string_argument”(而不是 row.balance 部分)在静态方法中提供一个字符串。仅当您的方法不包含字符串时。 ;) 干杯! 您可以在单引号中传递字符串,例如'the_string_argument'
- 无需与逃避共舞。
酷,这在春天对我有用...我很好奇是否可以做 2 个课程...只需要在 clas 前面加上一个 T() 我假设...这个为我正在做的事情工作: 也可以使用像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 + 在取消引用期间传递必要的参数。这种方法的额外负担是需要按摩请求上下文(例如在<web-app> → <filter>
)。【参考方案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 在这里提到的 ***.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 中获取该变量的值。
【讨论】:
以上是关于如何在 JSP/EL 中调用静态方法?的主要内容,如果未能解决你的问题,请参考以下文章