随笔-34  评论-1965  文章-0  trackbacks-0

上一篇文章,我大概地介绍一下基于faceslet的jsf页面端的构成。接下来,是时候说一下后台逻辑的实现啦。jsf的页面逻辑是由managed bean(姑且译为托管bean)实现。所谓的“managed bean”就是指一些由jsf运行时(runtime)创建与管理的普通java对象(潮流一点的叫法——pojo)。

标准jsf中managed bean

标准的jsf中managed bean是在faces-config.xml中通过xml定义的。例如:

<managed-bean>
    
<managed-bean-name>hellobeanmanaged-bean-name>
    
<managed-bean-class>
        net.blogjava.max.seam.hellobean
    
managed-bean-class>
    
<managed-bean-scope>requestmanaged-bean-scope>
managed-bean>

这些xml相信不用我怎么讲解大家也知道其作用啦。定义一个bean,无论是在spring、ejb还其它的bean容器(container)中,无非都是这几个元素:bean的名称(或者标识,id)、java类型和作用域。jsf的managed bean有四个作用域,如下表所示:

作用域 描述
none 作用域是none的managed bean通常是定义一些公用的bean,它们的创建与存储依赖于引用它的bean
request 在单一的http请求(request)中被创建和保持有效
session 在http的会话(session)中被创建和保持有效,可以跨请求
application 存储web应用的application上下文中,对于所有的请求和会话可见

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

<managed-bean>
   
<managed-bean-name>hellobeanmanaged-bean-name>
   
<managed-bean-class>
      com.pccw.jsftraining.managedbean.hellobean
   
managed-bean-class>
   
<managed-bean-scope>requestmanaged-bean-scope>
   
<managed-property>
      
<property-name>messagefromotherbeanproperty-name>
      
<property-class>java.lang.stringproperty-class>
      
<value>#{messagebean}value>
   
managed-property>
managed-bean>
<managed-bean>
   
<managed-bean-name>messagebeanmanaged-bean-name>
   
<managed-bean-class>java.lang.stringmanaged-bean-class>
   
<managed-bean-scope>nonemanaged-bean-scope>
   
<value>hello world from another bean!value>
managed-bean>

这个例子定义了一个名为messagebean、作用域是none的managed bean,然后它被注入名为messagebean、作用域是request的managed bean中。因此,这个messagebean的作用域会跟随hellobean,同为request。另外值得一提的是,上例同样展示了如何在一个managed bean初始其属性(property)的值,如何引用其它的managed bean。

seam中的web bean(相当于managed bean)

标准jsf的managed bean存在不少缺点:

  1. 必须通过xml进行配置,过于麻烦;
  2. 贫乏的作用域,上文提及标准的jsf的managed bean只有四种作用域:none、request、session和application。由于jsf对状态的依赖比较强,经常需要在请求之间保存应用的状态,所以很多时候我们时候都不得不使用session作用域的managed bean。但是众所周知,过多地使用session会带来很多问题,如容易造成内存耗尽,难于集群(cluster)等。

有监于此,seam对jsf进行了扩展,并进而起草了web bean标准(web bean还在beta阶段,坦白的说我也不是很了解)。下面我们就来学习一下seam的managed bean(官方文档中叫component)。在这方面seam与标准jsf有如下不同:

  1. seam的component既可以通过xml配置,又可以通过annotation的方式配置。我个人比较偏爱annotation的方式,方便快捷,能够提高工作效率。xml方式有一个好处就是可以集中管理,但是因为managed bean配置相对比较稳定,不会经常修改,所以xml优势并不会太明显;
  2. 更丰富的作用域(seam中称为上下文context),seam有6种上下文可选:无状态(stateless context)、事件(event context,或者request context)、页面(page context)、对话(conversation context)、会话(session context)、业务流(business process context)和应用程序(application context);
  3. seam引入一种双向注入(binjection)的方式。所谓的双向注入就是可以将上下文中的bean注入到另一个bean中,又或者将bean中的属性(property)直接发布在上下文中;
  4. seam的compoenet可以直接使用ejb 3.0的bean。

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

 1 package net.blogjava.max.hello.session;
 2 
 3 import org.jboss.seam.scopetype;
 4 import org.jboss.seam.annotations.name;
 5 import org.jboss.seam.annotations.scope;
 6 
 7 @name("hellowb")
 8 @scope(scopetype.page)
 9 public class hellowb {
10     private string name;
11     private string message;
12 
13     public string getname() {
14         return name;
15     }
16 
17     public void setname(string name) {
18         this.name = name;
19     }
20 
21     public string getmessage() {
22         return message;
23     }
24 
25     public void setmessage(string message) {
26         this.message = message;
27     }
28 
29     public void sayhello() {
30         message = "hello, "  name  "!";
31     }
32     
33     public void anotherevent() {
34         system.out.println("another request is coming");
35     }
36 }

通过上述代码,大家可以看到有两句annotation定义——name和scope。除此之外,并没有什么特别的地方,所以正是这两个annotation使hellowb成为一个可以被seam的运行时识别的component。name用于定义component的名称,是必须的;scope则用于定义component的作用域,是可选的,默认值为短对话(short conversation)。在本例中,hellowb的作用域是page。page与conversation都seam的杰作,在标准jsf是没有的。而且,这两个作用域是比较常用,我个人比较热衷于page作用域,所以在这里先谈一下page。

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

另外,一些jsf专家都推荐一种叫backing bean的风格。所谓的backing bean就是指一个jsf页面对应一个managed bean处理页面逻辑。page作用域非常适用这种情况,因为它是与页面一起序列化(serialize)到浏览器或保存在session中。如果大家还是不太明白的话,请看以下的xhtml代码。

 1 xml version="1.0" encoding="utf-8"?>
 2 doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
 3 
 4 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html">
 5     <head>
 6         <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
 7         <title>
 8             hello world
 9         title>
10     head>
11     <body>
12         <h:form>
13             <h:outputlabel value="name: " for="itname" />
14             <h:inputtext id="itname" value="#{hellowb.name}" />
15             <h:commandbutton action="#{hellowb.sayhello}" value="say hello" />
16             <h:commandbutton action="#{hellowb.anotherevent}" value="another reqeust" />
17             <hr />
18             <h2>
19                 <h:outputtext value="#{hellowb.message}" />
20             h2>
21         h:form>
22     body>
23 html>

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

在输入框中键入“max”,点击“say hello”按钮,将请求post-back到seam的组件中,由于按钮注册了组件的监听方法,所以hellowb的sayhello方法会被调用。它将通过值绑定所得的name与“hello”和“!”串起来,赋给message属性。因此,响应页面会如下图所示:

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

小结

本文粗略地介绍了一下jsf的页面逻辑处理组件——managed bean,还有很多关于seam的组件知识如bijection和conversation等还没有介绍,只有留待以后文章了。

posted on 2009-04-20 23:47 max 阅读(4627) 评论(10)  编辑  收藏 所属分类: seam系列

评论:
# re: seam的页面逻辑实现 2009-04-22 20:41 |
配置文件有麻烦的时候,也有便利的时候:有配置文件就不会因为某些小的更改而重新build过项目。  回复  
  
# re: seam的页面逻辑实现 2009-04-24 16:26 |
虽然现在还不懂,关注中  回复  
  
# re: seam的页面逻辑实现 2009-05-12 14:04 |
@yxc
希望这里能成为我技术修炼的好地方!  回复  
  
# re: seam的页面逻辑实现 2009-05-15 00:05 |
max 真的要赞你,请问你在哪个qq群,交流一下!qq:514251682  回复  
  
# re: seam的页面逻辑实现 2009-06-08 21:29 |
感谢max!写得非常棒,希望快快更新,一直关注ing!  回复  
  
# re: seam的页面逻辑实现 2009-06-09 20:05 |
是啊 max 期待更新 最近也在学seam呢...  回复  
  
# re: seam的页面逻辑实现 2009-06-13 18:52 |












账号:


密码:


验证码:


  回复  
  
# re: seam的页面逻辑实现 2009-06-13 19:01 |
亲爱的max:
您能不能告诉我,你上边的文章中的嵌入的代码:有红色有蓝色的 !这是怎么嵌入进去的啊??能告诉我吗?发我邮箱里边!或者有知道的加我qq:45522956  回复  
  
# re: seam的页面逻辑实现 2010-09-03 18:27 |
不错受教了。  回复  
  
# re: seam的页面逻辑实现 2010-09-26 10:54 |
期待seam系列续集......呵呵  回复  
  

只有注册用户后才能发表评论。


网站导航:
              
 
网站地图