webentwicklung-frage-antwort-db.com.de

Wie referenziere ich Konstanten in EL?

Wie verweisen Sie auf Konstanten mit EL auf einer JSP-Seite?

Ich habe eine Schnittstelle Addresses mit einer Konstante namens URL. Ich weiß, dass ich mit einem Skript darauf verweisen kann, indem ich gehe: <%=Addresses.URL%>, aber wie mache ich das mit EL?

102
tau-neutrino

EL 3.0 oder neuer

Wenn Sie bereits mit Java EE 7/EL 3.0 arbeiten, importiert der @page import auch Klassenkonstanten im EL-Bereich.

<%@ page import="com.example.YourConstants" %>

Dies wird unter den Deckblättern über ImportHandler#importClass() importiert und steht als ${YourConstants.FOO} zur Verfügung.

Beachten Sie, dass alle Java.lang.*-Klassen bereits implizit importiert wurden und wie folgt verfügbar sind: ${Boolean.TRUE} und ${Integer.MAX_VALUE}. Dies erfordert nur einen neueren Java EE 7-Container-Server, da in früheren Versionen Fehler aufgetreten sind. Beispiel: GlassFish 4.0 und Tomcat 8.0.0-1x schlagen fehl, GlassFish 4.1+ und Tomcat 8.0.2x + funktionieren jedoch Und Sie müssen unbedingt sicherstellen, dass Ihr web.xml als konform mit der neuesten vom Server unterstützten Servlet-Version deklariert ist. Bei einem web.xml, der als konform mit Servlet 2.5 oder älter deklariert ist, funktioniert keine der Servlet 3.0+ -Funktionen.

Beachten Sie auch, dass diese Funktion nur in JSP und nicht in Facelets verfügbar ist. Im Fall von JSF + Facelets verwenden Sie am besten OmniFaces <o:importConstants> wie folgt:

<o:importConstants type="com.example.YourConstants" />

Oder fügen Sie einen EL-Kontext-Listener hinzu, der ImportHandler#importClass() wie folgt aufruft:

@ManagedBean(eager=true)
@ApplicationScoped
public class Config {

    @PostConstruct
    public void init() {
        FacesContext.getCurrentInstance().getApplication().addELContextListener(new ELContextListener() {
            @Override
            public void contextCreated(ELContextEvent event) {
                event.getELContext().getImportHandler().importClass("com.example.YourConstants");
            }
        });
    }

}

EL 2.2 oder älter

Dies ist in EL 2.2 und älter nicht möglich. Es gibt verschiedene Alternativen:

  1. Fügen Sie sie in einen Map<String, Object> ein, den Sie in den Anwendungsbereich einfügen. In EL kann auf Kartenwerte auf die übliche Javabean-Weise über ${map.key} oder ${map['key.with.dots']} zugegriffen werden.

  2. Verwenden Sie <un:useConstants> der Unstandard Taglib (maven2 repo hier ):

    <%@ taglib uri="http://jakarta.Apache.org/taglibs/unstandard-1.0" prefix="un" %>
    <un:useConstants className="com.example.YourConstants" var="constants" />
    

    Auf diese Weise sind sie auf die übliche Javabean-Weise über ${constants.FOO} zugänglich.

  3. Verwenden Sie Javaranchs CCC <ccc:constantsMap>, wie unten in in diesem Artikel beschrieben.

    <%@ taglib uri="http://bibeault.org/tld/ccc" prefix="ccc" %>
    <ccc:constantsMap className="com.example.YourConstants" var="constants" />
    

    Auf diese Weise sind sie auch über ${constants.FOO} auf die übliche Javabean-Art zugänglich.

  4. Wenn Sie JSF2 verwenden, können Sie <o:importConstants> of OmniFaces verwenden.

    <html ... xmlns:o="http://omnifaces.org/ui">
    <o:importConstants type="com.example.YourConstants" />
    

    Auf diese Weise sind sie auch über #{YourConstants.FOO} auf die übliche Javabean-Art zugänglich.

  5. Erstellen Sie eine Wrapper-Klasse, die sie über Get-Methoden im Javabean-Stil zurückgibt.

  6. Erstellen Sie einen benutzerdefinierten EL-Resolver, der zuerst das Vorhandensein einer Konstanten überprüft und bei Abwesenheit an den Standard-Resolver delegiert, andernfalls wird stattdessen der Konstantenwert zurückgegeben.

151
BalusC

Das Folgende gilt nicht für EL im Allgemeinen, sondern nur für SpEL (Spring EL) (getestet mit 3.2.2.RELEASE auf Tomcat 7). Ich halte es für erwähnenswert, wenn jemand nach JSP und EL sucht (aber JSP mit Spring verwendet).

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<spring:eval var="constant" expression="T(com.example.Constants).CONSTANT"/>
11
anre

Normalerweise platzieren Sie diese Art von Konstanten in einem Configuration -Objekt (das Getter und Setter enthält) im Servlet-Kontext und greifen mit ${applicationScope.config.url} Darauf zu.

9
Bozho

Das kannst du nicht. Es folgt der Java Bean-Konvention. Sie müssen also einen Getter dafür haben.

6
Adeel Ansari

Auf statische Eigenschaften kann in EL nicht zugegriffen werden. Die Problemumgehung, die ich verwende, besteht darin, eine nicht statische Variable zu erstellen, die sich dem statischen Wert selbst zuordnet.

public final static String MANAGER_ROLE = 'manager';
public String manager_role = MANAGER_ROLE;

Ich benutze Lombok, um den Getter und Setter zu generieren. Ihre EL sieht folgendermaßen aus:

${bean.manager_role}

Vollständiger Code unter http://www.ninthavenue.com.au/Java-static-constants-in-jsp-and-jsf-el

5
Roger Keays

Ich habe umgesetzt wie:

public interface Constants{
    Integer PAGE_SIZE = 20;
}

-

public class JspConstants extends HashMap<String, String> {

        public JspConstants() {
            Class c = Constants.class;
            Field[] fields = c.getDeclaredFields();
            for(Field field : fields) {
                int modifier = field.getModifiers();
                if(Modifier.isPublic(modifier) && Modifier.isStatic(modifier) && Modifier.isFinal(modifier)) {
                    try {
                        Object o = field.get(null);
                        put(field.getName(), o != null ? o.toString() : null);
                    } catch(IllegalAccessException ignored) {
                    }
                }
            }
        }

        @Override
        public String get(Object key) {
            String result = super.get(key);
            if(StringUtils.isEmpty(result)) {
                throw new IllegalArgumentException("Check key! The key is wrong, no such constant!");
            }
            return result;
        }
    }

Im nächsten Schritt fügen Sie die Instanz dieser Klasse in servlerContext ein

public class ApplicationInitializer implements ServletContextListener {


    @Override
    public void contextInitialized(ServletContextEvent sce) {
        sce.getServletContext().setAttribute("Constants", new JspConstants());
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}

fügen Sie den Listener zu web.xml hinzu

<listener>
    <listener-class>com.example.ApplicationInitializer</listener-class>
</listener>

zugriff in jsp

${Constants.PAGE_SIZE}
5

Ich definiere gleich zu Beginn eine Konstante in meinem jsp:

<%final String URI = "http://www.example.com/";%>

Ich füge die Kern-Taglib in meine JSP ein:

<%@taglib prefix="c" uri="http://Java.Sun.com/jsp/jstl/core"%>

Dann stelle ich EL die Konstante mit folgender Anweisung zur Verfügung:

<c:set var="URI" value="<%=URI%>"></c:set>

Jetzt kann ich es später verwenden. Hier ein Beispiel, in dem der Wert nur als HTML-Kommentar für Debugging-Zwecke geschrieben wird:

<!-- ${URI} -->

Mit Ihrer Konstantenklasse können Sie einfach Ihre Klasse importieren und die Konstanten lokalen Variablen zuweisen. Ich weiß, dass meine Antwort eine Art schneller Hack ist, aber die Frage taucht auch auf, wenn man Konstanten direkt in der JSP definieren möchte.

4
koppor

Ja, du kannst. Sie benötigen ein benutzerdefiniertes Tag (falls Sie es nicht woanders finden können). Ich habe das gemacht:

package something;

import Java.lang.reflect.Field;
import Java.lang.reflect.Modifier;
import Java.util.Map;
import Java.util.TreeMap;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

import org.Apache.taglibs.standard.tag.el.core.ExpressionUtil;

/**
 * Get all class constants (statics) and place into Map so they can be accessed
 * from EL.
 * @author Tim.sabin
 */
public class ConstMapTag extends TagSupport {
    public static final long serialVersionUID = 0x2ed23c0f306L;

    private String path = "";
    private String var = "";

    public void setPath (String path) throws JspException {
        this.path = (String)ExpressionUtil.evalNotNull ("constMap", "path",
          path, String.class, this, pageContext);
    }

    public void setVar (String var) throws JspException {
        this.var = (String)ExpressionUtil.evalNotNull ("constMap", "var",
          var, String.class, this, pageContext);
    }

    public int doStartTag () throws JspException {
        // Use Reflection to look up the desired field.
        try {
            Class<?> clazz = null;
            try {
                clazz = Class.forName (path);
            } catch (ClassNotFoundException ex) {
                throw new JspException ("Class " + path + " not found.");
            }
            Field [] flds = clazz.getDeclaredFields ();
            // Go through all the fields, and put static ones in a Map.
            Map<String, Object> constMap = new TreeMap<String, Object> ();
            for (int i = 0; i < flds.length; i++) {
                // Check to see if this is public static final. If not, it's not a constant.
                int mods = flds [i].getModifiers ();
                if (!Modifier.isFinal (mods) || !Modifier.isStatic (mods) ||
                  !Modifier.isPublic (mods)) {
                    continue;
                }
                Object val = null;
                try {
                    val = flds [i].get (null);    // null for static fields.
                } catch (Exception ex) {
                    System.out.println ("Problem getting value of " + flds [i].getName ());
                    continue;
                }
                // flds [i].get () automatically wraps primitives.
                // Place the constant into the Map.
                constMap.put (flds [i].getName (), val);
            }
            // Export the Map as a Page variable.
            pageContext.setAttribute (var, constMap);
        } catch (Exception ex) {
            if (!(ex instanceof JspException)) {
                throw new JspException ("Could not process constants from class " + path);
            } else {
                throw (JspException)ex;
            }
        }
        return SKIP_BODY;
    }
}

und der tag heißt:

<yourLib:constMap path="path.to.your.constantClass" var="consts" />

Alle öffentlichen statischen Endvariablen werden in eine Map eingefügt, die mit ihrem Java name indiziert ist

public static final int MY_FIFTEEN = 15;

dann wird das Tag dies in eine Ganzzahl umschließen und Sie können es in einer JSP referenzieren:

<c:if test="${consts['MY_FIFTEEN'] eq 15}">

und du musst keine Getter schreiben!

3
Tim Sabin

Sie können. Versuchen Sie es auf folgende Weise

 #{T(com.example.Addresses).URL}

Getestet auf Tomcat 7 und Java6

3

@Bozho hat schon eine tolle Antwort geliefert

Normalerweise platzieren Sie diese Art von Konstanten in einem Configuration-Objekt (mit Getters und Setters) im Servlet-Kontext und greifen mit $ {applicationScope.config.url} darauf zu.

Ich bin jedoch der Meinung, dass ein Beispiel benötigt wird, um mehr Klarheit zu schaffen und jemandem Zeit zu sparen

@Component
public Configuration implements ServletContextAware {
    private String addressURL = Addresses.URL;

    // Declare other properties if you need as also add corresponding
    // getters and setters

    public String getAddressURL() {
        return addressURL;
    }

    public void setServletContext(ServletContext servletContext) {
        servletContext.setAttribute("config", this);
    }
}
2
lunohodov

Selbst wenn ich weiß, dass es etwas spät ist, und selbst wenn ich weiß, dass dies ein kleiner Hack ist, habe ich die folgende Lösung verwendet, um das gewünschte Ergebnis zu erzielen. Wenn Sie ein Liebhaber von Java-Namenskonventionen sind, ist mein Rat, hier nicht mehr zu lesen ...

Eine Klasse wie diese haben, Konstanten definieren und nach leeren Klassen gruppieren, um eine Art Hierarchie zu erstellen:

public class PERMISSION{
    public static class PAGE{
       public static final Long SEE = 1L; 
       public static final Long EDIT = 2L; 
       public static final Long DELETE = 4L; 
       ...
    }
}

kann innerhalb von Java als PERMISSION.PAGE.SEE verwendet werden, um den Wert 1L abzurufen

Um eine ähnliche Zugriffsmöglichkeit aus EL-Expressions heraus zu erreichen, habe ich folgendes getan: (Wenn es einen Codierungsgott gibt - er könnte mir hoffentlich vergeben: D)

@Named(value="PERMISSION")
public class PERMISSION{
    public static class PAGE{
       public static final Long SEE = 1L; 
       public static final Long EDIT = 2L; 
       public static final Long DELETE = 4L; 
       ...

       //EL Wrapper
       public Long getSEE(){
           return PAGE.SEE;
       }

       public Long getEDIT(){
           return PAGE.EDIT;
       }

       public Long getDELETE(){
           return PAGE.DELETE;
       }
    }

    //EL-Wrapper
    public PAGE getPAGE() {
        return new PAGE();
    }
}

schließlich wird der EL-Ausdruck, um auf das gleiche Long zuzugreifen, wie folgt: #{PERMISSION.PAGE.SEE} - Gleichheit für Java und EL-Access. Ich weiß, dass dies nicht der Fall ist Konvention, aber es funktioniert einwandfrei.

2
dognose

Es gibt eine Problemumgehung, die nicht genau Ihren Wünschen entspricht, die es Ihnen jedoch ermöglicht, mit dem Berühren von Scriptlets auf ganz minimale Weise fast dasselbe zu tun. Mit dem Scriptlet können Sie einen Wert in eine JSTL-Variable einfügen und später auf der Seite sauberen JSTL-Code verwenden.

<%@ taglib prefix="c"       uri="http://Java.Sun.com/jsp/jstl/core" %>
<%@ page import="com.whichever.namespace.Addresses" %>
<c:set var="ourUrl" value="<%=Addresses.URL%>"/>
<c:if test='${"http://www.google.com" eq ourUrl}'>
   Google is our URL!
</c:if>
0
Artem