JSP / EL에서 정적 메소드를 호출하는 방법은 무엇입니까?


88

저는 JSP를 처음 사용합니다. MySQL과 내 JSP 페이지를 연결하려고 시도했는데 제대로 작동합니다. 그러나 여기에 내가해야 할 일이 있습니다. "균형"이라는 테이블 속성이 있습니다. 이를 검색하여 "amount"라는 새 값을 계산하는 데 사용합니다. (저는 "잔액"을 인쇄하지 않습니다).

 <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 가지 옵션이 있습니다 (두 가정을 balance하고 Calculate#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에 일부 값이 있고 (계산 된) 매개 변수로 보내려면 어떻게해야합니까 ??
Sriram

7
@Sriram : 우선, JSP와 HTML / JS를 혼동하지 않습니까? 질문을 던지는 방식은 JSP가 웹 브라우저에서 실행되지만 이것이 완전히 사실이 아니라고 생각한다는 것을 나타냅니다. JSP는 HTML / CSS / JS 코드 생산자입니다. 그게 다야. 그것은 당신의 질문과 접근에 대해 생각할 무언가를 줄 것입니다.
BalusC 2011

내가 뭘 찾고 있었는지 :)
aliopi

@PhilipRego : 답변의 코드는 해당 코드를 기반으로합니다.
BalusC

61

또 다른 접근 방식은 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}

선택 사항 var="rowBalance"을 건너 뛰면 <s:eval>출력 할 표현식의 결과가 인쇄됩니다.


이것은 더 좋습니다! 다른 경우에는 (row.balance 부분 대신) \ "the_string_argument \"를 추가하여 정적 메서드에 문자열을 제공 할 수 있습니다. 방법이 문자열을 제외한 경우에만 해당됩니다. ;) 건배!
독재

3
작은 따옴표로 문자열을 전달할 수 있습니다 'the_string_argument'.
dma_k

멋지다, 봄에 나를 위해 일했다 ... 2 개의 클래스를 할 수 있는지 궁금했습니다 ... clas 앞에 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

@msangel :이 항목의 다른 답변을 확인하십시오.
dma_k 2013-09-11

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"/>

그런 다음 Expression Language를 사용하여 필요한 곳에 함수를 호출하십시오.

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

이것은 저에게 도움이됩니다. 큰!!
Abu Bakar Siddik

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 2014 년

3

EL 2.2에는 메서드를 호출하는 inbuild 메커니즘이 있습니다. 더 많은 곳 : oracle site . 그러나 정적 메서드에는 액세스 할 수 없습니다. 여전히 호출 할 수 있지만 객체 참조를 통해입니다. 하지만이 기사에서 설명한 다른 솔루션을 사용합니다. EL에서 정적 메서드 호출


1
EL 2.2가 실제로 정적 메서드 호출을위한 기본 지원을 추가한다고 생각합니다. 솔루션은 요청 컨텍스트에 빈을 넣는 것을 기반으로하며 (추악한) 에뮬레이션에 맵 + 필수 매개 변수가 역 참조 중에 전달됩니다. 이 접근 방식의 추가 부담은 요청 컨텍스트 (예 :)를 마사지해야한다는 것 <web-app> → <filter>입니다.
dma_k

2

struts2를 사용하는 경우 다음을 사용할 수 있습니다.

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

그런 다음 html 또는 html 태그 속성에서 'myVar'를 다음과 같이 참조하십시오. ${myVar}


1
Struts는 asker가 말한 것처럼 JSP가 아닙니다.
bogdan.mustiata

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

안녕 로버트, 정확히 무슨 뜻인지 미안합니다. 저는 그 코드를 오랫동안 사용해 왔으며 제대로 작동한다고 확신합니다. 내 실수는 어디에 있습니까?
Juan

나는 actuall 사양을 찾지 못했지만 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

예, EL에서 변수 인수를 사용할 수 없습니다. 그러나 EL에서 그 방법을 사용할 수 있습니다. 마지막 인수로 배열을 전달하는 데 사용할 수 있습니다. 이 경우 마지막 인수로 전달 된 개체가 하나뿐이므로 필요하지 않습니다.
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>

이 솔루션에서는 값 (코어 태그를 통해)을 변수에 할당 한 다음 해당 변수의 값을 스크립 렛에서 가져옵니다.


0

Struts2 또는 Webwork2에서 다음을 사용할 수 있습니다.

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

그런 다음 #tourLanguagejsp에서 참조 하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.