Come chiamare un metodo statico in JSP / EL?


88

Sono nuovo in JSP. Ho provato a collegare MySQL e le mie pagine JSP e funziona bene. Ma ecco cosa dovevo fare. Ho un attributo di tabella chiamato "balance". Recuperalo e usalo per calcolare un nuovo valore chiamato "importo". (Non sto stampando "saldo").

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

Sembra non sia possibile inserire scriptlet all'interno dei tag JSTL.

Risposte:


133

Non è possibile richiamare metodi statici direttamente in EL. EL richiamerà solo metodi di istanza.

Per quanto riguarda il tentativo fallito di scriptlet , non è possibile combinare scriptlet ed EL. Usa l'uno o l'altro. Poiché gli scriptlet sono scoraggiati per oltre un decennio, dovresti attenersi a una soluzione solo EL.

Hai fondamentalmente 2 opzioni (assumendo che sia balancee lo Calculate#getAmount()sono double).

  1. Basta avvolgerlo in un metodo di istanza.

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

    E usalo invece:

    Amount: ${row.amount}
    

  2. In alternativa, dichiara Calculate#getAmount()come una funzione EL. Prima crea un /WEB-INF/functions.tldfile:

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

    E usalo come segue:

    <%@taglib uri="http://example.com/functions" prefix="f" %>
    ...
    Amount: ${f:calculateAmount(row.balance)}">
    

@BalusC E se il mio jsp avesse (calcolato) un valore e mi piacerebbe inviarlo come parametro ??
Sriram

7
@Sriram: Prima di tutto, sei sicuro di non confondere JSP con HTML / JS? Il modo in cui poni la domanda indica che sembri pensare che JSP venga eseguito nel browser web mentre questo è completamente falso. JSP è un produttore di codice HTML / CSS / JS. È tutto. Questo dovrebbe darti qualcosa su cui riflettere sulla tua domanda e sul tuo approccio.
BalusC

quello che stavo cercando :)
aliopi

@PhilipRego: il codice in risposta si basa solo sul codice in questione.
BalusC

61

Un altro approccio consiste nell'usare 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}

Se si salta opzionale var="rowBalance"poi <s:eval>stampa il risultato dell'espressione di uscita.


questo è ancora meglio! per altri potresti fornire una stringa nel metodo statico aggiungendo \ "the_string_argument \" (invece della parte row.balance). Questo è solo se il tuo metodo esclude le stringhe. ;) Saluti!
despota

3
Puoi passare le stringhe tra virgolette singole, ad esempio 'the_string_argument', non è necessario ballare con l'escape.
dma_k

Fantastico, questo ha funzionato per me in primavera ... ero curioso di sapere se fosse possibile fare 2 lezioni ... ho solo bisogno di anteporre alla classe una T () presumo ... Questo ha funzionato per quello che stavo facendo: < s: eval expression = "T (org.jsoup.Jsoup) .clean (orig_text, T (org.jsoup.safety.Whitelist) .none ())" var = "text_stripped_html" /> equivalente a: String text_stripped_html = Jsoup. clean (orig_text, Whitelist.none ());
armyofda12mnkeys

@msangel: controlla altre risposte in questo argomento.
dma_k

5

Se la tua classe 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";
        }
    }
}

Quindi puoi chiamare il metodo statico 'getStatusDesc' come di seguito nella pagina JSP.

Usa JSTL useBean per ottenere la classe nella parte superiore della pagina JSP:

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

Quindi chiama la funzione dove richiesto utilizzando Expression Language:

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

Questo è utile per me. Grande!!
Abu Bakar Siddik

4

È possibile utilizzare anche Bean come StaticInterface

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

e fagioli

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();
    }
}

Non riesco a vedere alcuna parola chiave statica nel codice tranne "Static" nel nome della classe.
Uluk Biy

2
@ UlukBiy, Settings.reset()è una chiamata al metodo statico. Lukas propone di creare un ManagedBean tipo wrapper con un metodo non statico per ogni metodo statico, che si desidera chiamare da EL. È una valida soluzione.
Vsevolod Golovanov

3

EL 2.2 ha un meccanismo integrato per chiamare i metodi. Maggiori informazioni qui: sito Oracle . Ma non ha accesso a metodi statici. Anche se puoi ancora chiamarlo tramite riferimento all'oggetto. Ma io uso un'altra soluzione, descritta in questo articolo: Chiamare un metodo statico da EL


1
Sarei contento che EL 2.2 aggiunga davvero un supporto integrato per chiamare un metodo statico. La soluzione si basa sull'inserimento di un bean in contesti di richiesta e (brutte) emulazioni una mappa + i parametri necessari vengono passati durante la dereferenziazione. L'onere aggiuntivo di questo approccio è che è necessario massaggiare il contesto della richiesta (ad esempio in <web-app> → <filter>).
dma_k

2

Se stai usando struts2, potresti usare

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

e quindi fare riferimento a "myVar" nell'attributo tag html o html come ${myVar}


1
Struts non è JSP, come ha detto il richiedente.
bogdan.mustiata

2

Sulla base della risposta di @Lukas puoi usare quel bean e il metodo di chiamata per riflessione:

@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, in un pulsante di comando, ad esempio:

<p:commandButton action="#{staticCaller.call('org.company.Calculate', 'getAmount', row.balance)}" process="@this"/>

Non è possibile utilizzare argomenti variabili nelle espressioni del metodo EL (2.2).
Robert Kornmesser

Ciao Robert, scusa cosa intendi esattamente, ho usato quel codice per molto tempo e sono sicuro che funzioni. Dov'è il mio errore?
Juan

Io non trovate le specifiche actuall, ma come BalusC accenna qui stackoverflow.com/questions/15560508/...~~V~~singular~~3rd questo è il motivo di SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (http-localhost/127.0.0.1:8080-5) java.lang.IllegalArgumentException: wrong number of arguments.
Robert Kornmesser

Sì, non è possibile utilizzare argomenti variabili su EL. Ma puoi usare quel metodo da EL. Può essere utilizzato passando un array come ultimo argomento. In questo caso non è necessario perché c'è un solo oggetto passato come ultimo argomento.
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>

In questa soluzione, stiamo assegnando valore (tramite tag core) a una variabile e quindi stiamo recuperando il valore di quella variabile in scriplet.


0

In Struts2 o Webwork2, puoi usare questo:

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

Quindi riferimento #tourLanguagenel tuo jsp

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.