`

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

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


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

分享到:
评论
5 楼 itstarting 2010-12-28  
而针对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.getCodesByType(String.valueOf(key));
            }

            public boolean containsKey(Object key) {
                return true;
            }
        };
		
	logger.debug("put code table of [{}] to application scope.", codeType);
	this.getServletContext().setAttribute(CODE_TABLE_CONTEXT_NAME, codeMap);
  }
}


接口定义:
/**
 * It's a code table loading service 
 * for exporting code tables to application scope
 * 
 * but we don't put the dummy data to application scope directly
 * for avoiding non-refreshable issue
 * 
 * @author bright_zheng
 *
 */
public interface CodeTableLoaderService {

	/**
	 * load all code types from db/cache
	 * 
	 * @return an array including all code types
	 */
	public String[] loadAllCodeTypes();
	
	/**
	 * get all code objects/beans filter by code type
	 * 
	 * @param codeType
	 * @return responding code objects/beans
	 */
	public Object[] getCodesByType(String codeType);
}



为此,解决方案提供完毕。

当然了,关于Constants和Code table是整合考虑的方案,我分开了描述,只是为了阐述更有针对性而已
大家整合两部分的代码即可

欢迎讨论
4 楼 itstarting 2010-12-28  
基于上述思路,针对Constants的解决方案如下:
...
public class ApplicationScopeLoader extends WebApplicationObjectSupport {

	private static final Logger logger = LoggerFactory.getLogger(ApplicationScopeLoader.class);
	
	/** constant classes which can be injected by spring */
	private Map<String, String> constantClass;

	protected void initApplicationContext() {
		try {
			//build constants and put it to the application scope
			this.buildConstants();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * build constants map
	 * 
	 * @return constants map
	 * @throws ClassNotFoundException 
	 */
	private void buildConstants() throws ClassNotFoundException{
		Map<String, Object> result = new HashMap<String, Object>();
		for(Map.Entry<String, String> map: constantClass.entrySet()){
			//the constant group name
			String k = map.getKey();
			//the class
			String v = map.getValue();
			Class<?> clazz = this.getClass().getClassLoader().loadClass(v);
			Field[] fields = clazz.getDeclaredFields();
			for (int i = 0; i < fields.length; i++) {
				Field field = fields[i];
				int modifier = field.getModifiers();
				//must be final & public
				if (Modifier.isFinal(modifier) && !Modifier.isPrivate(modifier))
					try {
						String name = field.getName();
						Object value = field.get(this);
						logger.debug("building constants{}: name={},value={}", 
								new Object[]{k, name,value});
						result.put(name, value);
					} catch (IllegalAccessException e) {
					}
			}

			logger.info("put constant [{}] to application scope.", k);
			this.getServletContext().setAttribute(k, result);
		}
	}

	public Map<String, String> getConstantClass() {
		return constantClass;
	}

	public void setConstantClass(Map<String, String> constantClass) {
		this.constantClass = constantClass;
	}

}


配置如下,可以配置多个需要EL引用访问的类:
<bean name="applicationScopeLoader" class="xxx.utils.ApplicationScopeLoader" lazy-init="false">
  <property name="constantClass">
    <map>
      <entry key="Constants" value="xxx.framework.Constants"/>
      <!-- 
      <entry key ="Constants2" value="another.constants.class"/>
      -->
    </map>
  </property>
</bean>


用法如下:
${Constants.PAGE_SIZE_DEFAULT}


可以看到,此时可以简单的用标准的EL实现静态变量的访问。
3 楼 itstarting 2010-12-20  
我目前的思路是:
1、对于Constants,我将自动在启动时导出为applicationScope的map;
2、对于Code Table,我将自动在启动时加载到一系列的map,以CodeType为key

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


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

自己封装fn,我也觉得不好,或者说你在这方面有啥更具体的建议?
1 楼 gordonkkk 2010-12-20  
自己封一个标签,或者封一个fn,这是最简单的办法。

相关推荐

    javax/servlet/jsp/jstl/core/ConditionalTagSupport

    当你遇到`java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/ConditionalTagSupport`这样的异常时,意味着在运行时系统找不到这个类,这通常是由于缺少JSTL相关的依赖或者配置不正确所导致的。...

    使用此应用程序部署的jar文件中解析绝对uri:[http://java.sun.com/jsp/jstl/core],

    无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[http://java.sun.com/jsp/jstl/core],解决办法:WEB/INF的lib下,除了导入jstl.jar包,还要导入standard.jar包。另外,解压standard.jar包,把.tld文件...

    JavaWeb分页展示数据(含AJAX/JSTL/EL表达式等知识点)

    JavaWeb分页展示数据是Web应用开发中的常见需求,它涉及到多个关键技术的综合运用,包括AJAX、JSTL、EL表达式以及JSP标准动作。在这个项目中,我们将深入探讨这些技术,以便理解如何有效地在网页上实现数据的动态...

    jstl el taglib 完整jar包

    添加依赖项到一个WEB应用程序:    在web应用程序中,添加以下JAR包到/web-inf/lib目录: - taglibs-standard-spec-1.2.5.jar - taglibs-standard-impl-1.2.5.jar - taglibs-standard-jstlel-1.2.5.jar - xalan-...

    jstl和el的基础

    JSTL是一组标签库,提供了处理常见任务如迭代、条件判断、XML操作等功能,而EL则是一种轻量级的表达式语言,用于在JSP中简洁地访问和操作数据。 **1. EL(Expression Language)** 1. **EL表达式语法** EL表达式...

    JSTL和EL帮助文档

    **JSTL(JavaServer Pages Standard Tag Library)与EL(Expression Language)是Java Web开发中的两个重要组件,它们极大地简化了JSP页面的编写和管理,使得代码更加清晰和易于维护。** **JSTL** 是一个标准的标签...

    Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/core

    有的时候在开发jsp时,需要使用jstl时,在jsp上面引用jstl却出现错误:Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/core,这是由于缺少两个jar包导致的。

    总结EL和JSTL

    EL 表达式和 JSTL 是 JSP 开发中非常重要的技术,它们可以使开发人员更方便地访问页面内容,实现逻辑控制,优化代码结构。但是,EL 表达式和 JSTL 也需要开发人员具备一定的知识和经验,以便更好地使用它们。

    JSTL,EL表达式语法简介

    它的主要目标是提供一种简单的方式来访问存储在作用域中的对象属性,以及执行基本的算术和逻辑操作。EL表达式通常在`${}`中书写,比如`${user.name}`用来获取名为`user`的对象的`name`属性。 **JSTL中的核心标签库...

    JSTL和EL之间的关系

    ### JSTL与EL的关系详解 #### 引言 在探讨JSTL(JSP Standard Tag Library,JSP标准标签库)与EL(Expression Language,表达式语言)之间的关系前,我们首先需理解两者的基本概念及其在JSP(JavaServer Pages)...

    JSTL和EL完美笔记

    **JSTL(JavaServer Pages Standard Tag Library)和EL(Expression Language)是Java Web开发中的两个重要组件,它们极大地简化了JSP页面的编写和管理。** **JSTL** 是一套标准的标签库,提供了丰富的功能,如迭代...

    在jsp中使用JSTL跟El表达式访问和遍历Map集合

    在JavaServer Pages (JSP)开发中,JSTL(JavaServer Pages Standard Tag Library)和EL(Expression Language)是两种非常重要的技术,用于简化页面逻辑和增强可读性。本篇将详细介绍如何在JSP中利用JSTL与EL表达式...

    学生管理系统JSTL+EL.zip

    《基于JSTL和EL的学生管理系统详解》 在IT行业中,Web开发是不可或缺的一部分,而JavaWeb技术则是其中的重要支柱。对于初学者来说,掌握一套简单易懂的Web项目框架至关重要,"学生管理系统JSTL+EL.zip" 就是一个很...

    会议管理系统使用EL和JSTL优化jsp页面

    会议管理系统使用EL和JSTL优化jsp页面

    jakarta-taglibs-standard-current (JSP 标准标签库(JSTL) )

    EL用于获取和设置应用程序范围内的对象属性,而JSTL标签则用于处理复杂的逻辑。例如,`&lt;c:out&gt;`标签可以配合EL表达式显示变量的值。 **示例:** ```jsp &lt;%@ taglib prefix="c" uri="http://java.sun....

    JAVAEE实验报告EL表达式和jstl标签库的使用.pdf

    1. 访问变量:EL 表达式可以访问 JSP 页面中的变量,包括 page、request、session 和 application 等四个作用域中的变量。 例如:${user.name} 访问 user 对象的 name 属性 2. 进行逻辑操作:EL 表达式可以进行...

    jsf/jstl/MyFaces包

    **JSF(JavaServer Faces)** 是一个Java平台上的开源Web应用程序框架,它提供了一种组件化和事件驱动的方式来创建用户界面。JSF的核心概念是UI组件,这些组件可以组合成复杂的用户界面,并且能够与后端数据模型进行...

    jstl与el表达式所需jar

    在Java Web开发中,JSTL(JavaServer Pages Standard Tag Library)和EL(Expression Language)是两个非常重要的组件,它们极大地简化了页面逻辑的编写,提高了代码的可读性和维护性。下面将详细介绍这两个概念以及...

    JSTL&EL分页的例子

    通过这样的方式,我们可以利用JSTL和EL的强大功能,将复杂的分页逻辑封装在后端,保持JSP页面的整洁和高效。在ACCP 5.0这样的课程中,学习如何使用JSTL和EL进行分页是非常有价值的一部分,因为它们是企业级Web开发中...

Global site tag (gtag.js) - Google Analytics