Come si fa riferimento a costanti con EL su una pagina JSP?
Ho un'interfaccia Addresses
con una costante denominata URL
. So di poterlo fare riferimento con uno scriplet andando:, <%=Addresses.URL%>
ma come posso farlo usando EL?
Come si fa riferimento a costanti con EL su una pagina JSP?
Ho un'interfaccia Addresses
con una costante denominata URL
. So di poterlo fare riferimento con uno scriplet andando:, <%=Addresses.URL%>
ma come posso farlo usando EL?
Risposte:
Se sei già su Java EE 7 / EL 3.0, @page import
importerà anche le costanti di classe nell'ambito EL.
<%@ page import="com.example.YourConstants" %>
Questo sotto le coperte verrà importato tramite ImportHandler#importClass()
e sarà disponibile come file ${YourConstants.FOO}
.
Nota che tutte le java.lang.*
classi sono già implicitamente importate e disponibili in questo modo ${Boolean.TRUE}
e ${Integer.MAX_VALUE}
. Ciò richiede solo un server contenitore Java EE 7 più recente poiché le prime versioni presentavano bug in questo. Ad esempio, GlassFish 4.0 e Tomcat 8.0.0-1x non riesce, ma GlassFish 4.1+ e Tomcat 8.0.2x + funzionano. E devi assicurarti assolutamente che il tuo web.xml
sia dichiarato conforme all'ultima versione del servlet supportata dal server. Pertanto, con un web.xml
Servlet dichiarato conforme 2.5 o precedente, nessuna delle funzionalità di Servlet 3.0+ funzionerà.
Notare inoltre che questa funzione è disponibile solo in JSP e non in Facelets. In caso di JSF + Facelets, la soluzione migliore è utilizzare OmniFaces<o:importConstants>
come di seguito:
<o:importConstants type="com.example.YourConstants" />
O aggiungendo un listener di contesto EL che chiama ImportHandler#importClass()
come di seguito:
@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");
}
});
}
}
Questo non è possibile in EL 2.2 e versioni precedenti. Esistono diverse alternative:
Mettili in una Map<String, Object>
che inserisci nell'ambito dell'applicazione. In EL, i valori della mappa sono accessibili nel solito modo javabeano con ${map.key}
o ${map['key.with.dots']}
.
L'uso <un:useConstants>
del Unstandard taglib (maven2 Repo qui ):
<%@ taglib uri="http://jakarta.apache.org/taglibs/unstandard-1.0" prefix="un" %>
<un:useConstants className="com.example.YourConstants" var="constants" />
In questo modo sono accessibili nel solito modo javabeano ${constants.FOO}
.
Usa il CCC <ccc:constantsMap>
di Javaranch come descritto da qualche parte in fondo a questo articolo .
<%@ taglib uri="http://bibeault.org/tld/ccc" prefix="ccc" %>
<ccc:constantsMap className="com.example.YourConstants" var="constants" />
In questo modo sono accessibili anche nel solito modo javabeano ${constants.FOO}
.
Se stai usando JSF2, allora si potrebbe utilizzare <o:importConstants>
di OmniFaces .
<html ... xmlns:o="http://omnifaces.org/ui">
<o:importConstants type="com.example.YourConstants" />
In questo modo sono accessibili anche nel solito modo javabeano #{YourConstants.FOO}
.
Crea una classe wrapper che li restituisca tramite metodi getter in stile Javabean.
Creare un resolver EL personalizzato che prima scansiona la presenza di una costante e, se assente, quindi delegato al resolver predefinito, altrimenti restituisce invece il valore della costante.
unstandard-taglib
progetto jakarta è ancora vivo? c'è qualche alternativa?
Quanto segue non si applica a EL in generale, ma solo a SpEL (Spring EL) (testato con 3.2.2.RELEASE su Tomcat 7). Penso che valga la pena menzionarlo qui nel caso in cui qualcuno cerchi JSP ed EL (ma usa JSP con Spring).
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<spring:eval var="constant" expression="T(com.example.Constants).CONSTANT"/>
Di solito si inseriscono questi tipi di costanti in un Configuration
oggetto (che ha getter e setter) nel contesto servlet e si accede ad essi con${applicationScope.config.url}
url
una proprietà String Configuration
, nominala, crea un'istanza e imposta url
come preferisci. Dopo di che imposta Configuration
quell'oggetto ServletContext
. Fare qualcosa di simile, servletContext.setAttribute("config", config)
. Ed eccoti qui.
ServletContext
? È solo che puoi classificare le costanti in modo più ordinato? ad esempio: applicationScope.config.url
vs applicationScope.url
.
Non puoi. Segue la convenzione Java Bean. Quindi devi avere un getter per questo.
Le proprietà statiche non sono accessibili in EL. La soluzione alternativa che utilizzo è creare una variabile non statica che si assegna al valore statico.
public final static String MANAGER_ROLE = 'manager';
public String manager_role = MANAGER_ROLE;
Uso lombok per generare il getter e il setter, quindi va bene così. Il tuo EL ha questo aspetto:
${bean.manager_role}
Codice completo su http://www.ninthavenue.com.au/java-static-constants-in-jsp-and-jsf-el
Ho implementato come:
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;
}
}
Il passaggio successivo inserisce l'istanza di questa classe in servlerContext
public class ApplicationInitializer implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
sce.getServletContext().setAttribute("Constants", new JspConstants());
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
aggiungi listener a web.xml
<listener>
<listener-class>com.example.ApplicationInitializer</listener-class>
</listener>
accesso in jsp
${Constants.PAGE_SIZE}
Sto definendo una costante nel mio jsp all'inizio:
<%final String URI = "http://www.example.com/";%>
Includo il core taglib nel mio JSP:
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
Quindi, metto la costante a disposizione di EL con la seguente dichiarazione:
<c:set var="URI" value="<%=URI%>"></c:set>
Ora posso usarlo in seguito. Ecco un esempio, in cui il valore è scritto solo come commento HTML a scopo di debug:
<!-- ${URI} -->
Con la tua classe costante, puoi semplicemente importare la tua classe e assegnare le costanti alle variabili locali. So che la mia risposta è una sorta di hack veloce, ma la domanda sorge anche quando si desidera definire le costanti direttamente nel JSP.
<%=URI%>
: P
<%=URI%>
non funzionava, ma questa tecnica funzionava.
Si, puoi. Hai bisogno di un tag personalizzato (se non riesci a trovarlo da qualche altra parte). Ho fatto questo:
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;
}
}
e il tag si chiama:
<yourLib:constMap path="path.to.your.constantClass" var="consts" />
Tutte le variabili finali statiche pubbliche verranno inserite in una mappa indicizzata dal loro nome Java, quindi se
public static final int MY_FIFTEEN = 15;
quindi il tag lo racchiuderà in un numero intero e puoi fare riferimento ad esso in un JSP:
<c:if test="${consts['MY_FIFTEEN'] eq 15}">
e non devi scrivere getter!
Puoi. Prova nel modo seguente
#{T(com.example.Addresses).URL}
Testato su TomCat 7 e java6
Anche sapendo che è un po 'tardi, e anche sapendo che questo è un piccolo trucco, ho usato la seguente soluzione per ottenere il risultato desiderato. Se sei un amante delle convenzioni di denominazione Java, il mio consiglio è di smettere di leggere qui ...
Avere una classe come questa, che definisce le costanti, raggruppate per classi vuote per creare una sorta di gerarchia:
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;
...
}
}
può essere utilizzato da java PERMISSION.PAGE.SEE
per recuperare il valore1L
Per ottenere una possibilità di accesso simile da EL-Expressions, ho fatto questo: (Se c'è un dio della codifica - si spera che possa perdonarmi: 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();
}
}
infine, l'espressione EL per accedere allo stesso Long
diventa: #{PERMISSION.PAGE.SEE}
- uguaglianza per Java ed EL-Access. So che è fuori dalle convenzioni, ma funziona perfettamente.
@Bozho ha già fornito un'ottima risposta
Di solito si inseriscono questi tipi di costanti in un oggetto Configuration (che ha getter e setter) nel contesto servlet e si accede ad essi con $ {applicationScope.config.url}
Tuttavia, sento che è necessario un esempio, quindi porta un po 'più di chiarezza e risparmia tempo a qualcuno
@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);
}
}
C'è una soluzione alternativa che non è esattamente ciò che desideri, ma ti consente di attivarti quasi allo stesso modo toccando gli scriptlet in modo minimale. È possibile utilizzare lo scriptlet per inserire un valore in una variabile JSTL e utilizzare il codice JSTL pulito più avanti nella pagina.
<%@ 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>