Как вызвать статический метод в 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.
8 ответов
Вы не можете вызывать статические методы непосредственно в EL. EL будет вызывать только методы экземпляра.
Что касается вашей неудачной попытки скриптлета, вы не можете смешивать скриптлеты и EL. Используйте один или другой. Поскольку скриптлеты не поощряются в течение десяти лет, вы должны придерживаться решения только для EL.
У вас есть в основном 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)}">
Другой подход заключается в использовании 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>
напечатает результат выражения для вывода.
Если ваш класс 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";
}
}
}
Затем вы можете вызвать статический метод getStatusDesc, как показано ниже на странице JSP.
Используйте JSTL useBean, чтобы получить класс в верхней части страницы JSP:
<jsp:useBean id="cmnUtilFunc" class="com.test.ejb.util.CommonUtilFunc"/>
Затем вызовите функцию там, где вам нужно, используя язык выражений:
<table>
<td>${cmnUtilFunc.getStatusDesc('A')}</td>
</table>
Бин как StaticInterface также может быть использован
<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();
}
}
EL 2.2 имеет встроенный механизм вызова методов. Подробнее здесь: сайт оракула. Но он не имеет доступа к статическим методам. Хотя вы можете по-прежнему вызывать это через ссылку на объект. Но я использую другое решение, описанное в этой статье: вызов статического метода из EL
Основываясь на ответе @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"/>
Если вы используете Struts2, вы можете использовать
<s:var name='myVar' value="%{@package.prefix.MyClass#myMethod('param')}"/>
а затем ссылаться на "myVar" в атрибуте html или html tag как ${myVar}
<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>
В этом решении мы присваиваем значение (через основной тег) переменной, а затем извлекаем значение этой переменной в сценарии.
В Struts2 или Webwork2 вы можете использовать это:
<s:set name="tourLanguage" value="@foo.bar.TourLanguage@getTour(#name)"/>
Тогда ссылка #tourLanguage
в вашем JSP