EL'de sabitlere nasıl başvurulur?


106

Bir JSP sayfasında EL sabitlerine nasıl başvurursunuz?

AddressesSabit isimli bir arayüzüm var URL. Bunu bir komut dosyasıyla şu şekilde referans gösterebileceğimi biliyorum: <%=Addresses.URL%>ama bunu EL kullanarak nasıl yapabilirim?

Yanıtlar:


156

EL 3.0 veya daha yeni

Zaten Java EE 7 / EL 3.0 kullanıyorsanız, @page importsınıf sabitlerini de EL kapsamına aktaracaktır.

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

Bu kapakların altına aktarılacak ImportHandler#importClass()ve olarak satışa sunulacaktır ${YourConstants.FOO}.

Tüm java.lang.*sınıfların zaten dolaylı olarak içe aktarıldığını ve böyle ${Boolean.TRUE}ve gibi kullanılabilir olduğunu unutmayın ${Integer.MAX_VALUE}. Bu, yalnızca daha yeni bir Java EE 7 kapsayıcı sunucusu gerektirir, çünkü önceki sürümlerde hatalar vardır. Örneğin, GlassFish 4.0 ve Tomcat 8.0.0-1x başarısız olur, ancak GlassFish 4.1+ ve Tomcat 8.0.2x + çalışır. Ayrıca web.xml, sunucunuzun sunucu tarafından desteklenen en son sunucu uygulaması sürümüne uygun olduğunun beyan edildiğinden kesinlikle emin olmanız gerekir . Dolayısıyla, web.xmlServlet 2.5 veya daha eski bir sürümle uyumlu olduğu bildirilen bir ile, Servlet 3.0+ özelliklerinin hiçbiri çalışmayacaktır.

Ayrıca bu özelliğin sadece JSP'de mevcut olduğunu ve Facelets'te bulunmadığını unutmayın. JSF + Facelets durumunda, en iyi bahsiniz aşağıdaki gibi OmniFaces<o:importConstants> kullanmaktır :

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

Veya ImportHandler#importClass()aşağıdaki gibi çağıran bir EL bağlam dinleyicisi eklemek :

@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 veya üstü

Bu değil EL 2.2 ve daha eski mümkün. Birkaç alternatif var:

  1. Bunları Map<String, Object>uygulama kapsamına koyduğunuz bir yere koyun. EL'de, harita değerlerine normal Javabean yoluyla ${map.key}veya ile erişilebilir ${map['key.with.dots']}.

  2. Kullanım <un:useConstants>ait Unstandard taglib (Maven2 repo burada ):

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

    Bu şekilde, normal Javabean yoluyla erişilebilirler ${constants.FOO}.

  3. Kullanım Javaranch en CCC <ccc:constantsMap> altındaki desribed yerde olarak bu makalede .

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

    Bu şekilde normal Javabean yoluyla da erişilebilirler ${constants.FOO}.

  4. JSF2 kullanıyorsanız <o:importConstants>, OmniFaces'i kullanabilirsiniz .

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

    Bu şekilde normal Javabean yoluyla da erişilebilirler #{YourConstants.FOO}.

  5. Javabean tarzı alıcı yöntemleriyle onları döndüren bir sarmalayıcı sınıfı oluşturun.

  6. Önce bir sabitin varlığını tarayan ve yoksa, varsayılan çözümleyiciye delege eden, aksi takdirde bunun yerine sabit değeri döndüren özel bir EL çözümleyici oluşturun.


4
Bu soruyu buldum çünkü bir form: options etiketiyle statik bir Liste alanını kullanmaya çalışırken aynı sorunu yaşıyordum. Statik listeyi döndüren statik olmayan bir alıcı ekleyerek çalıştırmayı başardım. Biraz karışık ama hey, bu sizin için JSP geliştirme!
spaaarky 21

1
Çekirdekler yayla yönetiliyorsa, bunu JSF için nasıl yapılandıracağınıza dair herhangi bir örneğiniz var mı? Önceden Thx.
Lodger

2
@Lodger: Bahar yapmam.
BalusC

2
Jakarta unstandard-taglibprojesi hala yaşıyor mu? alternatif var mı
davioooh

1
Numaralandırma için bu teknikleri kullanmanın bir yolu var mı?
Niklas Peter

11

Aşağıdakiler genel olarak EL için geçerli değildir, bunun yerine yalnızca SpEL (Spring EL) için geçerlidir (Tomcat 7'de 3.2.2.RELEASE ile test edilmiştir). Birisinin JSP ve EL için arama yapması durumunda (ancak Spring ile JSP kullanması durumunda) burada bahsetmeye değer olduğunu düşünüyorum.

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

9

Bu tür sabitleri genellikle Configurationsunucu uygulaması bağlamındaki bir nesneye (alıcıları ve ayarlayıcıları olan) yerleştirirsiniz ve bunlara${applicationScope.config.url}


Konu jsp'ye gelince burada biraz acemi- bunu daha tam olarak açıklayabilir misin?
tau-neutrino

1
@ tau-nötrino: Aslında basit. urlString özelliğine sahip bir sınıf oluşturun , adlandırın Configuration, örnekleyin ve istediğiniz urlşekilde ayarlayın . Bundan sonra o Configurationnesneyi yerleştirin ServletContext. , Gibi bir şey yapın servletContext.setAttribute("config", config). Ve işte gidiyorsun.
Adeel Ansari

Önerilen çözümünüz ile sabiti yalnızca bir özniteliği olarak eklemek arasındaki fark nedir ServletContext? Sadece sabitleri daha düzgün bir şekilde sınıflandırabilmeniz için mi? örneğin: applicationScope.config.urlvs applicationScope.url.
theyuv

7

Yapamazsın. Java Bean kuralını izler. Yani bunun için bir alıcıya sahip olmalısın.



5

Ben şöyle uyguladım:

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

Sonraki adım bu sınıfın örneğini servlerContext'e koy

public class ApplicationInitializer implements ServletContextListener {


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

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

web.xml'ye dinleyici ekle

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

jsp'de erişim

${Constants.PAGE_SIZE}

4

En başında jsp'mde bir sabit tanımlıyorum:

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

Çekirdek taglib'i JSP'me dahil ediyorum:

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

Ardından, aşağıdaki ifadeyi kullanarak sabiti EL için kullanılabilir hale getiriyorum:

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

Şimdi, daha sonra kullanabilirim. Burada, değerin yalnızca hata ayıklama amacıyla HTML açıklaması olarak yazıldığı bir örnek:

<!-- ${URI} -->

Sabit sınıfınızla, sınıfınızı içe aktarabilir ve sabitleri yerel değişkenlere atayabilirsiniz. Cevabımın bir tür hızlı hack olduğunu biliyorum, ancak soru sabitleri doğrudan JSP'de tanımlamak istediğinde de artıyor.


1
lol EL değişkenlerini bu şekilde başlatıyorsanız neden doğrudan Scriptlets kullanmıyorsunuz?
Navin

Üstteki üç çizgi dağınıktır ve ardından JSP ^^ nin geri kalanında EL'yi temizleyin.
koppor

1
@koppoor sanırım öyle. Sadece şunu kullanacağım <%=URI%>: P
Navin

1
Direkt <%=URI%>çalışmayan bir yerim vardı ama bu teknik işe yaradı.
englebart

3

Evet yapabilirsin. Özel bir etikete ihtiyacınız var (eğer başka bir yerde bulamazsanız). Bunu yaptım:

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

ve etiketin adı:

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

Tüm genel statik son değişkenler, Java adlarına göre indekslenmiş bir Haritaya yerleştirilecektir.

public static final int MY_FIFTEEN = 15;

sonra etiket bunu bir Tamsayı olarak sarar ve bir JSP'de buna referans verebilirsiniz:

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

ve alıcılar yazmanıza gerek yok!


3

Yapabilirsin. Takip yolunu dene

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

TomCat 7 ve java6'da test edildi


3
Bu, EL'ye değil, SpEL'e benziyor. Yanılıyor muyum? Ayrıca, bu daha eski bir Tomcat5.5'te çalışır mı?
Pytry

2

Biraz geç olduğunu ve hatta bunun küçük bir hack olduğunu bilmek bile - istenen sonucu elde etmek için aşağıdaki çözümü kullandım. Java Adlandırma Konvansiyonlarını seviyorsanız, tavsiyem burada okumayı bırakmanızdır ...

Bunun gibi bir sınıfa sahip olmak, Sabitleri tanımlamak, bir tür hiyerarşi yaratmak için boş sınıflara göre gruplandırılmak:

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

PERMISSION.PAGE.SEEdeğeri almak için java içinden kullanılabilir1L

EL-İfadeleri içinden benzer bir erişim olasılığı elde etmek için şunu yaptım: (Bir kodlama tanrısı varsa - umarım beni affedebilir: 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();
    }
}

son olarak, aynısına erişmek için EL-İfadesi şu Longhale gelir: #{PERMISSION.PAGE.SEE}- Java ve EL-Access için eşitlik. Bunun herhangi bir konvansiyonun dışında olduğunu biliyorum, ama gayet iyi çalışıyor.


2

@Bozho zaten harika bir cevap verdi

Bu tür sabitleri genellikle sunucu uygulaması bağlamındaki bir Yapılandırma nesnesine (alıcıları ve ayarlayıcıları olan) yerleştirir ve bunlara $ {applicationScope.config.url} ile erişirsiniz.

Bununla birlikte, bir örneğe ihtiyaç olduğunu hissediyorum, bu yüzden biraz daha netlik getiriyor ve birine zaman ayırıyor

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

0

Tam olarak istediğiniz şey olmayan, ancak komut dosyalarına dokunarak neredeyse aynı şekilde oldukça minimal bir şekilde aktif olmanıza izin veren bir geçici çözüm var. Bir JSTL değişkenine değer eklemek için betik uygulamasını kullanabilir ve sayfanın ilerleyen kısımlarında temiz JSTL kodunu kullanabilirsiniz.

<%@ 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>

1
Bunun neden reddedildiğini anlamıyorum. Bu, 3. seçenekle aynı kalıp: stackoverflow.com/a/16692821/274677
Marcus Junius Brutus
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.