Bagaimana memanggil metode statis di JSP / EL?


88

Saya baru mengenal JSP. Saya mencoba menghubungkan MySQL dan halaman JSP saya dan berfungsi dengan baik. Tapi inilah yang perlu saya lakukan. Saya memiliki atribut tabel yang disebut "keseimbangan". Ambil dan gunakan untuk menghitung nilai baru yang disebut "jumlah". (Saya tidak mencetak "saldo").

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

Sepertinya scriptlet tidak dapat dimasukkan dalam tag JSTL.

Jawaban:


133

Anda tidak dapat memanggil metode statis secara langsung di EL. EL hanya akan memanggil metode instance.

Mengenai percobaan scriptlet Anda yang gagal , Anda tidak dapat mencampur scriptlet dan EL. Gunakan yang satu atau yang lainnya. Karena scriptlet tidak dianjurkan selama lebih dari satu dekade, Anda harus tetap menggunakan solusi khusus EL.

Anda pada dasarnya memiliki 2 opsi (dengan asumsi keduanya balancedan Calculate#getAmount()adalah double).

  1. Bungkus saja dalam metode instance.

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

    Dan gunakan sebagai gantinya:

    Amount: ${row.amount}
    

  2. Atau, nyatakan Calculate#getAmount()sebagai fungsi EL. Pertama buat /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>
    

    Dan gunakan sebagai berikut:

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

@BalusC Bagaimana jika jsp saya memiliki (menghitung) beberapa nilai dan saya ingin mengirimkannya sebagai parameter ??
Sriram

7
@Sriram: Pertama-tama, apakah Anda yakin bahwa Anda tidak mengacaukan JSP dengan HTML / JS? Cara Anda mengajukan pertanyaan menunjukkan bahwa Anda tampaknya berpikir bahwa JSP berjalan di browser web padahal ini sama sekali tidak benar. JSP adalah produsen kode HTML / CSS / JS. Itu saja. Itu akan memberi Anda sesuatu untuk dipikirkan tentang pertanyaan dan pendekatan Anda.
BalusC

apa yang saya cari :)
aliopi

@PhilipRego: kode jawaban hanya berdasarkan kode yang dimaksud.
BalusC

61

Pendekatan lain adalah dengan menggunakan 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}

Jika Anda melewatkan opsional var="rowBalance"maka <s:eval>akan mencetak hasil ekspresi ke output.


ini bahkan lebih baik! untuk orang lain, Anda bisa memberikan string dalam metode statis dengan menambahkan \ "the_string_argument \" (bukan bagian row.balance). Ini hanya jika metode Anda mengecualikan string. ;) Bersulang!
lalim

3
Anda dapat mengirimkan string dalam tanda kutip tunggal misalnya 'the_string_argument'- tidak perlu menari dengan melarikan diri.
dma_k

Keren, itu berhasil untuk saya di musim semi ... Saya ingin tahu apakah mungkin untuk melakukan 2 kelas ... hanya perlu mengawali kelas dengan T () saya berasumsi ... Ini berhasil untuk apa yang saya lakukan: < s: eval expression = "T (org.jsoup.Jsoup) .clean (orig_text, T (org.jsoup.safety.Whitelist) .none ())" var = "text_stripped_html" /> setara dengan: String text_stripped_html = Jsoup. bersih (orig_text, Whitelist.none ());
armyofda12mnkeys

@msangel: Periksa jawaban lain dalam topik ini.
dma_k

5

Jika kelas Java Anda adalah:

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

Kemudian Anda dapat memanggil metode statis 'getStatusDesc' seperti di bawah ini di halaman JSP.

Gunakan JSTL useBean untuk mendapatkan kelas di bagian atas halaman JSP:

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

Kemudian panggil fungsi di mana Anda perlu menggunakan Expression Language:

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

Ini membantu saya. Bagus!!
Abu Bakar Siddik

4

Bean seperti StaticInterface juga dapat digunakan

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

dan kacang

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

Saya tidak dapat melihat kata kunci statis dalam kode kecuali "Statis" di nama kelas.
Uluk Biy

2
@UlukBiy, Settings.reset()adalah pemanggilan metode statis. Lukas mengusulkan untuk membuat ManagedBean mirip pembungkus dengan metode non-statis untuk setiap metode statis, yang ingin dipanggil dari EL. Itu solusi yang valid.
Vsevolod Golovanov

3

EL 2.2 memiliki mekanisme inbuild dari metode pemanggilan. Lebih lanjut di sini: situs oracle . Tetapi tidak memiliki akses ke metode statis. Meskipun Anda masih dapat menyebutnya melalui referensi objek. Tetapi saya menggunakan solusi lain, yang dijelaskan dalam artikel ini: Memanggil Metode Statis Dari EL


1
Saya akan khawatir bahwa EL 2.2 benar-benar menambahkan dukungan built-in untuk memanggil metode statis. Solusinya didasarkan pada memasukkan kacang ke dalam konteks permintaan dan (jelek) emulasi peta + parameter yang diperlukan diteruskan selama dereferencing. Beban tambahan dari pendekatan ini adalah bahwa seseorang perlu memijat konteks permintaan (misalnya dalam <web-app> → <filter>).
dma_k

2

Jika Anda menggunakan struts2, Anda bisa menggunakan

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

dan kemudian mereferensikan 'myVar' dalam atribut tag html atau html sebagai ${myVar}


1
Struts bukanlah JSP, seperti yang dikatakan penanya.
bogdan.mustiata

2

Berdasarkan jawaban @Lukas Anda dapat menggunakan metode kacang dan panggilan itu dengan refleksi:

@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, menjadi tombol perintah misalnya:

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

Tidak mungkin menggunakan argumen variabel dalam ekspresi metode EL (2.2).
Robert Kornmesser

Hai Robert, maaf apa maksud Anda sebenarnya, saya telah menggunakan kode itu untuk waktu yang lama, dan saya yakin itu berhasil. Dimana kesalahan saya?
Juan

Saya tidak menemukan spesifikasi sebenarnya, tetapi seperti yang disebutkan BalusC di sini stackoverflow.com/questions/15560508/… inilah alasannya SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (http-localhost/127.0.0.1:8080-5) java.lang.IllegalArgumentException: wrong number of arguments.
Robert Kornmesser

Ya, Anda tidak dapat menggunakan argumen variabel di EL. Tapi Anda bisa menggunakan metode itu dari EL. Ini dapat digunakan untuk meneruskan array sebagai argumen terakhir. Dalam hal ini tidak perlu karena hanya ada satu objek yang diteruskan sebagai argumen terakhir.
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>

Dalam solusi ini, kami menetapkan nilai (Melalui tag inti) ke variabel dan kemudian kami mengambil nilai variabel tersebut dalam skrip.


0

Di Struts2 atau Webwork2, Anda dapat menggunakan ini:

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

Kemudian referensi #tourLanguagedi jsp Anda

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.