日期:2014-05-16  浏览次数:20558 次

JSTL/EL如何方便高效的访问Constants和CodeTable(存储于DB的应用系统变量)
之前只是简单的使用JSTL/EL进行输出,一般的思路很简单:retrieve data -> put to Request -> JSTL/EL


一直没太注意两个问题:

1、JSTL/EL官方上无法方便、直接的访问静态变量。


比如,我们定义了一个Constants类:
public class Constants implements Serializable {
	public static final String CONSTANT_A= "ABC";	
	...
}

我们并不能直接这样使用:
<c:out value="${Constants.CONSTANT_A}"/>


原因很简单:
1)这个Constants必须出现在某个scope,比如requestScope;
2)这个CONSTANT_A必须有一个getter方法,EL支持bean和map的规范

怎么办?


2、JSTL/EL如何才能简单的使用CodeTable(存储于DB的应用系统变量)?
应用系统变量几乎是无可避免的,好处大家都懂的。
一般人的思维肯定是:
1)提供一个service,拥有若干方法,比如getCodesByType(String codeType);
2)用的时候get出来,然后put到request上面,最后在JSP中用JSTL/EL来取出

最后的用法,以Spring MVC的tag为例,一般是:
<form:select path="gender">
  <form:option value="-" label="--Please Select"/>
  <form:options items="${CodeTable.Gender}" itemValue="codeValue" itemLabel="codeName"/>
</form:select>

此时表示要获取Gender的CodeTable,并以codeValue为值,codeName为Label

是否存在更简单有效的方法?


我目前正在整合一些信息并加以模式化,试图提供一个简洁有效的办法来达成目标,也希望大家参与讨论,提供“一站式”的解决方案

6 楼 xieke 2010-12-28  
itstarting 写道
我目前的思路是:
1、对于Constants,我将自动在启动时导出为applicationScope的map;
2、对于Code Table,我将自动在启动时加载到一系列的map,以CodeType为key

那之后就可以用“标准”的EL语法透明的访问Constants和CodeTable了。


但在这里有一个问题,那就是对于Code Table而言,一旦“自动在启动时加载到一系列的map”,会不会导致这些Code Table是non-reloadable的——我想这是难以让人接受的——总不能改一下系统变量就要reload一次application吧?


该系统变量时 单独对 Map 里某个 key 作更新就好了,为何要reload.
7 楼 itstarting 2010-12-28  
itstarting 写道
而针对code table的解决方案,其实有不少技巧:
1、暴露到application scope的不是简单的数据,而是引用[color=red][/color]。这一点非常重要,也确保了我们的code table是reloadable的——而reload的策略,完全取决于业务的需要,比如我们用ibatis,可以简单的配置cache-model就行了,此时在DAO层cache,如要在service层,要专门考虑采用cache框架的API;
2、单独定义一个需要真正业务实现的接口,这样就变得更具通用性了。

public class ApplicationScopeLoader extends WebApplicationObjectSupport {
...
	
  /** code table service */
  private final CodeTableLoaderService codeTableLoaderService = ApplicationContextManager
		.getBean("codeTableLoaderService",CodeTableLoaderService.class);
	
  private final static String CODE_TABLE_CONTEXT_NAME = "CodeTable";

  protected void initApplicationContext() {
    try {
      //build constants and put it to the application scope
      this.buildConstants();
			
      //build code table and put it to the application scope
      this.buildCodeTables();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
	
  /**
   * build code tables
   * each code table will be group by the type
   * for example, if there is a code table type 'gender'
   * then will be put to 
   */
  private void buildCodeTables(){
    String[] codeTypes = codeTableLoaderService.loadAllCodeTypes();
	for(String codeType: codeTypes){
		this.buildOneCodeTableByCodeType(codeType);
	}
  }

  /**
   * extract given codes to a sub array of codes by code type
   * @param codes
   * @return
   */
  private void buildOneCodeTableByCodeType(String codeType){
	Map<Object,Object> codeMap = new HashMap<Object,Object>() {
            private static final long serialVersionUID = -1759893921358235848L;
            
            /**
             * get from the service, not raw data for avoiding non-refresh issue
             */
            public Object get(Object key) {
                return codeTableLoaderService.ge