回答:
すでにJava EE 7 / EL 3.0を使用している場合は、@page import
クラス定数もELスコープにインポートされます。
<%@ page import="com.example.YourConstants" %>
これはカバーの下にインポートされImportHandler#importClass()
、として利用できます${YourConstants.FOO}
。
すべてのことに注意java.lang.*
クラスがすでに暗黙的にインポートされ、そのような利用可能である${Boolean.TRUE}
と${Integer.MAX_VALUE}
。初期のバージョンにはバグがあったため、これには最新のJava EE 7コンテナサーバーのみが必要です。たとえば、GlassFish 4.0とTomcat 8.0.0-1xは失敗しますが、GlassFish 4.1+とTomcat 8.0.2x +は機能します。またweb.xml
、サーバーでサポートされている最新のサーブレットバージョンに準拠していることを宣言する必要があります。したがって、web.xml
がServlet 2.5以前の準拠として宣言されている場合、Servlet 3.0以降の機能はどれも機能しません。
また、この機能はJSPでのみ使用でき、Faceletsでは使用できないことにも注意してください。JSF + Faceletsの場合、最善の策<o:importConstants>
は以下のようにOmniFacesを使用することです。
<o:importConstants type="com.example.YourConstants" />
またはImportHandler#importClass()
、以下のように呼び出すELコンテキストリスナーを追加します。
@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以前では不可能です。いくつかの選択肢があります:
それらをMap<String, Object>
アプリケーションスコープに配置したものに配置します。ELでは、${map.key}
またはを使用して、通常のJavabeanの方法でマップ値にアクセスできます${map['key.with.dots']}
。
使用<un:useConstants>
のUnstandardのtaglib(Maven2をレポこちら):
<%@ taglib uri="http://jakarta.apache.org/taglibs/unstandard-1.0" prefix="un" %>
<un:useConstants className="com.example.YourConstants" var="constants" />
この方法では、通常のJavabeanの方法でにアクセスできます${constants.FOO}
。
この記事の下部のどこかに記載されているJavaranchのCCC <ccc:constantsMap>
を使用してください。
<%@ taglib uri="http://bibeault.org/tld/ccc" prefix="ccc" %>
<ccc:constantsMap className="com.example.YourConstants" var="constants" />
この方法で、通常のJavabeanの方法でもアクセスできます${constants.FOO}
。
JSF2を使用している場合<o:importConstants>
は、OmniFacesを使用できます。
<html ... xmlns:o="http://omnifaces.org/ui">
<o:importConstants type="com.example.YourConstants" />
この方法で、通常のJavabeanの方法でもアクセスできます#{YourConstants.FOO}
。
Javabeanスタイルのgetterメソッドを介してそれらを返すラッパークラスを作成します。
最初に定数の存在をスキャンし、存在しない場合はデフォルトのリゾルバーに委任するカスタムELリゾルバーを作成します。そうでない場合は代わりに定数値を返します。
unstandard-taglib
プロジェクトはまだ生きていますか?いくつかの選択肢はありますか?
通常、これらの種類の定数Configuration
は、サーブレットコンテキストのオブジェクト(ゲッターとセッターを持つ)に配置し、次のようにしてアクセスします${applicationScope.config.url}
url
Stringプロパティとしてクラスを作成し、それに名前を付けてConfiguration
インスタンス化し、url
を好きなように設定します。その後、そのConfiguration
オブジェクトをに設定しますServletContext
。のような何かをしてくださいservletContext.setAttribute("config", config)
。そして、あなたは行きます。
ServletContext
ですか?定数をよりきれいに分類できるというだけですか?例:applicationScope.config.url
対applicationScope.url
。
ELでは静的プロパティにアクセスできません。私が使用する回避策は、それ自体を静的な値に割り当てる非静的変数を作成することです。
public final static String MANAGER_ROLE = 'manager';
public String manager_role = MANAGER_ROLE;
私はロンボクを使用してゲッターとセッターを生成しているので、それはかなりうまくいきます。ELは次のようになります。
${bean.manager_role}
完全なコード(http://www.ninthavenue.com.au/java-static-constants-in-jsp-and-jsf-el)
私は次のように実装しました:
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;
}
}
次のステップでは、このクラスのインスタンスをservlerContextに配置します
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に追加する
<listener>
<listener-class>com.example.ApplicationInitializer</listener-class>
</listener>
jspでのアクセス
${Constants.PAGE_SIZE}
最初にjspで定数を定義しています:
<%final String URI = "http://www.example.com/";%>
JSPにコアtaglibを含めます。
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
次に、次のステートメントによってELで定数を使用できるようにします。
<c:set var="URI" value="<%=URI%>"></c:set>
これで、後で使用できます。以下の例では、値はデバッグ目的でHTMLコメントとして記述されています。
<!-- ${URI} -->
定数クラスを使用すると、クラスをインポートして、ローカル変数に定数を割り当てることができます。私の答えは一種の簡単なハックであることはわかっていますが、JSPで定数を直接定義したい場合にも問題が発生します。
<%=URI%>
:P
<%=URI%>
が機能しない場所がありましたが、このテクニックは機能しました。
はい、できます。カスタムタグが必要です(他の場所で見つからない場合)。私はこれをやった:
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;
}
}
タグが呼び出されます:
<yourLib:constMap path="path.to.your.constantClass" var="consts" />
すべてのpublic static final変数は、Java名で索引付けされたMapに入れられるため、
public static final int MY_FIFTEEN = 15;
その後、タグはこれを整数でラップし、JSPで参照できます。
<c:if test="${consts['MY_FIFTEEN'] eq 15}">
ゲッターを書く必要はありません!
あなたはできる。フォロー方法で試してください
#{T(com.example.Addresses).URL}
TomCat 7およびjava6でテスト済み
少し遅れていることを知っていても、これが少しハックであることを知っていても、次の解決策を使用して目的の結果を達成しました。あなたがJava-Naming-Conventionsの愛好家なら、私のアドバイスはここを読むのをやめることです...
このようなクラスを作成し、定数を定義し、空のクラスでグループ化して、一種の階層を作成します。
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.SEE
値を取得するためにJava内から使用できます1L
EL-Expressions内から同様のアクセス可能性を実現するために、私はこれを行いました:(コーディング神がいる場合-彼はうまくいけば私を許してくれるでしょう: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();
}
}
最終的には、EL-発現はアクセスに非常に同じことがLong
次のようになります#{PERMISSION.PAGE.SEE}
- JavaとEL-アクセスの平等。これは慣例ではありませんが、完全に正常に動作します。
@Bozhoはすでに素晴らしい答えを提供してくれました
通常、これらの種類の定数は、サーブレットコンテキストのConfigurationオブジェクト(ゲッターとセッターを持つ)に配置し、$ {applicationScope.config.url}を使用してアクセスします
しかし、例が必要だと思うので、もう少し明確にして誰かの時間を節約できます
@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);
}
}
必要な回避策はありませんが、最小限の方法でスクリプトレットを操作することでほぼ同じようにアクティブにできます。スクリプトレットを使用してJSTL変数に値を入力し、ページの後半でクリーンなJSTLコードを使用できます。
<%@ 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>