Wie rufe ich eine statische Methode in JSP / EL auf?


87

Ich bin neu in JSP. Ich habe versucht, MySQL und meine JSP-Seiten zu verbinden, und es funktioniert einwandfrei. Aber hier ist, was ich tun musste. Ich habe ein Tabellenattribut namens "balance". Rufen Sie es ab und verwenden Sie es, um einen neuen Wert namens "Betrag" zu berechnen. (Ich drucke nicht "Balance").

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

Es scheint nicht möglich zu sein, Scriptlets in JSTL-Tags einzufügen.

Antworten:


131

Sie können statische Methoden nicht direkt in EL aufrufen. EL ruft nur Instanzmethoden auf.

In Bezug auf Ihren fehlgeschlagenen Scriptlet- Versuch können Sie Scriptlets und EL nicht mischen . Verwenden Sie den einen oder anderen. Da Scriptlets sind entmutigt mehr als einem Jahrzehnt, sollten Sie auf eine EL-only Lösung bleiben.

Sie haben grundsätzlich 2 Möglichkeiten (vorausgesetzt beide balanceund Calculate#getAmount()sind double).

  1. Wickeln Sie es einfach in eine Instanzmethode.

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

    Und benutze es stattdessen:

    Amount: ${row.amount}

  2. Oder deklarieren Sie Calculate#getAmount()als EL-Funktion. Erstellen Sie zuerst eine /WEB-INF/functions.tldDatei:

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

    Und verwenden Sie es wie folgt:

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

@BalusC Was ist, wenn mein JSP einen Wert hat (berechnet) und ich diesen als Parameter senden möchte?
Sriram

7
@Sriram: Sind Sie sicher, dass Sie JSP nicht mit HTML / JS verwechseln? Die Art und Weise, wie Sie die Frage stellen, deutet darauf hin, dass Sie anscheinend glauben, dass JSP im Webbrowser ausgeführt wird, während dies völlig falsch ist. JSP ist ein HTML / CSS / JS-Codeproduzent. Das ist alles. Das sollte Ihnen etwas zum Nachdenken über Ihre Frage und Ihren Ansatz geben.
BalusC

was ich gesucht habe :)
Aliopi

@PhilipRego: Der Code in der Antwort basiert nur auf dem fraglichen Code.
BalusC

61

Ein anderer Ansatz ist die Verwendung von 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}

Wenn Sie überspringen optional var="rowBalance"dann <s:eval>wird das Ergebnis des Ausdrucks zur Ausgabe drucken.


das ist noch besser! Für andere können Sie eine Zeichenfolge in der statischen Methode angeben, indem Sie "the_string_argument" (anstelle des Teils "row.balance") hinzufügen. Dies ist nur möglich, wenn Ihre Methode Zeichenfolgen ausschließt. ;) Prost!
Despot

3
Sie können Zeichenfolgen in einfachen Anführungszeichen übergeben, z. B. müssen Sie 'the_string_argument'nicht mit Flucht tanzen.
dma_k

Cool, das hat bei mir im Frühling funktioniert ... Ich war neugierig, ob es möglich ist, 2 Klassen zu absolvieren ... Ich muss den Klassen nur ein T () voranstellen, nehme ich an ... Das hat für das funktioniert, was ich getan habe: < s: eval expression = "T (org.jsoup.Jsoup) .clean (orig_text, T (org.jsoup.safety.Whitelist) .none ())" var = "text_stripped_html" /> entspricht: String text_stripped_html = Jsoup. clean (orig_text, Whitelist.none ());
Armyofda12mnkeys

@msangel: Überprüfen Sie andere Antworten in diesem Thema.
dma_k

4

Bean wie StaticInterface kann ebenfalls verwendet werden

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

und Bohne

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

Ich kann kein statisches Schlüsselwort im Code außer "Statisch" im Klassennamen sehen.
Uluk Biy

2
@UlukBiy, das Settings.reset()ist ein statischer Methodenaufruf. Lukas schlägt vor, für jede statische Methode, die von EL aufgerufen werden soll, eine wrapperartige ManagedBean mit einer nicht statischen Methode zu erstellen. Es ist eine gültige Lösung.
Vsevolod Golovanov

4

Wenn Ihre Java-Klasse ist:

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

Anschließend können Sie die statische Methode 'getStatusDesc' wie unten auf der JSP-Seite aufrufen.

Verwenden Sie JSTL useBean, um die Klasse oben auf der JSP-Seite abzurufen:

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

Rufen Sie dann die gewünschte Funktion mit Expression Language auf:

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

Das ist hilfreich für mich. Toll!!
Abu Bakar Siddik

3

EL 2.2 verfügt über einen eingebauten Mechanismus zum Aufrufen von Methoden. Mehr hier: Orakelseite . Es hat jedoch keinen Zugriff auf statische Methoden. Sie können es aber immer noch über eine Objektreferenz aufrufen. Aber ich benutze eine andere Lösung, die in diesem Artikel beschrieben wird: Aufrufen einer statischen Methode von EL


1
Ich würde sagen, dass EL 2.2 wirklich eine integrierte Unterstützung für den Aufruf einer statischen Methode hinzufügt. Die Lösung basiert darauf, eine Bean in Anforderungskontexte zu setzen und (hässliche) Emulationen einer Karte + notwendige Parameter während der Dereferenzierung zu übergeben. Die zusätzliche Belastung dieses Ansatzes besteht darin, dass man den Anforderungskontext (z <web-app> → <filter>. B. in ) massieren muss .
dma_k

2

Wenn Sie struts2 verwenden, können Sie verwenden

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

und verweisen Sie dann auf 'myVar' im HTML- oder HTML-Tag-Attribut als ${myVar}


1
Struts ist keine JSP, wie der Fragesteller sagte.
Bogdan.mustiata

2

Basierend auf der Antwort von @Lukas können Sie diese Bean- und Call-Methode durch Reflektion verwenden:

@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 eine Befehlsschaltfläche zum Beispiel:

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

Es ist nicht möglich, variable Argumente in EL (2.2) -Methodenausdrücken zu verwenden.
Robert Kornmesser

Hallo Robert, tut mir leid, was meinst du genau? Ich habe diesen Code schon lange verwendet und bin mir sicher, dass er funktioniert. Wo ist mein Fehler?
Juan

Ich finde die tatsächliche Spezifikation nicht, aber wie BalusC hier erwähnt, ist stackoverflow.com/questions/15560508/… der Grund dafür SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (http-localhost/127.0.0.1:8080-5) java.lang.IllegalArgumentException: wrong number of arguments.
Robert Kornmesser

Ja, Sie können keine variablen Argumente für EL verwenden. Sie können diese Methode jedoch von EL aus verwenden. Es kann verwendet werden, indem ein Array als letztes Argument übergeben wird. In diesem Fall ist dies nicht erforderlich, da nur ein Objekt als letztes Argument übergeben wird.
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 dieser Lösung weisen wir einer Variablen einen Wert (Through Core Tag) zu und rufen dann den Wert dieser Variablen in Scriplet ab.


0

In Struts2 oder Webwork2 können Sie Folgendes verwenden:

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

Dann referenzieren Sie #tourLanguagein Ihrem jsp

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.