电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

Seam的页面逻辑实现


发布日期:2019/2/24
 

上一篇文章我大概地介绍一下基于Faceslet的JSF页面端的构成接下来是时候说一下后台逻辑的实现啦JSF的页面逻辑是由Managed Bean(姑且译为托管BEAN)实现所谓的Managed Bean就是指一些由JSF运行时(Runtime)创建与管理的普通Java对象(潮流一点的叫法——POJO)

标准JSF中Managed Bean

标准的JSF中Managed Bean是在facesconfigxml中通过XML定义的例如

<managedbean>

<managedbeanname>helloBean</managedbeanname>

<managedbeanclass>

netblogjavamaxseamHelloBean

</managedbeanclass>

<managedbeanscope>request</managedbeanscope>

</managedbean>

这些XML相信不用我怎么讲解大家也知道其作用啦定义一个BEAN无论是在SpringEJB还其它的BEAN容器(Container)中无非都是这几个元素BEAN的名称(或者标识ID)JAVA类型和作用域JSF的Managed Bean有四个作用域如下表所示

作用域描述none作用域是none的Managed Bean通常是定义一些公用的BEAN它们的创建与存储依赖于引用它的BEANrequest在单一的HTTP请求(Request)中被创建和保持有效session在HTTP的会话(Session)中被创建和保持有效可以跨请application存储WEB应用的Application上下文中对于所有的请求和会话可见

可能大家对none作用域比较陌生举个例子可能会好理解一点

<managedbean>

<managedbeanname>helloBean</managedbeanname>

<managedbeanclass>

compccwjsftrainingmanagedbeanHelloBean

</managedbeanclass>

<managedbeanscope>request</managedbeanscope>

<managedproperty>

<propertyname>messageFromOtherBean</propertyname>

<propertyclass>javalangString</propertyclass>

<value>#{messageBean}</value>

</managedproperty>

</managedbean>

<managedbean>

<managedbeanname>messageBean</managedbeanname>

<managedbeanclass>javalangString</managedbeanclass>

<managedbeanscope>none</managedbeanscope>

<value>HelloWorldfromAnotherBean!</value>

</managedbean>

这个例子定义了一个名为messageBean作用域是none的Managed Bean然后它被注入名为messageBean作用域是request的Managed Bean中因此这个messageBean的作用域会跟随helloBean同为request另外值得一提的是上例同样展示了如何在一个Managed Bean初始其属性(Property)的值如何引用其它的Managed Bean

Seam中的Web Bean(相当于Managed Bean)

标准JSF的Managed Bean存在不少缺点

必须通过XML进行配置过于麻烦

贫乏的作用域上文提及标准的JSF的Managed Bean只有四种作用域nonerequestsession和application由于JSF对状态的依赖比较强经常需要在请求之间保存应用的状态所以很多时候我们时候都不得不使用Session作用域的Managed Bean但是众所周知过多地使用Session会带来很多问题如容易造成内存耗尽难于集群(Cluster)等

有监于此Seam对JSF进行了扩展并进而起草了Web Bean标准(Web Bean还在BETA阶段坦白的说我也不是很了解)下面我们就来学习一下Seam的Managed Bean(官方文档中叫Component)在这方面Seam与标准JSF有如下不同

Seam的Component既可以通过XML配置又可以通过Annotation的方式配置我个人比较偏爱Annotation的方式方便快捷能够提高工作效率XML方式有一个好处就是可以集中管理但是因为Managed Bean配置相对比较稳定不会经常修改所以XML优势并不会太明显

更丰富的作用域(Seam中称为上下文Context)Seam有种上下文可选无状态(Stateless Context)事件(Event Context或者Request Context)页面(Page Context)对话(Conversation Context)会话(Session Context)业务流(Business Process Context)和应用程序(Application Context)

Seam引入一种双向注入(Binjection)的方式所谓的双向注入就是可以将上下文中的Bean注入到另一个Bean中又或者将Bean中的属性(Property)直接发布在上下文中

Seam的Compoenet可以直接使用EJB 的Bean

下面我们看一个简单的Component的定义的例子

packagenetblogjavamaxhellosession;

importorgjbossseamScopeType;

importorgjbossseamannotationsName;

importorgjbossseamannotationsScope;

@Name(helloWB)

@Scope(ScopeTypePAGE)

publicclassHelloWB{

privateStringname;

privateStringmessage;

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

thisname=name;

}

publicStringgetMessage(){

returnmessage;

}

publicvoidsetMessage(Stringmessage){

ssage=message;

}

publicvoidsayHello(){

message=Hello+name+!;

}

publicvoidanotherEvent(){

Systemoutprintln(Anotherrequestiscoming);

}

}

通过上述代码大家可以看到有两句Annotation定义——Name和Scope除此之外并没有什么特别的地方所以正是这两个Annotation使HelloWB成为一个可以被SEAM的运行时识别的ComponentName用于定义Component的名称是必须的Scope则用于定义Component的作用域是可选的默认值为短对话(Short Conversation)在本例中HelloWB的作用域是PagePage与Conversation都Seam的杰作在标准JSF是没有的而且这两个作用域是比较常用我个人比较热衷于Page作用域所以在这里先谈一下Page

正如我前面所说JSF对状态的依赖比较强……造成我们对Session的依赖引起了很多问题Page很大程度上解决了这个问题它可以跨请求存活只要该请求不是新的什么请求是新的请求呢?要回答这个问题先要搞清楚什么是POSTBACK学过ASPNET的朋友可能对POSTBACK概念比较熟悉没学过的话不要紧POSTBACK并不是什么深奥的东西所谓的POSTBACK就是指用户按下页面上的某个按钮或表单控件将表单数据发送回到页面自身的URL相反如果用户是通过在地址栏中输入URL或通过点击页面的链接访问页面则这个请求就是一个NONPOSTBACK的请求也即是一个新的请求

另外一些JSF专家都推荐一种叫Backing Bean的风格所谓的Backing Bean就是指一个JSF页面对应一个Managed Bean处理页面逻辑Page作用域非常适用这种情况因为它是与页面一起序列化(Serialize)到浏览器或保存在Session中如果大家还是不太明白的话请看以下的XHTML代码

<?xmlversion=encoding=utf?>

<!DOCTYPEhtmlPUBLIC//WC//DTDXHTMLTransitional//ENtransitionaldtd>

<htmlxmlns=xmlns:h=>

<head>

<metacontent=text/html;charset=utfhttpequiv=ContentType/>

<title>

HelloWorld

</title>

</head>

<body>

<h:form>

<h:outputLabelvalue=Name:for=itName/>

<h:inputTextid=itNamevalue=#{helloWBname}/>

<h:commandButtonaction=#{helloWBsayHello}value=SayHello/>

<h:commandButtonaction=#{helloWBanotherEvent}value=AnotherReqeust/>

<hr/>

<h>

<h:outputTextvalue=#{ssage}/>

</h>

</h:form>

</body>

</html>

发布运行上述代码大家可以看如下页面

在输入框中键入max点击Say Hello按钮将请求POSTBACK到Seam的组件中由于按钮注册了组件的监听方法所以HelloWB的sayHello方法会被调用它将通过值绑定所得的name与Hello串起来赋给message属性因此响应页面会如下图所示

这时候大家可以再点击Another Request按钮出现的结果与上图一样这就说明虽然发生了第二次请求name与message的同样保持上一次的值然后大家可以再试下复制页面地址粘贴到新窗口或新选项卡(TAB)的地址栏中按下ENTER你会发现页面的被重置回到最初的状态这个例子很好地演示了POSTBACK请求与NONPOSTBACK请求的区别

小结

本文粗略地介绍了一下JSF的页面逻辑处理组件——Managed Bean还有很多关于Seam的组件知识如Bijection和Conversation等还没有介绍只有留待以后文章了

上一篇:一个相当经典的RMI实例源代码及详细说明

下一篇:log4j--新的日志操作方法