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つのオプションがあります(balanceCalculate#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に(計算された)値があり、それをパラメーターとして送信したい場合はどうなりますか?
スリラム2012年

7
@Sriram:まず、JSPとHTML / JSを混同していないことを確認しますか?あなたが質問をする方法は、これが完全に真実ではないのに、JSPがウェブブラウザで実行されているとあなたが思っているように見えることを示しています。JSPはHTML / CSS / JSコードプロデューサーです。それで全部です。それはあなたにあなたの質問とアプローチについて考える何かを与えるはずです。
BalusC 2012年

私が探していたもの:)
aliopi

@PhilipRego:回答のコードは、問題のコードに基づいています。
BalusC

61

別のアプローチは、SpringSpELを使用することです。

<%@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部分の代わりに)\ "the_string_argument \"を追加することで、静的メソッドに文字列を指定できます。これは、メソッドが文字列を除く場合のみです。;)乾杯!
専制君主

3
文字列を一重引用符で囲むことができます。たとえば'the_string_argument'、エスケープして踊る必要はありません。
dma_k 2012年

かっこいい、それは春に私のために働いた... 2つのクラスを行うことが可能かどうか興味があった...私が推測するT()をクラスの前に付ける必要がある...これは私がやっていたことのために働いた:< s:eval expression = "T(org.jsoup.Jsoup).clean(orig_text、T(org.jsoup.safety.Whitelist).none())" var = "text_stripped_html" />と同等:String text_stripped_html = Jsoup。 clean(orig_text、Whitelist.none());
armyofda12mnkeys 2013

@msangel:このトピックの他の回答を確認してください。
dma_k 2013

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

次に、JSPページで以下のように静的メソッド 'getStatusDesc'を呼び出すことができます。

JSTL useBeanを使用して、JSPページの上部にクラスを取得します。

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

次に、式言語を使用して、必要な場所で関数を呼び出します。

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

これは私にとって役に立ちます。すごい!!
Abu Bakar Siddik 2018

4

StaticInterfaceのようなBeanも使用できます

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

クラス名の「Static」以外の静的キーワードがコードに表示されません。
Uluk Biy 2013

2
@UlukBiy、これSettings.reset()は静的メソッド呼び出しです。Lukasは、ELから呼び出したい静的メソッドごとに非静的メソッドを使用してラッパーのようなManagedBeanを作成することを提案しています。それは有効な解決策です。
Vsevolod Golovanov

3

EL 2.2には、メソッドを呼び出す組み込みメカニズムがあります。詳細はこちら:oracleサイト。ただし、静的メソッドにはアクセスできません。あなたはそれをオブジェクト参照を介して呼び出すことができますが。しかし、私はこの記事で説明されている別のソリューションを使用しています:ELから静的メソッドを呼び出す


1
EL 2.2には、静的メソッドを呼び出すための組み込みサポートが実際に追加されていると思います。このソリューションは、Beanをリクエストコンテキストに配置することに基づいており、(醜い)エミュレーションマップ+必要なパラメータが間接参照中に渡されます。このアプローチの追加の負担は、リクエストコンテキストをマッサージする必要があることです(例:)<web-app> → <filter>
dma_k 2013

2

struts2を使用している場合は、

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

次に、htmlまたはhtmlタグ属性の「myVar」を次のように参照します。 ${myVar}


1
アスカーが言ったように、StrutsはJSPではありません。
bogdan.mustiata 2016

2

@Lukasの回答に基づいて、そのBeanを使用し、リフレクションによってメソッドを呼び出すことができます。

@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)メソッド式で変数引数を使用することはできません。
Robert Kornmesser 2016年

こんにちはロバート、申し訳ありませんが、正確にはどういう意味ですか、私は長い間そのコードを使用してきました、そしてそれはうまくいくと確信しています。私の間違いはどこにありますか?
フアン

実際の仕様は見つかりませんが、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
Robert Kornmesser 2016年

はい、ELで可変引数を使用することはできません。ただし、ELからそのメソッドを使用できます。最後の引数として配列を渡すことで使用できます。この場合、最後の引数として渡されるオブジェクトは1つだけなので、これは必要ありません。
フアン

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>

このソリューションでは、変数にvalue(Through core tag)を割り当ててから、その変数の値をスクリプトレットでフェッチします。


0

Struts2またはWebwork2では、次を使用できます。

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

次に#tourLanguage、jspで参照します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.