Seam采用的JSF作为表现层技术,但是标准的jsf有很多的不足之处。
1. JSF对POST方法的http request的依赖太强了,只有POST请求的数据才能直接绑定到后台的组件上,GET方法的则不可以。
2. 根据JSF的规范,当收到一个GET请求后,JSF走完RESTORE VIEW PHARSE 就会直接到RENDER RESPONSE PHARSE,而不会做INVOKE APPLICATION,所以GET方法的请求不能触发业务逻辑。
这些限定让JSF在某些方面不太方便,比如书签功能。因为浏览器的书签都是记下当前页的URL,而不会记下POST请求里的参数。SEAM虽然采用了JSF,但是加入了Page parameter 和 page action,弥补了JSF在这方面的缺陷。
Page parameter是将GET请求时的参数直接绑定到组件上的技术。Page action则是在生成页面之前调用业务逻辑的技术。这两者的配置都可以在WEB-INF/pages.xml或者 *.page.xml里完成。比如:
<page view-id="/calculator.jsp" action="#{calculator.calculate}">
<param name="x" value="#{calculator.lhs}"/>
<param name="y" value="#{calculator.rhs}"/>
<param name="op" converter="#{operatorConverter}" value="#{calculator.op}"/>
</page>
上 面的配置,会让用GET方法访问/calculator.jsp时的参数x, y, op分别绑定到calculator的lhs, rhs和op属性上,然后执行calculator的calculate()方法。如果你只需要在页面上传递参数,而并不需要绑定到某个组件上,只需要写成:
<page view-id="/calculator.jsp" >
<param name="result" />
</page>
这样以GET方法传来的名为result的参数将继续以result为名字在Page Scope内传递下去。
Page action 还可以按条件执行:
<page view-id="/calculator.jsp" >
<param name="x" value="#{calculator.lhs}"/>
<param name="y" value="#{calculator.rhs}"/>
<param name="op" converter="#{operatorConverter}" value="#{calculator.op}"/>
<action execute="#{calculator.calculate}" if="#{calculator.op != null}" />
</page>
除了在pages.xml, *.page.xml里配置,还可以用seam的组件s:link s:button来实现指定page action,例如:
<s:link view="/calculator.jsp" action="#{calculator.calculate}" ></s:link>
这 样,当这个链接被点击后,会引发一个对/calculator.jsp的GET请求,并且在生成/calculator.jsp页面之前执行 #{calculator.calculate} 方法。如果用普通的h:commandLink的话,则会提交表单,引发POST请求。
使用page action时要注意,在处理POST请求的时候,page action会在INVOKE APPLICATION PHARSE之后执行。