posts - 14,  comments - 37,  trackbacks - 0
appfuse 的web包下有这么几个包
org.appfuse.webapp.action:
org.appfuse.webapp.filter:
org.appfuse.webapp.listerner:
org.appfuse.webapp.taglib:
org.appfuse.webapp.util
jsf 它有自己的配制文件  位于/ WEB-INF/faces-config.xml。在appfuse 的此文件中我们可以看到在
faces-config 下几种标记
application,navigation-rule,managed-bean,render-kit..
在application 下面定义了一个元素:
<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver </variable-resolver>


这个是为了与spring集成而加进来的, 在之前jsf 与spring 的集成是通过:
ApplicationContext ctx =FacesContextUtils.getWebApplicationContext( FacesContext.getCurrentInstance());
的方式在jsf的
managed-bean里调用spring配置文件中的bean.或者通过jsf-spring这个项目开发的第三方软件的方式.现
在通过spring的提供
的VariableResolver,我们在jsf的f配制文件里就可以像spring的配制文件一样在它里边配置类与类的依
赖关系.比如:
<managed-bean>
        
<managed-bean-name>userList</managed-bean-name>
        
<managed-bean-class>org.appfuse.webapp.action.UserList </managed-bean-class>
        
<managed-bean-scope>request</managed-bean-scope> 
        
<managed-property>
            
<property-name>userManager</property-name>
            
<value>#{userManager}</value> 
        
</managed-property>
    
</managed-bean> 

可以看到managed-bean的属性中的userManager 的值为#{userManager} 表示jsf这个managed-bean的属性
userManager是spring
配制文件中的名为 "userManager"的bean.可以看到通过这种方法把spring的IOC的理念引入了JSF中 .
在application 下还有locale-config和message-bundle标签是和这个应用的国际化文件相关的配制.在这
里表示国际化文件名为
ApplicationResources.默认是英文.支持en,es,fr,nl,pt_BR,zh_CN这几种locale.
然后是<navigation-rule>例如:
<navigation-rule>
        
<from-view-id>/users.jsp</from-view-id>
        
<navigation-case>
            
<from-outcome>add</from-outcome>
            
<to-view-id>/userProfile.jsp</to-view-id>
        
</navigation-case>
    
</navigation-rule>

    这个是定义页面导航的相关配置. 上述配制的含义为 如果当前是 user.jsp页面.此时如果页面转发
的名为add,就会返回userProfile.jsp
    页面.
    然后是<managed-bean>例如.
    
<managed-bean>
        
<managed-bean-name>basePage</managed-bean-name>
        
<managed-bean-class>org.appfuse.webapp.action.BasePage</managed-bean-class> 
        
<managed-bean-scope>request</managed-bean-scope>
    
</managed-bean>

它定义了jsf中所使用的bean.在JSF中我们可以把一个html元素与一个managed-bean的某个属性相绑定.也
可以把某个按钮的触发事件与
一个managed-bean的某个方法相关联.相对于struts来说,个人认为JSF更简单了.而且处理业务的时候我们
可以更好的利用面向对象的观点
页面之间的关系被映射成与它相绑定的类与类之间的关系.与它相比struts有点面向过程的意味.与JSF类
似的框架是tapestry. tapestry是通过
一个单独的xml格式的配制文件来配置html元素与类的属性的关系.而jsf是在页面的直接通过JSF标签属性
来绑定,总之他们都是面向组件,事件
触发的,而struts则是表单提交的方式,而且提交的数据局限于有限的几种格式.比如不能在form里定义
date类型的属性.(date类型form提交不过去)
除非像appfuse的struts版本那样定义一个action然后在它里边加上
static {
        ConvertUtils.register(
new CurrencyConverter(), Double.class);
        ConvertUtils.register(
new DateConverter(), Date.class );
 

然后所有的action从它继承.  在jsf 不存在这个问题.可以直接把managed-bean 的一个类型为date 或
double的属性与一个表单元素绑定.
还有一个名为render-kit 的元素.它里边定义了一个renderer.这个是jsf定义的装饰器.
      
<renderer>
         
<description>Replacement renderer for h:outputLabel</description>
         
<component-family>javax.faces.Output</component-family> 
         
<renderer-type>javax.faces.Label</renderer-type>
         
<renderer-class>org.appfuse.webapp.action.LabelRenderer</renderer-class>
      
</renderer>

      对于jsf 的所有输出的label 都通过用户定义的LabeRenderer来修饰. 打开
org.appfuse.webapp.action.LabelRenderer
      这个类我们会看到这个是用来修饰表单中的那些必填项的标签的。
org.appfuse.webapp.action包下主要是:managed-bean
CountryModel是一个和国家相关的类.在它里边声明了一个内部类.
LabelValueComparator实现Comparator接口.此类有一个带一个参数的构造函数.和一个类型为Comparator
的属性c
.实现了Comparator接口的compare方法.它的构造函数为 LabelValueComparator(Locale locale),具体的
实现为
c = Collator.getInstance (locale);Collator 执行国别敏感的 String比较.在compare  里的实现是
c.compare(lhs.getLabel(), rhs.getLabel());可以看到比较的元素是label.
CountryModel里还有一个方法.getCountries(Locale locale)这个方法是把操作系统所有的有效的locale
放到一个l类型为
ArrayList的集合countries里., 然后通过它定义的那个内部类的比较规则把countries里的元素进行比较
排序.最后把这个结果
集放到一个Map里.在JSF中Map中的元素可以被select 组件直接使用.
BasePage是定义的一个基本的类,它定义了managed-bean 应该有的共同的属性。其他的一些bean继承它

在它的构造函数里把JSF的上下文赋给了他自己的上下文变量facesContext.通过facesContext可以取得一
些jsp/servlet 所
拥有的对象,如request,response.
它还有一个名为setFacesContext的方法,这个主要是在测试的时候设置bean的上下文。
setUserManager 方法主要是设置这个bean 的userManager对象。当然在这里主要是为了与在faces-
config.xml 里的属性
userManager对应。例如:
<managed-bean>
        
<managed-bean-name>userList</managed-bean-name>
        
<managed-bean-class> org.appfuse.webapp.action.UserList</managed-bean-class> 
        
<managed-bean-scope>request</managed-bean-scope>
        
<managed-property>
            
<property-name>userManager</property-name> 
            
<value>#{userManager}</value> 
        
</managed-property>
  
</managed-bean>

    userList是继承于BsePage的。所以它也有setUserManager方法。在这里配置属性userManager
    的值为#{userManager},具体的实现还有通过setUserManager (UserManager userManager)这个方法
    来实现的。    setMailEngine(),setMessage(),setTemplateName()与setUserManager ()类似。
    getRequest(),getSession(),getResponse(),getServletContext(),都是直接或间接通过
facesContext 取得的。
    getParameter() 此方法就是从request范围内取根据输入参数名取出对象。
    getBundleName()和getBundle()两个合起来完成一件事情就是通过jstl的方式,根据locale 来取得
ResourceBundle
    对象。因为jsf相关的操作比较复杂。
具体实现是这样的。在web.xml里 配制了如下上下文参数
<context-param>
        
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext </param-name>
        
<param-value>ApplicationResources</param-value> 
</context-param>

然后在BasePage里定义了如下一些东东。
public static final String jstlBundleParam = "javax.servlet.jsp.jstl.fmt.localizationContext
";(就是前面定义的参数名)
然后就是方法getBundleName()它是通过getServletContext().getInitParameter(jstlBundleParam);来
把参数的值取出来。
它返回的就是<param-value>中指定的ApplicationResources。然后通过getBundle()方法根据locale来取
得ResourceBundle
ResourceBundle.getBundle (getBundleName(), getRequest().getLocale());.当然这些ResourceBundle
文件是放在/WEB-INF/
classes/下的.
getText(String key) 就是在前面取得的ResourceBundle里根据key来取得对应的值.
getText(String key, Object arg)的作用就是针对有{0},{1},{2},{3} 这种信息处理的.通过key从
ResourceBundle里取到信息值 ,然后
通过arg 对象填写里边的参数.
例如 key 的值为 "{0} 为无效信用卡号"。arg 为"12345" 最后的返回"12345 为无效信用卡号"
addMessage(String key, Object arg)这个方法是因为jsf有缺陷.当程序重定向后消息就丢失了,所以在
这里appfuse
自己写了一个方法.它从session里找"messages"对象, 如果没有找到就新建一个arrayList赋给messages.
然后通过getText(key, arg)把消息取出后添加
到messages里.然后把它放到session 的messages里.
addMessage(String key) 就是addMessage(key, null);
addError(String key, Object arg)和addError(String key)类似于上面的两个方法.只是放在session
范围内的"errors"里.
boolean hasErrors()就是判断在session范围内有没有"errors"对象.
sendUserMessage(User user, String msg, String url)调用在service包中定义的MailEngine类的相关
方法发送邮件信息
getConfiguration()方法是从 ServletContext范围里找"Constants.CONFIG"对象放到Map里返回.
getCountries()调用在CoutryModel中定义的方法,把国家信息放到一个Map返回.
FileUpload类是与上传文件相关的类.它有name 和file两个属性.以及和他们对应的get和set方法.这两个
属性是与前台html
元素绑定的.当然绑定是通过与他们对应的get 和set方法来实现的.
在这个类中还有一个名为upload()的方法.此方法用来处理上传文件事件.把上传的文件放到/resource/"
用户名"/下.
个人认为这个方法写的有问题..比如我们上传一个文件上传不上去.tomcat会报错.主要原因是这行代码:
OutputStream bos =new FileOutputStream(uploadDir + file.getName());其中uploadDir是我们定义的
资源存放位置,后边的哪个
 file.getName()其实是包含路径的.所以会报类似如下的错误:
Caused by: java.io.FileNotFoundException: H:\apache-tomcat-5.5.12\apache-tomcat-
5.5.12\webapps\myapp\resources\mraible\D:\costviewdetail.jsp (文件名、目录名或卷标语法不正确
。)
修改如下:
OutputStream bos = new FileOutputStream(uploadDir + this.getName());就是文件名设为我们填写的
重命名名称.
还有两个地方要同时修改。
 request.setAttribute ("location", dirPath.getAbsolutePath() + Constants.FILE_SEP
+this.getName());                     
request.setAttribute("link", link + this.getName());
都是把 file.getName()替换成 this.getName()。
          
 LabelRenderer就是前边提到的装饰器。
 具体工作原理如下,先把组件的所有属性取出来,然后找它的for属性。放到String id里。然后根据此
id,找相应的
 输入组件。如果找到。而且此组件的类型为required 则输出一个 "*" 一个空格"&nbsp;"然后开始输出
此label标签
 如果程序这个component 指定了class就以指定的class显示label如果没有指定class就以requreid 的
class显示
 此label.然后判断input是否为空,如果不为空把input.getClientId(context)的值放到String
renderedId里,否则把
 component.getClientId(context) 赋给 renderedId。然后输出把 renderedId作为for的属性值输出。
最后输出value
 的值。
 encodeEnd方法的操作如下,字符串marker里写 ":"如果label的value字段为空。marker赋值"" 然后输
出marker.然后结束
 label输出。
 
 总之这个装饰器的作用是如果label中的for 所指的对象的是required 的就在它显示的value前输出* 空
格。它也允许输出value
 为空的label.
 还有一个hasMessages()的方法,用来判断这个label是否有message.
 passwordHint 负责处理与密码提示相关的操作它继承于BasePage。
它有一个username 属性以及对应的get和set方法。可以把它和页面元素绑定。
还有个名为execute的方法。它负责向用户发送邮件。
这个类在faces-config.xml中的配置为
<managed-bean>
        
<managed-bean-name>passwordHint</managed-bean-name> 
        
<managed-bean-class>org.jsfdemo.webapp.action.PasswordHint</managed-bean-class>
        
<managed-bean-scope>request</managed-bean-scope>
        
<managed-property>
          
<property-name>username</property-name> 
          
<value>#{param.username}</value>
        
</managed-property>
        
<managed-property>
            
<property-name>userManager</property-name>
            
<value>#{userManager}</value> 
        
</managed-property>
        
<managed-property>
            
<property-name>mailEngine</property-name>
            
<value>#{mailEngine}</value>
        
</managed-property> 
        
<managed-property>
            
<property-name>message</property-name>
            
<value>#{mailMessage}</value>
        
</managed-property>
        
<managed-property> 
            
<property-name>templateName</property-name>
            
<value>accountCreated.vm</value>
        
</managed-property>
    
</managed-bean>

这个bean存在的范围为request然后,依赖注入userManager mailEngine message
templateName,前三个是在spring中配置的bean.最后一个是在/WEB-INF/classes下
定义的模板。
Reload 继承于BasePage 它有一个名为execute的方法。此方法在内部调用StartupListerner的
静态方法setupContext(),然后添加一条reload.successded 消息。然后返回"mainMenu"
SignupForm 继承BasePage 它有user 和roleManager两个属性。以及对应的set和get方法。
roleManger属性没有get方法。
还有getCountry() 和setCountry(String)这两个方法处理的是user中的address中的country字段
save()方法的具体流程如下。它先调用从BasePage里继承的getConfiguration()方法。从servletContext
里的Constants.CONFIG里把相关的信息放到一个Map里。然后再从Map里的Constants.ENC_ALGORITHM里取

算法名放到algorithm里。如果算法名为空。则algorithm="SHA"。调用StringUtil的encodePassword方法
加密用户的密码,加密算法为algorithm。然后把用户的密码设为这个加密后的值。然后把用户的enable
字段
设为true.用户的角色设为Constants.USER_ROLE .然后调用userManager把这个用户存到数据库中。
在session范围内设一个registed属性。通过acegi security框架提供的authentication的一个具体实现

UsernamePasswordAuthentictionToken(,)和用户的用户名和密码,创建一个Authentication对象auth.
然后通过WebApplicationContextUtils获得ApplicationContext对象ctx.通过ctx获得bean
"authenticationManager"
赋予类型为ProviderManager的authenticationManager对象。然后调用authenticationManager的
doAuthentication()
方法验证auth.把此方法返回的authentication对象放到SecurityContextHolder拥有的SecurityContext
对象的authentication
属性里。然后调用从BasePage里继承的方法sendUserMessage给用户发送确认信息。返回"mainMenu".在
faces-config.xml
中与此bean对应的相关配置类似于passwordHit.
UserForm这个类继承了类BasePage.它有属性roleManager,from,username,user,availableRoles以及与它
们对应的
set和get方法。
cancel()方法
它通过StringUtils这个类提供的equals方法来比较request范围内的"from"是否等于list.如果是,返
回"mainMenu".否则返回cancel.
edit()方法
如果属性值username不为空,通过userManager的getUser方法,以username为主键取user放到属性user里

否则以request.getRemoteUser()为主键取user.其他情况new 一个User对象。然后给这个对象添加一个角
色Constants.USER_ROLE
如果不是刚刚新建的用户,user.setConfirmPassword(user.getPassword ());
通过AuthenticationTrustResolver的实现类创建一个AuthenticationTrustResolver对象resovlver.
通过SecurityContextHolder对象获得SecurityContext 对象ctx.
如果ctx不为null.从它里边取出authentication对象。然后通过resolver 判断此authentication对象的
类型是否是rememberMe。
如果是,在session里设置属性cookieLogin的值为true.然后调用从超类那里继承的addMessage方法添加
一条"userProfile.cookieLogin"
的消息。然后返回"editProfile".
save()方法
通过属性user获得用户密码password。通过getParameter("userForm:originalPassword")获得用户原来
的密码,
通过getConfiguration().get(Constants.ENCRYPT_PASSWORD);取得保存在ServletContext范围内的属性
Constants.CONFIG的值放在一个Map
里,然后从此Map中取与属性Constants.ENCRYPT_PASSWORD对应的值。如果这个值为true.而且从request
范围取得的与encryptPass属性相
对应的值也为true.或者password和originalPassword不等,则从servletContext范围内,取得与
Constants.CONFIG对应的Map.从此Map中取得与
Constants.ENC_ALGORITHM对应的值赋予algorithm.如果algorithm为null,algorithm为SHA.
然后调用StringUtil.encodePassword (password, algorithm)加密passoword赋给user的password属性。
通过getRequest().getParameterValues("userForm:userRoles")获得用户的角色集放到UserRolesl里。
然后以UserRoles中的值为主键,
循环取出Role对象赋予此用户。
然后调用userManager.saveUser(user).把此用户保存到数据库里。如果 此步出现错误,添加一条错误信
息,返回"editProfile".
判断request范围内的参数from的值是否为list.
如果不是
 在session里把user赋给属性Constants.USER_KEY(userform)。添加一条"user,saved"消息。返
回"mainMenu"
否则
 如果从request范围内的parameter里取得的"userForm:version"值为"",添加一条消息addMessage("
user.added", user.getFullName());
 XXXXX 添加成功。调用sendUserMessage给此用户发邮件。返回list.
 否则
  添加一条 类似 XXXX被修改的消息,然后返回 "editProfile".
delete()方法。
 根据getUser().getUsername()值通过userManager删除此用户。添加一条此用户被删除的消息。返
回"list".
getFrom()方法。
如果用户名不为空,或request参数"editUser:add"不为空,或者参数"from"等于"list" ,返回list.
返回"";
Map getAvailableRoles() 方法。
如果此bean的属性availableRoles为null. 从servletContext里取出属性Constants.AVAILABLE_ROLES 的
值。然后把
它转换成Map.赋予avaibleRoles.
返回avaibleRoles.
getUserRoles方法。
把user 的Roles集合中的所有Role的名字放到一个字符数组里,返回。
它在faces-config.xml中的定义如下:
  
<managed-bean>
        
<managed-bean-name>userForm</managed-bean-name>
        
<managed-bean-class> org.appfuse.webapp.action.UserForm</managed-bean-class>
        
<managed-bean-scope>request</managed-bean-scope>
        
<managed-property>
          
<property-name>username</property-name> 
          
<value>#{param.username}</value>
        
</managed-property>
        
<managed-property>
            
<property-name>userManager</property-name>
            
<value>#{userManager}</value> 
        
</managed-property>
        
<managed-property>
            
<property-name>roleManager</property-name>
            
<value>#{roleManager}</value>
        
</managed-property> 
        
<managed-property>
            
<property-name>mailEngine</property-name>
            
<value>#{mailEngine}</value>
        
</managed-property>
        
<managed-property> 
            
<property-name>message</property-name>
            
<value>#{mailMessage}</value>
        
</managed-property>
        
<managed-property>
            
<property-name>templateName</property-name> 
            
<value>accountCreated.vm</value>
        
</managed-property>
    
</managed-bean>
    UserList继承于BasePage,它只定义了一个方法。
  
    public List getUsers() {
        return userManager.getUsers(null);
    }
    返回所有用户。
org.appfuse.webapp.filter
这个包下定义了一些过滤器
首先是GZIPFilter继承实现了spring提供的抽象类OncePerRequestFilter(每一次请求执行一次的过滤器)

doFilterInternal方法。 这个类的作用是通过gzip来压缩输出流。
private boolean isGZIPSupported(HttpServletRequest)
通过request获得TableTagParameters.PARAMETER_EXPORTING的属性值。放到字符串exporting里。
如果exporting不为null.说明此时是用displayTag以execel或xml或pdf的格式往外输出表格内容。此时不
应该
压缩输出流。所以返回false.
通过request获得http 头中的"accept-encoding"的属性值。如果此值中有gzip这个字符串,support就为
true.其他情况为false
通过request获得http 头中的"user-agent"属性值。如果此值是以httpunit开头 返回false.(此时是进行
页面测试,不需要压缩输出流)。
返回support.
doFilterInternal(HttpServletRequest request, HttpServletResponse response,  FilterChain
chain)
调用前边的方法判断是否需要压缩输出流。
如果需要
 新建 一个GZIPResponseWrapper(HttpServletResponse).对象把response 做为参数传过去。 然后调用
  chain.doFilter (request, wrappedResponse);
   wrappedResponse.finishResponse();
否则
 chain.doFilter (request, response);
 
GZIPResponseStream继承于ServletOutputStream.是实现对response进行 gzip 压缩的最终实现类。
 GZIPResponseWrapper继承了HttpServletResponseWrapper.是对GZIPResponseStream的一个包装。
类LocaleRequestWrapper继承了HttpServletRequestWrapper。它有一个不可被继承的属性
preferredLocale。
在它的构造函数里把参数userLocale的值赋给preferredLocale.
重构了getLocale()方法。如果preferredLocale 不为空,返回它,否则调用父类的方法。
重构了父类的getLocales()方法。如果preferredLocale不为空,调用父类的方法取得Locales后放到一个
列表里
如果此列表中有preferredLocale.从列表中把它删除把preferredLocale添加到此列表的开头。返回.
否则调用父类的getLocales()方法。
LocaleFilter 继承实现了OncePerRequestFilter 的doFilterInternal方法。
在此方法中,先request获得locale对象赋给字符串locale.如果locale不为null,通过字符串locale生成
一个Locale赋给preferredLocale.
然后获取一个session对象 request.getSession(false);
 request.getSession (boolean)的参数有true和false两个值,true为如果如果没有相同的session则创
建。如果有则覆盖,
 false则没有则创建有则不创建。
如果preferredLocale为null,
 从Session范围取得属性Constants.PREFERRED_LOCALE_KEY的值赋予preferredLocale。
如果preferredLocale不为null
 在Session范围设置属性Constants.PREFERRED_LOCALE_KEY 的值为preferredLocale。
 通过jstl的的Config在session范围内设置fmt的local为preferredLocale.
                Config.set(session, Config.FMT_LOCALE, preferredLocale);
如果preferredLocale 不为null,request的类型是LocaleRequestWrapper。
给request赋值new LocaleRequestWrapper(request, preferredLocale)。
把spring的LocaleCOntextHolder的属性Locale设为preferredLocale.
然后是
 chain.doFilter(request, response);
 LocaleContextHolder.setLocaleContext(null);
MessageFilter实现了Filter接口。
实现了doFilter 方法。在此方法中,从session里取属性messages的值。如果取到值,把这个值放到
reques范围内messages里.
从session里删掉这条属性。
对session范围内的errors属性执行类似操作。然后调用  chain.doFilter(req, res);
重构init 和destroy方法,在这两个方法里不执行任何代码。
org.appfuse.webapp.listener 这个包下是和监听相关的类。
StartupListener 这个类继承于spring的ContextLoaderListener类,实现了ServletContextListener接
口。
方法setupContext
通过   WebApplicationContextUtils.getRequiredWebApplicationContext(context) 获得spring的上下
文句柄ctx。
通过ctx获得bean "lookupManager"赋予LookupManager 对象mgr.然后把mgr.getAllRoles()做为
Constants.AVAILABLE_ROLES的
属性值放到context里。
覆盖了父类的contextinitialized方法。
首先调用父类的对应方法。然后根据输入的参数ServletContextEvent获得ServletContext对象。然后从
它里边获取Constants.CONFIG
对应的属性值。放到Map  config里。通过
WebApplicationContextUtils.getRequiredWebApplicationContext(context);获得spring上下文
ctx. 通过ctx获得bean "authenticationManager".赋予ProviderManager对象实例provider.
然后循环判断provider 的属性providers.如果它包含一个类型为RememberMeAuthenticationProvider的
实例,就在config里放一条属性
"rememberMeEnabled",值为Boolean.TRUE.
判断是否在spring的配置文件里定义了名为"passwordEncoder"
如果有 把encryptPassword赋值true.然后在config里添加属性Constants.ENCRYPT_PASSWORD,值为
Boolean.TRUE.如果spring配置文件
中定义的"passwordEncoder" 的类型是Md5PasswordEncoder. algorithm 赋值MD5,其他情况下赋值SHA.
然后在config 里添加一条属性
Constants.ENC_ALGORITHM .值为algorithm.
然后把config做为Constants.CONFIG.的值放到context里。
最后前边介绍的setupContext(context)方法。
总之这个类的作用就是在servletContext 根据实际情况设置 Constants.CONFIG属性值。
UserCounterlistener 这个类实现了ServletContextListener 和HttpSessionAttributeListener接口。
它有几个不可被继承的属性 COUNT_KEY,USERS_KEY,EVENT_KEY.有两个被transient修饰的属性
log和ServletContext 修饰的属性.(被transient修饰的属性在对象序列化的过程中是不被包括的,比如
把对象序列化保存到硬盘中的
过程中,此属性是不被保存的)。
还有两个私有属性, counter(int 型数据)和users(Set 集合).
实现了HttpSessionAttributeListener接口的 attributeAdded方法. 在这个方法中,程序先判断参数
event(类型为HttpSessionBindingEvent)
的名字是否等于属性EVENT_KEY的值
(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY).
如果相等,取event的值.然后赋给SecurityContext 对象securityContext.根据它取得authentication 属
性,把authentication对象中的principal
赋给 User对象user.然后调用addUsername方法添加此用户.
实现了HttpSessionAttributeListener的attributeRemoved方法,在这个方法中先判断event的名字是否为
EVENT_KEY.如果是把event的值
赋予SecurityContext对象securityContext.然后通过它取得储存在它的属性authentication中的
principal对象赋予User对象user.然后调用
removeUsername方法删除此对象.
实现了HttpSessionAttributeListener的attributeReplaced方法,但是在此方法中没有任何代码.
公共方法contextInitialized(ServletContextEvent sce) 此方法被synchronized关键字修饰,表示此方
法是线程互斥的.在
此方法中,先通过
输入参数ServletContextEvent,获得ServletContext对象.然后在ServletContext里添加属性COUNT_KEY,
值为counter的字符串形式表达.
公共方法contextDestroyed,此方法是被synchronized 关键字修饰的,在此方法中给属性
servletContext,users 赋值null,counter 赋值0.
friend 方法 incrementUserCounter() 此方法也是线程互斥的,它servletContext里把COUNT_KEY取出加
一后再放回。(不写范围表达的方法就是friend,范围是本包和子类)
friend 方法decrementUserCounter 它的作用是把servletContext里的COUNT_KEY减一后再放回,当然它
也是线程互斥的。
friend 方法addUsername  此方法的作用是把把用户添加到servletContext范围内与属性USERS_KEY对应
的HashMap里。然后调用incrementUserCounter方法。这个方法也是线程互斥的。
friend方法removeUsername 此方法的作用是把用户从servletContext范围内与属性USER_KEY对应的
HashMap中删掉。然后调用decrementUserCounter方法。
org.jsfdemo.webapp.taglib包下是appfuse自定义标签相对应的类.
首先看一下这个自定义标签的tld文件 appfuse.tld.(这个文件会根据你的项目名而定)
在这个文件里首先配置了两个监听类StartupListener 和UserCounterListener.
然后定义了一个constants的tag.与这个tag对应的<tag-class>是ConstantsTag,对应的<tei-class>是
ConstantsTei.并且定义了这个tag有三个属性className,scope,var.
其实这个标签的作用是把一个了类放到scope指定的范围里。
类ConstantsTag继承了TagSupport类
它有clazz ,scope,var 三个属性以及对应的set和get方法,通过这些可以让标签的属性与具体的tag类的
属性关联起来。即
此自定义标签的class ,scope 和var属性与这里的clazz ,scope,var 对应。
它有一个静态的 不可被继承的Map scopes.然后通过一个static 块来初始化它如下:
static {
        scopes.put(
"page"new Integer(PageContext.PAGE_SCOPE));
        scopes.put(
"request"new Integer(PageContext.REQUEST_SCOPE ));
        scopes.put(
"session"new Integer(PageContext.SESSION_SCOPE));
        scopes.put(
"application"new Integer(PageContext.APPLICATION_SCOPE));
    }

因为使用的是jdk1.5所以这种写法没有错误 :)。
getScope(String scopeName) 这个方法的作用就是通过从上边定义的那个scopes里取与scopeName对应的
值。返回的数据
类型是int.
覆盖了TagSupport的 doStartTag方法,此方法的作用是把class 属性指定的类中的var指定的属性保存在
scope所指定的范围内。
如果class 为空class的默认值是Constants。scope如果为空默认值是PageContext.PAGE_SCOPE,var如果
为空则保存全部声明的属性。
然后返回 SKIP_BODY(因为这个标签没有真文,所以不需要和正文发生交互,也不会判断正文,所以返回
SKIP_BODY).
覆盖了父类的release方法,在此方法中释放占用资源。个人认为它的这个方法有误(appfuse 1.9 jsf
)应该是scope = null;而不是
scope = Constants.class.getName();
类ConstantsTei 继承了TagExtraInfo 覆盖了getVariableInfo方法。
  注: 通过扩展类javax.servlet.jsp.TagExtraInfo定义tag extra info类。一个TagExtraInfo必须实
现getVariableInfo方法以返回包含下列信息的VariableInfo对象数组:
  变量名 ,变量类 ,变量是否引用新对象 , 变量可用性 。
  Web容器向getVariableInfo方法传递包含每一个标签属性的属性-值元组的名为data的参数。这些属性
可以用于为VariableInfo对象提供脚本变量名和类。
所以这个类是与脚本变量有关的。这个方法的作用是把class指定的类的var属性,作为一个脚本变量返回
。如果var为空,就对全部变量进行处理。
返回的脚本变量的类型为String. 变量可以引用新对象,变量可用的范围是VariableInfo.AT_END(在结束
标签之后直到页面的结束 ).
 
org.appfuse.webapp.util
此包下是一些在web开发过程中用到的实用类。
FacesUtils 类,这个类的所有方法都是静态的。
getServletContext() 通过Facescontext对象获得servletContext对象。
getJsfEl(String value) 这个 方法的作用是 返回 "#{" + value + "}";
Application getApplication()
这个方法通过 FactoryFinder 获取application对象。
FactoryFinder提供了查找在jsf API中定义的所有factory对象的算法。如果在 system 中有一个属性与
想要查找的factory同名,它的值就做为你想要查找的factory返回.在system 中没有找到,如果在你的
web 应用的资源路径里找faces.properties文件。如果文件中包含与所要查找对象同名的属性,这个属性
就做为这个factory执行类的名字。最后如果存在META-INF/services/{factory-class-name}资源文件(比
如在lib包里的jar文件中)。读此文件的第一行做为factory实现类的名字。
factory Name有这么几种
APPLICATION_FACTORY------与ApplicationFactory对应的属性名.
FACES_CONTEXT_FACTORY----FacesContextFactory对应的属性名.
LIFECYCLE_FACTORY--------LifecycleFactory对应的属性名.
RENDER_KIT_FACTORY-------RenderKitFactory对应的属性名.
TREE_FACTORY-------------TreeFactory对应的属性名.
在这里通过FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY)获得ApplicationFactory
对象.然后再通过它获得Application对象.
getValueBinding(String el) 这个方法如下:
return getApplication().createValueBinding(el);
这个类是根据输入的对象名创建一个ValueBinding对象.比如在jsf的配置文件里定义了一个managed bean
"userBean",通过以下方式getValueBinding("#{userBean}")就创建了一个ValueBinding对象,通过此对象
可以获得userBean实例.
getELValue(String el)这个方法如下:
getValueBinding(el).getValue(FacesContext.getCurrentInstance());
此方法就是获得与el相对应的实例.
  
getManagedBean(String beanName) 此方法代码大体如下:
getValueBinding(getJsfEl(beanName)).getValue( FacesContext.getCurrentInstance());
:)就是通过前面定义的一系列方法获得与beanName对应的 Managed bean实例.
resetManagedBean 这个方法的作用是删除与beanName对应的Managed bean.具体如下:
getValueBinding(getJsfEl(beanName)).setValue(FacesContext.getCurrentInstance(),null); 
setManagedBeanInSession(String beanName,Object managedBean)这个方法的作用是
把managedBean 放到session范围内的属性beanName里。
getRequestParameter(String name)  从 request范围取得与parameter对应的参数。
addInfoMessage(String clientId,String msg)给一个特定的客户(由clientId指定)添加一条jsf消息,
消息的安全程度是FacesMessage.SEVERITY_INFO.
addInfoMessage(String msg) 这个方法就是添加一条jsf消息。如下:
addInfoMessage(null, msg);
addErrorMessage(String clientId, String msg)和 addErrorMessage(String msg)与前边类似分别是给
特定客户添加一条错误消息和添加一条错误消息。
evalInt(String el)
这个方法是判断参数el是不是某个对象的 jsf 表达,
如果是,通过el构建ValueBinding对象,进而获得此el对应的对象.如果是Integer 直接返回,否则把它转换
成Integer返回
否则 返回Integer(el);
还有 getRequest(),getResponse(),getSession()方法.
 RequestUtil 类的所有方法也是静态的。
setCookie(HttpServletResponse response, String name, String value, String path)
这个是用来发送cookie的。以参数name 和value构建一个cookie,它是非安全的,路径设为path.生命期为30天。然后添加到response里。
getCookie(HttpServletRequest request, String name) 根据name 从参数request里找到相应的cookie.
deleteCookie(HttpServletResponse response, Cookie cookie, String path)
通过把生命周期设为0的方式删除一个cookie.
getAppURL(HttpServletRequest request)
这个方法是通过request来获得应用的URL.
posted on 2007-07-12 10:43 冰封的爱 阅读(1142) 评论(0)  编辑  收藏 所属分类: J2EE

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


网站导航:
 
<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用链接

留言簿(3)

随笔档案

文章分类

文章档案

相册

搜索

  •  

最新评论

阅读排行榜

评论排行榜