Як викликати статичний метод у 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.