论坛首页 Java企业应用论坛

JSTL/EL如何方便高效的访问Constants和CodeTable(存储于DB的应用系统变量)

浏览 6841 次
精华帖 (1) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-01-05  
kidneyball 写道
既然是增强EL表达式的解释能力,添加一个ELResolver会更加自然。

大致思路是,在应用启动时(例如你上面的 initApplicationContext()方法中,或者一个load-on-startup的servlet的init方法里)用
JspFactory.getJspApplicationContext(javax.servlet.ServletContext).addELResolver(ELResorver resolver)

方法加入一个ELResolver的实现。(这个方法不能在应用已经处理过请求之后使用,否则会抛IllegalStateException)

这个ELResolver会被加入到JSP规范的默认的ImplicitObjectELResolver之后,其他规范ELResolver之前(例如BeanELResolver与ScopedAttributeELResolver)。也就是说,优先级低于隐含对象,高于scope属性。

在ELResolver中,是知道了EL表达式的实际内容(例如"Constants"字符串),再去求值。这时你可以用forName或者ClassLoader拿到Constants类(拿不到就不处理,留给后续的ELResolver处理,如果后续的Resolver也无法处理,容器就报错),这就没有reload的需要了。

详情可参考 http://download.oracle.com/docs/cd/E17802_01/products/products/jsp/2.1/docs/jsp-2_1-pfd2/javax/servlet/jsp/JspApplicationContext.html



谢谢指点

你说的这种方式看来是最“正统”的办法了——而我所提供的方法是更Spring-ly的

当然,这两种方法的思路其实都一样:put到application scope里。
这里外加一点小技巧——对于code table,提供的是引用而非真实数据,确保reloadable.
0 请登录后投票
   发表时间:2011-01-05   最后修改:2011-01-05
为啥不在启动的时候就加载存放在Application Scope呢?
或者以内存表的方式加载并存储。
0 请登录后投票
   发表时间:2011-01-05   最后修改:2011-01-05
itstarting 写道

当然,这两种方法的思路其实都一样:put到application scope里。
这里外加一点小技巧——对于code table,提供的是引用而非真实数据,确保reloadable.


用自定义ELResolver的好处是,它允许你在求值的瞬间,对求值过程拥有完全的支配权。在ELResolver的getValue方法中你可以拿到EL表达式被求值瞬间的实时上下文,当然包括访问数据库或拿到spring bean。坏处是实现起来相对麻烦,要实现好几个接口方法。

在系统启动期把值put到application scope的好处是实现简单,事实上是借用了求值过程不可控的ScopedAttributeELResolver。问题是put进去与实际求值两个行为之间有个时间差。而reload,就是在还可控的代码中不断地调整application scope中的东西,使得在不可控的求值过程中能获取到尽可能最新的上下文。

当然,我个人觉得还是实用至上,能满足当前需求的方案就是好方案。自定义ELResolver可以作为一种候选方案,等有一天确实application scope方案满足不了再考虑也不迟。
0 请登录后投票
   发表时间:2011-01-05   最后修改:2011-01-05
kongzhizhen 写道
为啥不在启动的时候就加载存放在Application Scope呢?
或者以内存表的方式加载并存储。



不是这个问题,或者说这不是问题,我们要解决和讨论的是其他问题:)
0 请登录后投票
   发表时间:2011-04-14  
希望楼主多分享类似于这样有价值的文章。。。 实用
0 请登录后投票
   发表时间:2011-04-15  
haitaohehe 写道
希望楼主多分享类似于这样有价值的文章。。。 实用

咱是实战派的,呵呵

不过这个帖子响应率超级低,可见大家应该有其他更好的方案
0 请登录后投票
   发表时间:2011-04-15  
最好的方案应该是使用包装模式,把HttpServletRequest包装起来,并在包装类中定义特殊的表达式形式和值获取方式来返回结果。

请参照Struts2中的StrutsRequestWrapper是怎么处理JSTL标签对ValueStack的取值方式的。
0 请登录后投票
   发表时间:2011-04-16  
downpour 写道
最好的方案应该是使用包装模式,把HttpServletRequest包装起来,并在包装类中定义特殊的表达式形式和值获取方式来返回结果。

请参照Struts2中的StrutsRequestWrapper是怎么处理JSTL标签对ValueStack的取值方式的。

这种做法也太笨重了吧?

难道其他引用request的地方也要考虑使用自己的request wrapper以求得一劳永逸?
我见过重新封装request,session,application的,但需求场景应该严重不一样。

还请多加指点
0 请登录后投票
   发表时间:2011-04-17  
itstarting 写道
downpour 写道
最好的方案应该是使用包装模式,把HttpServletRequest包装起来,并在包装类中定义特殊的表达式形式和值获取方式来返回结果。

请参照Struts2中的StrutsRequestWrapper是怎么处理JSTL标签对ValueStack的取值方式的。

这种做法也太笨重了吧?

难道其他引用request的地方也要考虑使用自己的request wrapper以求得一劳永逸?
我见过重新封装request,session,application的,但需求场景应该严重不一样。

还请多加指点


你对HttpServletRequestWrapper的作用还不理解,所以我才让你去看StrutsRequestWrapper的源码。

你的需求是试图通过JSTL或者EL来获取Java对象中的值。途径只有两种:第一,把你要取的值放到request/session/application中。第二,不要从request/session/application中去取值。

之前所有讨论的思路都是第一种途径,这种途径其实没有从本质上解决你的问题,尤其是reloadable的需求。第二种途径是推荐的做法,既干净又有效。

我之所以推荐第二种方式,是因为你的问题其实和Struts2与JSTL整合的问题是极其类似的。JSTL和EL想要获取Struts2中Action内部的属性的值,通过什么方法呢?Action内部的值,完全不存在request/session/application的作用域中。Struts2给出的方案就是采用StrutsRequestWrapper。你可以思考一下,为什么一个框架级别的解决方案,也采用了这种方法呢?因为它是一种最佳实践。
0 请登录后投票
   发表时间:2011-04-17  
downpour 写道


你对HttpServletRequestWrapper的作用还不理解,所以我才让你去看StrutsRequestWrapper的源码。

你的需求是试图通过JSTL或者EL来获取Java对象中的值。途径只有两种:第一,把你要取的值放到request/session/application中。第二,不要从request/session/application中去取值。

之前所有讨论的思路都是第一种途径,这种途径其实没有从本质上解决你的问题,尤其是reloadable的需求。第二种途径是推荐的做法,既干净又有效。

我之所以推荐第二种方式,是因为你的问题其实和Struts2与JSTL整合的问题是极其类似的。JSTL和EL想要获取Struts2中Action内部的属性的值,通过什么方法呢?Action内部的值,完全不存在request/session/application的作用域中。Struts2给出的方案就是采用StrutsRequestWrapper。你可以思考一下,为什么一个框架级别的解决方案,也采用了这种方法呢?因为它是一种最佳实践。



极不情愿的下载了struts2,看了StrutsRequestWrapper的源码,两点感觉:
1.自己再维护一个ValueStack,不愿意也不会这么干;
2.看到了这个类的Comment,不爽:
All Struts requests are wrapped with this class, which provides simple JSTL accessibility. This is because JSTL works with request attributes, so this class delegates to the value stack except for a few cases where required to prevent infinite loops.
你们自己看看这个because

如果为了这个JSTL还要自己扩展request wrapper,感觉太委屈了自己——没必要这么找罪受吧我想


抱歉downpour,咱的境界也许没到你那个层次,咱只会干些投机取巧的事情(好像有这种感觉),总是觉得简单明了的解决方案就是最好的
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics