Як викликати статичний метод у JSP / EL?


88

Я новачок у 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.

Відповіді:


133

Ви не можете викликати статичні методи безпосередньо в EL. EL буде викликати лише методи екземпляра.

Що стосується вашої невдалої спроби скриплету , ви не можете змішувати скриплети та EL. Використовуйте те чи інше. Оскільки скриплети не рекомендуються впродовж десяти років, вам слід дотримуватися рішення лише для EL.

У вас є в основному 2 варіанти (припускаючи обидва balanceі Calculate#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 має (обчислює) якесь значення, і я хотів би надіслати це як параметр ??
Шрірам

7
@Sriram: Перш за все, ви впевнені, що не плутаєте JSP з HTML / JS? Те, як ви ставите питання, вказує на те, що ви, здається, думаєте, що JSP працює у веб-браузері, хоча це абсолютно неправда. 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>надрукує результат виразу для виведення.


це ще краще! для інших ви можете надати рядок у статичному методі, додавши \ "аргумент__струнка \" (замість частини row.balance). Це лише в тому випадку, якщо ваш метод не містить рядків. ;) Вітаємо!
деспот

3
Ви можете передавати струни в одинарних лапках, наприклад 'the_string_argument'- не потрібно танцювати з втечею.
dma_k

Класно, це працювало у мене навесні ... Мені було цікаво, чи можна робити 2 класи ... просто потрібно поставити префікс до класу 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. очистити (orig_text, Whitelist.none ());
armyofda12mnkeys

@msangel: Перевірте інші відповіді в цій темі.
dma_k

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";
        }
    }
}

Тоді ви можете викликати статичний метод 'getStatusDesc', як показано нижче на сторінці JSP.

Використовуйте JSTL useBean, щоб отримати клас вгорі сторінки JSP:

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

Потім викличте функцію там, де вам потрібно, використовуючи Expression Language:

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

Це мені корисно. Чудово !!
Абу Бакар Сіддік

4

Також може використовуватися бін, подібний 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();
    }
}

Я не бачу жодного статичного ключового слова в коді, крім "Статичний" в назві класу.
Uluk Biy

2
@UlukBiy, Settings.reset()це виклик статичного методу. Лукас пропонує створити подібний обгортці ManagedBean з нестатичним методом для кожного статичного методу, який потрібно викликати з EL. Це дійсне рішення.
Всеволод Голованов

3

EL 2.2 має вбудований механізм виклику методів. Більше тут: сайт oracle . Але він не має доступу до статичних методів. Хоча ви все ще можете назвати це за допомогою посилання на об'єкт. Але я використовую інше рішення, описане в цій статті: Виклик статичного методу з EL


1
Я міг би сказати, що EL 2.2 дійсно додає вбудовану підтримку для виклику статичного методу. Рішення засновані на введенні компонента в контекст запиту та (потворних) емуляціях, карта + необхідні параметри передаються під час розмежування посилань. Додатковим навантаженням цього підходу є те, що потрібно масажувати контекст запиту (наприклад, в <web-app> → <filter>).
dma_k

2

Якщо ви використовуєте struts2, ви можете використовувати

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

а потім посилатися на 'myVar' в атрибуті html або html тегу як ${myVar}


1
Struts - це не JSP, як сказав допитувач.
bogdan.mustiata

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).
Роберт Корнмессер,

Привіт, Роберте, вибачте, що ви точно маєте на увазі, я давно використовую цей код, і я впевнений, що він працює. Де моя помилка?
Хуан

Я не знайшов actuall специфікації, але , як 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>

У цьому рішенні ми призначаємо значення (Через основний тег) змінній, а потім отримуємо значення цієї змінної в скрипті.


0

У Struts2 або Webwork2 ви можете використовувати це:

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

Потім посилання #tourLanguageу вашому jsp

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.