时不时看到有人在问如何在非jsf页面(通过ajax)动态调用jsf的托管bean的属性或方法,其实我在刚接触jsf的时候也有同样的疑惑,虽然jsf提供了非常优雅的局部刷新功能(通过reRendor属性指定刷新区域),但是这种方式必须预先定义好要刷新的区域的内容,而且必须通过服务端控件触发,不能绕开服务端控件而单纯的通过js实现数据更新。
研究了下,要达到上述目的其实不难,思路是:
1、制作一个动态页面(可以是jsf页面,也可以是servlet),根据接收到的参数(例如EL表达式),动态调用托管bean,将结果返回
2、调用方通过ajax发送请求,接收结果就行了。
完成上述任务,其核心就是如何动态解析EL表达式,其实JSF具备这样的功能,通过ELResolver即可实现。下面是用JSF实现的范例:
托管Bean:
前台(JSF)页面testService.xhtml:
GET调用方法(POST调用亦可):
testService.jsf?testService.jsf?expression= testAction.now
上述实现实际上是有安全隐患的,因为任何人如果知道了托管bean,都能通过发送请求来进行调用,很容易对数据库数据进行破坏。JSF不直接提供动态调用托管bean,估计也是为了安全考虑。
研究了下,要达到上述目的其实不难,思路是:
1、制作一个动态页面(可以是jsf页面,也可以是servlet),根据接收到的参数(例如EL表达式),动态调用托管bean,将结果返回
2、调用方通过ajax发送请求,接收结果就行了。
完成上述任务,其核心就是如何动态解析EL表达式,其实JSF具备这样的功能,通过ELResolver即可实现。下面是用JSF实现的范例:
托管Bean:
import javax.el.ELResolver;
import javax.faces.context.FacesContext;
public class TestServiceAction {
public Object getResult() {
FacesContext _context = FacesContext.getCurrentInstance();
//客户端请求的表达式,例如userService.currentUser
String _expression = _context.getExternalContext().getRequestParameterMap().get("expression");
if(_expression != null && _expression.length() > 0) {
return _context.getApplication().getExpressionFactory()
.createValueExpression(_context.getELContext(), "${" + _expression + "}", Object.class)
.getValue(_context.getELContext());
}
return null;
}
}
前台(JSF)页面testService.xhtml:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets">#{testServiceAction.result}</ui:composition>
GET调用方法(POST调用亦可):
testService.jsf?testService.jsf?expression= testAction.now
上述实现实际上是有安全隐患的,因为任何人如果知道了托管bean,都能通过发送请求来进行调用,很容易对数据库数据进行破坏。JSF不直接提供动态调用托管bean,估计也是为了安全考虑。