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?
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");
}
});
}
}
Dies ist in EL 2.2 und älter nicht möglich. Es gibt verschiedene Alternativen:
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.
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.
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.
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.
Erstellen Sie eine Wrapper-Klasse, die sie über Get-Methoden im Javabean-Stil zurückgibt.
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.
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"/>
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.
Das kannst du nicht. Es folgt der Java Bean-Konvention. Sie müssen also einen Getter dafür haben.
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
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}
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.
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!
Sie können. Versuchen Sie es auf folgende Weise
#{T(com.example.Addresses).URL}
Getestet auf Tomcat 7 und Java6
@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);
}
}
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.
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>