Comment appeler une méthode statique dans JSP / EL?

88

Je suis nouveau sur JSP. J'ai essayé de connecter MySQL et mes pages JSP et cela fonctionne bien. Mais voici ce que je devais faire. J'ai un attribut de table appelé "balance". Récupérez-le et utilisez-le pour calculer une nouvelle valeur appelée «montant». (Je n'imprime pas "balance").

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

Il semble qu'il n'est pas possible d'insérer des scriptlets dans les balises JSTL.

John
la source

Réponses:

133

Vous ne pouvez pas appeler des méthodes statiques directement dans EL. EL invoquera uniquement les méthodes d'instance.

Quant à l'échec de votre tentative de scriptlet , vous ne pouvez pas mélanger des scriptlets et EL. Utilisez l'un ou l'autre. Étant donné que les scriptlets sont découragés pendant une décennie, vous devez vous en tenir à une solution exclusivement EL.

Vous avez essentiellement 2 options (en supposant les deux balanceet Calculate#getAmount()sont double).

  1. Enveloppez-le simplement dans une méthode d'instance.

    public double getAmount() {
        return Calculate.getAmount(balance);
    }
    

    Et utilisez-le à la place:

    Amount: ${row.amount}
    

  2. Ou déclarez en Calculate#getAmount()tant que fonction EL. Créez d'abord un /WEB-INF/functions.tldfichier:

    <?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>
    

    Et utilisez-le comme suit:

    <%@taglib uri="http://example.com/functions" prefix="f" %>
    ...
    Amount: ${f:calculateAmount(row.balance)}">
    
BalusC
la source
@BalusC Que faire si mon jsp a (calculé) une certaine valeur et que j'aimerais l'envoyer en tant que paramètre ??
Sriram
7
@Sriram: Tout d'abord, êtes-vous sûr de ne pas confondre JSP avec HTML / JS? La façon dont vous posez la question indique que vous semblez penser que JSP s'exécute dans le navigateur Web alors que c'est complètement faux. JSP est un producteur de code HTML / CSS / JS. C'est tout. Cela devrait vous permettre de réfléchir à votre question et à votre approche.
BalusC
ce que je cherchais :)
aliopi
@PhilipRego: le code en réponse est juste basé sur le code en question.
BalusC
61

Une autre approche consiste à utiliser 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}

Si vous ignorez facultatif , le résultat de l'expression sera var="rowBalance"alors <s:eval>imprimé.

dma_k
la source
c'est encore mieux! pour d'autres, vous pouvez fournir une chaîne dans la méthode statique en ajoutant \ "the_string_argument \" (au lieu de la partie row.balance). Ce n'est que si votre méthode exclut les chaînes. ;) À votre santé!
despote
3
Vous pouvez passer des chaînes entre guillemets simples, par exemple 'the_string_argument'- pas besoin de danser avec l'échappement.
dma_k
Cool, cela a fonctionné pour moi au printemps ... J'étais curieux de savoir s'il était possible de faire 2 classes ... juste besoin de préfixer la classe avec un T () je suppose ... Cela a fonctionné pour ce que je faisais: < s: eval expression = "T (org.jsoup.Jsoup) .clean (orig_text, T (org.jsoup.safety.Whitelist) .none ())" var = "text_stripped_html" /> équivalent à: String text_stripped_html = Jsoup. clean (orig_text, Whitelist.none ());
armyofda12mnkeys
@msangel: Vérifiez les autres réponses dans cette rubrique.
dma_k du
5

Si votre classe Java est:

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

Ensuite, vous pouvez appeler la méthode statique 'getStatusDesc' comme ci-dessous dans la page JSP.

Utilisez JSTL useBean pour obtenir la classe en haut de la page JSP:

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

Ensuite, appelez la fonction où vous avez besoin d'utiliser le langage d'expression:

<table>
    <td>${cmnUtilFunc.getStatusDesc('A')}</td>
</table>
Sahan Marasinghe
la source
Ceci est utile pour moi. Génial!!
Abu Bakar Siddik
4

Bean comme StaticInterface peut également être utilisé

<h:commandButton value="reset settings" action="#{staticinterface.resetSettings}"/>

et haricot

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();
    }
}
Lukas
la source
Je ne vois aucun mot-clé statique dans le code sauf "Static" dans le nom de la classe.
Uluk Biy
2
@UlukBiy, le Settings.reset()est un appel de méthode statique. Lukas propose de créer un ManagedBean de type wrapper avec une méthode non statique pour chaque méthode statique, que l'on veut appeler depuis EL. C'est une solution valable.
Vsevolod Golovanov
3

EL 2.2 a un mécanisme inbuild pour appeler des méthodes. Plus ici: site oracle . Mais il n'a pas accès aux méthodes statiques. Bien que vous puissiez toujours l'appeler via une référence d'objet. Mais j'utilise une autre solution, décrite dans cet article: Appel d'une méthode statique depuis EL

msangel
la source
1
Je dirais que EL 2.2 ajoute vraiment un support intégré pour appeler une méthode statique. Les solutions sont basées sur la mise d'un bean dans des contextes de requêtes et des émulations (moche) une carte + les paramètres nécessaires sont passés lors du déréférencement. Le fardeau supplémentaire de cette approche est qu'il faut masser le contexte de la demande (par exemple dans <web-app> → <filter>).
dma_k le
2

Si vous utilisez struts2, vous pouvez utiliser

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

puis référencez «myVar» dans l'attribut de balise html ou html comme ${myVar}

dhblah
la source
1
Struts n'est pas JSP, comme l'a dit le demandeur.
bogdan.mustiata
2

Sur la base de la réponse @Lukas, vous pouvez utiliser ce bean et appeler la méthode par réflexion:

@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, dans un bouton de commande par exemple:

<p:commandButton action="#{staticCaller.call('org.company.Calculate', 'getAmount', row.balance)}" process="@this"/>
Juan
la source
Il n'est pas possible d'utiliser des arguments variables dans les expressions de méthode EL (2.2).
Robert Kornmesser
Salut Robert, désolé ce que tu veux dire exactement, j'utilise ce code depuis longtemps, et je suis sûr que ça marche. Où est mon erreur?
Juan
Je ne trouve pas les spécifications actuelles, mais comme BalusC le mentionne ici, stackoverflow.com/questions/15560508/ ... c'est la raison de SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (http-localhost/127.0.0.1:8080-5) java.lang.IllegalArgumentException: wrong number of arguments.
Robert Kornmesser
Oui, vous ne pouvez pas utiliser d'arguments variables sur EL. Mais vous pouvez utiliser cette méthode d'EL. Il peut être utilisé en passant un tableau comme dernier argument. Dans ce cas, ce n'est pas nécessaire car il n'y a qu'un seul objet passé en dernier argument.
Juan
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>

Dans cette solution, nous attribuons une valeur (via la balise principale) à une variable, puis nous récupérons la valeur de cette variable dans scriplet.

cendre9
la source
0

Dans Struts2 ou Webwork2, vous pouvez utiliser ceci:

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

Puis référence #tourLanguagedans votre jsp

sendon1982
la source