appfuse 的web包下有這么幾個(gè)包
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 下幾種標(biāo)記
application,navigation-rule,managed-bean,render-kit..
在application 下面定義了一個(gè)元素:
<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver </variable-resolver>
這個(gè)是為了與spring集成而加進(jìn)來(lái)的, 在之前jsf 與spring 的集成是通過(guò):
ApplicationContext ctx =FacesContextUtils.getWebApplicationContext( FacesContext.getCurrentInstance());
的方式在jsf的
managed-bean里調(diào)用spring配置文件中的bean.或者通過(guò)jsf-spring這個(gè)項(xiàng)目開(kāi)發(fā)的第三方軟件的方式.現(xiàn)
在通過(guò)spring的提供
的VariableResolver,我們?cè)趈sf的f配制文件里就可以像spring的配制文件一樣在它里邊配置類與類的依
userManager是spring
配制文件中的名為 "userManager"的bean.可以看到通過(guò)這種方法把spring的IOC的理念引入了JSF中 .
在application 下還有l(wèi)ocale-config和message-bundle標(biāo)簽是和這個(gè)應(yīng)用的國(guó)際化文件相關(guān)的配制.在這
里表示國(guó)際化文件名為
ApplicationResources.默認(rèn)是英文.支持en,es,fr,nl,pt_BR,zh_CN這幾種locale.
的名為add,就會(huì)返回userProfile.jsp
頁(yè)面.
可以把某個(gè)按鈕的觸發(fā)事件與
一個(gè)managed-bean的某個(gè)方法相關(guān)聯(lián).相對(duì)于struts來(lái)說(shuō),個(gè)人認(rèn)為JSF更簡(jiǎn)單了.而且處理業(yè)務(wù)的時(shí)候我們
可以更好的利用面向?qū)ο蟮挠^點(diǎn)
頁(yè)面之間的關(guān)系被映射成與它相綁定的類與類之間的關(guān)系.與它相比struts有點(diǎn)面向過(guò)程的意味.與JSF類
似的框架是tapestry. tapestry是通過(guò)
一個(gè)單獨(dú)的xml格式的配制文件來(lái)配置html元素與類的屬性的關(guān)系.而jsf是在頁(yè)面的直接通過(guò)JSF標(biāo)簽屬性
來(lái)綁定,總之他們都是面向組件,事件
觸發(fā)的,而struts則是表單提交的方式,而且提交的數(shù)據(jù)局限于有限的幾種格式.比如不能在form里定義
double的屬性與一個(gè)表單元素綁定.
org.appfuse.webapp.action.LabelRenderer
這個(gè)類我們會(huì)看到這個(gè)是用來(lái)修飾表單中的那些必填項(xiàng)的標(biāo)簽的。
org.appfuse.webapp.action包下主要是:managed-bean
CountryModel是一個(gè)和國(guó)家相關(guān)的類.在它里邊聲明了一個(gè)內(nèi)部類.
LabelValueComparator實(shí)現(xiàn)Comparator接口.此類有一個(gè)帶一個(gè)參數(shù)的構(gòu)造函數(shù).和一個(gè)類型為Comparator
的屬性c
.實(shí)現(xiàn)了Comparator接口的compare方法.它的構(gòu)造函數(shù)為 LabelValueComparator(Locale locale),具體的
實(shí)現(xiàn)為
c = Collator.getInstance (locale);Collator 執(zhí)行國(guó)別敏感的 String比較.在compare 里的實(shí)現(xiàn)是
c.compare(lhs.getLabel(), rhs.getLabel());可以看到比較的元素是label.
CountryModel里還有一個(gè)方法.getCountries(Locale locale)這個(gè)方法是把操作系統(tǒng)所有的有效的locale
放到一個(gè)l類型為
ArrayList的集合countries里., 然后通過(guò)它定義的那個(gè)內(nèi)部類的比較規(guī)則把countries里的元素進(jìn)行比較
排序.最后把這個(gè)結(jié)果
集放到一個(gè)Map里.在JSF中Map中的元素可以被select 組件直接使用.
BasePage是定義的一個(gè)基本的類,它定義了managed-bean 應(yīng)該有的共同的屬性。其他的一些bean繼承它
。
在它的構(gòu)造函數(shù)里把JSF的上下文賦給了他自己的上下文變量facesContext.通過(guò)facesContext可以取得一
些jsp/servlet 所
擁有的對(duì)象,如request,response.
它還有一個(gè)名為setFacesContext的方法,這個(gè)主要是在測(cè)試的時(shí)候設(shè)置bean的上下文。
setUserManager 方法主要是設(shè)置這個(gè)bean 的userManager對(duì)象。當(dāng)然在這里主要是為了與在faces-
facesContext 取得的。
getParameter() 此方法就是從request范圍內(nèi)取根據(jù)輸入?yún)?shù)名取出對(duì)象。
getBundleName()和getBundle()兩個(gè)合起來(lái)完成一件事情就是通過(guò)jstl的方式,根據(jù)locale 來(lái)取得
ResourceBundle
對(duì)象。因?yàn)閖sf相關(guān)的操作比較復(fù)雜。
具體實(shí)現(xiàn)是這樣的。在web.xml里 配制了如下上下文參數(shù)
<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
";(就是前面定義的參數(shù)名)
然后就是方法getBundleName()它是通過(guò)getServletContext().getInitParameter(jstlBundleParam);來(lái)
把參數(shù)的值取出來(lái)。
它返回的就是<param-value>中指定的ApplicationResources。然后通過(guò)getBundle()方法根據(jù)locale來(lái)取
得ResourceBundle
ResourceBundle.getBundle (getBundleName(), getRequest().getLocale());.當(dāng)然這些ResourceBundle
文件是放在/WEB-INF/
classes/下的.
getText(String key) 就是在前面取得的ResourceBundle里根據(jù)key來(lái)取得對(duì)應(yīng)的值.
getText(String key, Object arg)的作用就是針對(duì)有{0},{1},{2},{3} 這種信息處理的.通過(guò)key從
ResourceBundle里取到信息值 ,然后
通過(guò)arg 對(duì)象填寫(xiě)里邊的參數(shù).
例如 key 的值為 "{0} 為無(wú)效信用卡號(hào)"。arg 為"12345" 最后的返回"12345 為無(wú)效信用卡號(hào)"
addMessage(String key, Object arg)這個(gè)方法是因?yàn)閖sf有缺陷.當(dāng)程序重定向后消息就丟失了,所以在
這里appfuse
自己寫(xiě)了一個(gè)方法.它從session里找"messages"對(duì)象, 如果沒(méi)有找到就新建一個(gè)arrayList賦給messages.
然后通過(guò)getText(key, arg)把消息取出后添加
到messages里.然后把它放到session 的messages里.
addMessage(String key) 就是addMessage(key, null);
addError(String key, Object arg)和addError(String key)類似于上面的兩個(gè)方法.只是放在session
范圍內(nèi)的"errors"里.
boolean hasErrors()就是判斷在session范圍內(nèi)有沒(méi)有"errors"對(duì)象.
sendUserMessage(User user, String msg, String url)調(diào)用在service包中定義的MailEngine類的相關(guān)
方法發(fā)送郵件信息
getConfiguration()方法是從 ServletContext范圍里找"Constants.CONFIG"對(duì)象放到Map里返回.
getCountries()調(diào)用在CoutryModel中定義的方法,把國(guó)家信息放到一個(gè)Map返回.
FileUpload類是與上傳文件相關(guān)的類.它有name 和file兩個(gè)屬性.以及和他們對(duì)應(yīng)的get和set方法.這兩個(gè)
屬性是與前臺(tái)html
元素綁定的.當(dāng)然綁定是通過(guò)與他們對(duì)應(yīng)的get 和set方法來(lái)實(shí)現(xiàn)的.
在這個(gè)類中還有一個(gè)名為upload()的方法.此方法用來(lái)處理上傳文件事件.把上傳的文件放到/resource/"
用戶名"/下.
個(gè)人認(rèn)為這個(gè)方法寫(xiě)的有問(wèn)題..比如我們上傳一個(gè)文件上傳不上去.tomcat會(huì)報(bào)錯(cuò).主要原因是這行代碼:
OutputStream bos =new FileOutputStream(uploadDir + file.getName());其中uploadDir是我們定義的
資源存放位置,后邊的哪個(gè)
file.getName()其實(shí)是包含路徑的.所以會(huì)報(bào)類似如下的錯(cuò)誤:
Caused by: java.io.FileNotFoundException: H:\apache-tomcat-5.5.12\apache-tomcat-
5.5.12\webapps\myapp\resources\mraible\D:\costviewdetail.jsp (文件名、目錄名或卷標(biāo)語(yǔ)法不正確
。)
修改如下:
OutputStream bos = new FileOutputStream(uploadDir + this.getName());就是文件名設(shè)為我們填寫(xiě)的
重命名名稱.
還有兩個(gè)地方要同時(shí)修改。
request.setAttribute ("location", dirPath.getAbsolutePath() + Constants.FILE_SEP
+this.getName());
request.setAttribute("link", link + this.getName());
都是把 file.getName()替換成 this.getName()。
LabelRenderer就是前邊提到的裝飾器。
具體工作原理如下,先把組件的所有屬性取出來(lái),然后找它的for屬性。放到String id里。然后根據(jù)此
id,找相應(yīng)的
輸入組件。如果找到。而且此組件的類型為required 則輸出一個(gè) "*" 一個(gè)空格" "然后開(kāi)始輸出
此label標(biāo)簽
如果程序這個(gè)component 指定了class就以指定的class顯示label如果沒(méi)有指定class就以requreid 的
class顯示
此label.然后判斷input是否為空,如果不為空把input.getClientId(context)的值放到String
renderedId里,否則把
component.getClientId(context) 賦給 renderedId。然后輸出把 renderedId作為for的屬性值輸出。
最后輸出value
的值。
encodeEnd方法的操作如下,字符串marker里寫(xiě) ":"如果label的value字段為空。marker賦值"" 然后輸
出marker.然后結(jié)束
label輸出。
總之這個(gè)裝飾器的作用是如果label中的for 所指的對(duì)象的是required 的就在它顯示的value前輸出* 空
格。它也允許輸出value
為空的label.
還有一個(gè)hasMessages()的方法,用來(lái)判斷這個(gè)label是否有message.
Reload 繼承于BasePage 它有一個(gè)名為execute的方法。此方法在內(nèi)部調(diào)用StartupListerner的
靜態(tài)方法setupContext(),然后添加一條reload.successded 消息。然后返回"mainMenu"
SignupForm 繼承BasePage 它有user 和roleManager兩個(gè)屬性。以及對(duì)應(yīng)的set和get方法。
roleManger屬性沒(méi)有g(shù)et方法。
還有g(shù)etCountry() 和setCountry(String)這兩個(gè)方法處理的是user中的address中的country字段
save()方法的具體流程如下。它先調(diào)用從BasePage里繼承的getConfiguration()方法。從servletContext
里的Constants.CONFIG里把相關(guān)的信息放到一個(gè)Map里。然后再?gòu)腗ap里的Constants.ENC_ALGORITHM里取
出
算法名放到algorithm里。如果算法名為空。則algorithm="SHA"。調(diào)用StringUtil的encodePassword方法
加密用戶的密碼,加密算法為algorithm。然后把用戶的密碼設(shè)為這個(gè)加密后的值。然后把用戶的enable
字段
設(shè)為true.用戶的角色設(shè)為Constants.USER_ROLE .然后調(diào)用userManager把這個(gè)用戶存到數(shù)據(jù)庫(kù)中。
在session范圍內(nèi)設(shè)一個(gè)registed屬性。通過(guò)acegi security框架提供的authentication的一個(gè)具體實(shí)現(xiàn)
類
UsernamePasswordAuthentictionToken(,)和用戶的用戶名和密碼,創(chuàng)建一個(gè)Authentication對(duì)象auth.
然后通過(guò)WebApplicationContextUtils獲得ApplicationContext對(duì)象ctx.通過(guò)ctx獲得bean
"authenticationManager"
賦予類型為ProviderManager的authenticationManager對(duì)象。然后調(diào)用authenticationManager的
doAuthentication()
方法驗(yàn)證auth.把此方法返回的authentication對(duì)象放到SecurityContextHolder擁有的SecurityContext
對(duì)象的authentication
屬性里。然后調(diào)用從BasePage里繼承的方法sendUserMessage給用戶發(fā)送確認(rèn)信息。返回"mainMenu".在
faces-config.xml
中與此bean對(duì)應(yīng)的相關(guān)配置類似于passwordHit.
UserForm這個(gè)類繼承了類BasePage.它有屬性roleManager,from,username,user,availableRoles以及與它
們對(duì)應(yīng)的
set和get方法。
cancel()方法
它通過(guò)StringUtils這個(gè)類提供的equals方法來(lái)比較request范圍內(nèi)的"from"是否等于list.如果是,返
回"mainMenu".否則返回cancel.
edit()方法
如果屬性值username不為空,通過(guò)userManager的getUser方法,以u(píng)sername為主鍵取user放到屬性u(píng)ser里
。
否則以request.getRemoteUser()為主鍵取user.其他情況new 一個(gè)User對(duì)象。然后給這個(gè)對(duì)象添加一個(gè)角
色Constants.USER_ROLE
如果不是剛剛新建的用戶,user.setConfirmPassword(user.getPassword ());
通過(guò)AuthenticationTrustResolver的實(shí)現(xiàn)類創(chuàng)建一個(gè)AuthenticationTrustResolver對(duì)象resovlver.
通過(guò)SecurityContextHolder對(duì)象獲得SecurityContext 對(duì)象ctx.
如果ctx不為null.從它里邊取出authentication對(duì)象。然后通過(guò)resolver 判斷此authentication對(duì)象的
類型是否是rememberMe。
如果是,在session里設(shè)置屬性cookieLogin的值為true.然后調(diào)用從超類那里繼承的addMessage方法添加
一條"userProfile.cookieLogin"
的消息。然后返回"editProfile".
save()方法
通過(guò)屬性u(píng)ser獲得用戶密碼password。通過(guò)getParameter("userForm:originalPassword")獲得用戶原來(lái)
的密碼,
通過(guò)getConfiguration().get(Constants.ENCRYPT_PASSWORD);取得保存在ServletContext范圍內(nèi)的屬性
Constants.CONFIG的值放在一個(gè)Map
里,然后從此Map中取與屬性Constants.ENCRYPT_PASSWORD對(duì)應(yīng)的值。如果這個(gè)值為true.而且從request
范圍取得的與encryptPass屬性相
對(duì)應(yīng)的值也為true.或者password和originalPassword不等,則從servletContext范圍內(nèi),取得與
Constants.CONFIG對(duì)應(yīng)的Map.從此Map中取得與
Constants.ENC_ALGORITHM對(duì)應(yīng)的值賦予algorithm.如果algorithm為null,algorithm為SHA.
然后調(diào)用StringUtil.encodePassword (password, algorithm)加密passoword賦給user的password屬性。
通過(guò)getRequest().getParameterValues("userForm:userRoles")獲得用戶的角色集放到UserRolesl里。
然后以UserRoles中的值為主鍵,
循環(huán)取出Role對(duì)象賦予此用戶。
然后調(diào)用userManager.saveUser(user).把此用戶保存到數(shù)據(jù)庫(kù)里。如果 此步出現(xiàn)錯(cuò)誤,添加一條錯(cuò)誤信
息,返回"editProfile".
判斷request范圍內(nèi)的參數(shù)from的值是否為list.
如果不是
在session里把user賦給屬性Constants.USER_KEY(userform)。添加一條"user,saved"消息。返
回"mainMenu"
否則
如果從request范圍內(nèi)的parameter里取得的"userForm:version"值為"",添加一條消息addMessage("
user.added", user.getFullName());
XXXXX 添加成功。調(diào)用sendUserMessage給此用戶發(fā)郵件。返回list.
否則
添加一條 類似 XXXX被修改的消息,然后返回 "editProfile".
delete()方法。
根據(jù)getUser().getUsername()值通過(guò)userManager刪除此用戶。添加一條此用戶被刪除的消息。返
回"list".
getFrom()方法。
如果用戶名不為空,或request參數(shù)"editUser:add"不為空,或者參數(shù)"from"等于"list" ,返回list.
返回"";
Map getAvailableRoles() 方法。
如果此bean的屬性availableRoles為null. 從servletContext里取出屬性Constants.AVAILABLE_ROLES 的
值。然后把
它轉(zhuǎn)換成Map.賦予avaibleRoles.
返回avaibleRoles.
UserList繼承于BasePage,它只定義了一個(gè)方法。
public List getUsers() {
return userManager.getUsers(null);
}
返回所有用戶。
org.appfuse.webapp.filter
這個(gè)包下定義了一些過(guò)濾器
首先是GZIPFilter繼承實(shí)現(xiàn)了spring提供的抽象類OncePerRequestFilter(每一次請(qǐng)求執(zhí)行一次的過(guò)濾器)
的
doFilterInternal方法。 這個(gè)類的作用是通過(guò)gzip來(lái)壓縮輸出流。
private boolean isGZIPSupported(HttpServletRequest)
通過(guò)request獲得TableTagParameters.PARAMETER_EXPORTING的屬性值。放到字符串exporting里。
如果exporting不為null.說(shuō)明此時(shí)是用displayTag以execel或xml或pdf的格式往外輸出表格內(nèi)容。此時(shí)不
應(yīng)該
壓縮輸出流。所以返回false.
通過(guò)request獲得http 頭中的"accept-encoding"的屬性值。如果此值中有g(shù)zip這個(gè)字符串,support就為
true.其他情況為false
通過(guò)request獲得http 頭中的"user-agent"屬性值。如果此值是以httpunit開(kāi)頭 返回false.(此時(shí)是進(jìn)行
頁(yè)面測(cè)試,不需要壓縮輸出流)。
返回support.
doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain
chain)
調(diào)用前邊的方法判斷是否需要壓縮輸出流。
如果需要
新建 一個(gè)GZIPResponseWrapper(HttpServletResponse).對(duì)象把response 做為參數(shù)傳過(guò)去。 然后調(diào)用
chain.doFilter (request, wrappedResponse);
wrappedResponse.finishResponse();
否則
chain.doFilter (request, response);
GZIPResponseStream繼承于ServletOutputStream.是實(shí)現(xiàn)對(duì)response進(jìn)行 gzip 壓縮的最終實(shí)現(xiàn)類。
GZIPResponseWrapper繼承了HttpServletResponseWrapper.是對(duì)GZIPResponseStream的一個(gè)包裝。
類LocaleRequestWrapper繼承了HttpServletRequestWrapper。它有一個(gè)不可被繼承的屬性
preferredLocale。
在它的構(gòu)造函數(shù)里把參數(shù)userLocale的值賦給preferredLocale.
重構(gòu)了getLocale()方法。如果preferredLocale 不為空,返回它,否則調(diào)用父類的方法。
重構(gòu)了父類的getLocales()方法。如果preferredLocale不為空,調(diào)用父類的方法取得Locales后放到一個(gè)
列表里
如果此列表中有preferredLocale.從列表中把它刪除把preferredLocale添加到此列表的開(kāi)頭。返回.
否則調(diào)用父類的getLocales()方法。
LocaleFilter 繼承實(shí)現(xiàn)了OncePerRequestFilter 的doFilterInternal方法。
在此方法中,先request獲得locale對(duì)象賦給字符串locale.如果locale不為null,通過(guò)字符串locale生成
一個(gè)Locale賦給preferredLocale.
然后獲取一個(gè)session對(duì)象 request.getSession(false);
request.getSession (boolean)的參數(shù)有true和false兩個(gè)值,true為如果如果沒(méi)有相同的session則創(chuàng)
建。如果有則覆蓋,
false則沒(méi)有則創(chuàng)建有則不創(chuàng)建。
如果preferredLocale為null,
從Session范圍取得屬性Constants.PREFERRED_LOCALE_KEY的值賦予preferredLocale。
如果preferredLocale不為null
在Session范圍設(shè)置屬性Constants.PREFERRED_LOCALE_KEY 的值為preferredLocale。
通過(guò)jstl的的Config在session范圍內(nèi)設(shè)置fmt的local為preferredLocale.
Config.set(session, Config.FMT_LOCALE, preferredLocale);
如果preferredLocale 不為null,request的類型是LocaleRequestWrapper。
給request賦值new LocaleRequestWrapper(request, preferredLocale)。
把spring的LocaleCOntextHolder的屬性Locale設(shè)為preferredLocale.
然后是
chain.doFilter(request, response);
LocaleContextHolder.setLocaleContext(null);
MessageFilter實(shí)現(xiàn)了Filter接口。
實(shí)現(xiàn)了doFilter 方法。在此方法中,從session里取屬性messages的值。如果取到值,把這個(gè)值放到
reques范圍內(nèi)messages里.
從session里刪掉這條屬性。
對(duì)session范圍內(nèi)的errors屬性執(zhí)行類似操作。然后調(diào)用 chain.doFilter(req, res);
重構(gòu)init 和destroy方法,在這兩個(gè)方法里不執(zhí)行任何代碼。
org.appfuse.webapp.listener 這個(gè)包下是和監(jiān)聽(tīng)相關(guān)的類。
StartupListener 這個(gè)類繼承于spring的ContextLoaderListener類,實(shí)現(xiàn)了ServletContextListener接
口。
方法setupContext
通過(guò) WebApplicationContextUtils.getRequiredWebApplicationContext(context) 獲得spring的上下
文句柄ctx。
通過(guò)ctx獲得bean "lookupManager"賦予LookupManager 對(duì)象mgr.然后把mgr.getAllRoles()做為
Constants.AVAILABLE_ROLES的
屬性值放到context里。
覆蓋了父類的contextinitialized方法。
首先調(diào)用父類的對(duì)應(yīng)方法。然后根據(jù)輸入的參數(shù)ServletContextEvent獲得ServletContext對(duì)象。然后從
它里邊獲取Constants.CONFIG
對(duì)應(yīng)的屬性值。放到Map config里。通過(guò)
WebApplicationContextUtils.getRequiredWebApplicationContext(context);獲得spring上下文
ctx. 通過(guò)ctx獲得bean "authenticationManager".賦予ProviderManager對(duì)象實(shí)例provider.
然后循環(huán)判斷provider 的屬性providers.如果它包含一個(gè)類型為RememberMeAuthenticationProvider的
實(shí)例,就在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)方法。
總之這個(gè)類的作用就是在servletContext 根據(jù)實(shí)際情況設(shè)置 Constants.CONFIG屬性值。
UserCounterlistener 這個(gè)類實(shí)現(xiàn)了ServletContextListener 和HttpSessionAttributeListener接口。
它有幾個(gè)不可被繼承的屬性 COUNT_KEY,USERS_KEY,EVENT_KEY.有兩個(gè)被transient修飾的屬性
log和ServletContext 修飾的屬性.(被transient修飾的屬性在對(duì)象序列化的過(guò)程中是不被包括的,比如
把對(duì)象序列化保存到硬盤(pán)中的
過(guò)程中,此屬性是不被保存的)。
還有兩個(gè)私有屬性, counter(int 型數(shù)據(jù))和users(Set 集合).
實(shí)現(xiàn)了HttpSessionAttributeListener接口的 attributeAdded方法. 在這個(gè)方法中,程序先判斷參數(shù)
event(類型為HttpSessionBindingEvent)
的名字是否等于屬性EVENT_KEY的值
(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY).
如果相等,取event的值.然后賦給SecurityContext 對(duì)象securityContext.根據(jù)它取得authentication 屬
性,把a(bǔ)uthentication對(duì)象中的principal
賦給 User對(duì)象user.然后調(diào)用addUsername方法添加此用戶.
實(shí)現(xiàn)了HttpSessionAttributeListener的attributeRemoved方法,在這個(gè)方法中先判斷event的名字是否為
EVENT_KEY.如果是把event的值
賦予SecurityContext對(duì)象securityContext.然后通過(guò)它取得儲(chǔ)存在它的屬性authentication中的
principal對(duì)象賦予User對(duì)象user.然后調(diào)用
removeUsername方法刪除此對(duì)象.
實(shí)現(xiàn)了HttpSessionAttributeListener的attributeReplaced方法,但是在此方法中沒(méi)有任何代碼.
公共方法contextInitialized(ServletContextEvent sce) 此方法被synchronized關(guān)鍵字修飾,表示此方
法是線程互斥的.在
此方法中,先通過(guò)
輸入?yún)?shù)ServletContextEvent,獲得ServletContext對(duì)象.然后在ServletContext里添加屬性COUNT_KEY,
值為counter的字符串形式表達(dá).
公共方法contextDestroyed,此方法是被synchronized 關(guān)鍵字修飾的,在此方法中給屬性
servletContext,users 賦值null,counter 賦值0.
friend 方法 incrementUserCounter() 此方法也是線程互斥的,它servletContext里把COUNT_KEY取出加
一后再放回。(不寫(xiě)范圍表達(dá)的方法就是friend,范圍是本包和子類)
friend 方法decrementUserCounter 它的作用是把servletContext里的COUNT_KEY減一后再放回,當(dāng)然它
也是線程互斥的。
friend 方法addUsername 此方法的作用是把把用戶添加到servletContext范圍內(nèi)與屬性USERS_KEY對(duì)應(yīng)
的HashMap里。然后調(diào)用incrementUserCounter方法。這個(gè)方法也是線程互斥的。
friend方法removeUsername 此方法的作用是把用戶從servletContext范圍內(nèi)與屬性USER_KEY對(duì)應(yīng)的
HashMap中刪掉。然后調(diào)用decrementUserCounter方法。
org.jsfdemo.webapp.taglib包下是appfuse自定義標(biāo)簽相對(duì)應(yīng)的類.
首先看一下這個(gè)自定義標(biāo)簽的tld文件 appfuse.tld.(這個(gè)文件會(huì)根據(jù)你的項(xiàng)目名而定)
在這個(gè)文件里首先配置了兩個(gè)監(jiān)聽(tīng)類StartupListener 和UserCounterListener.
然后定義了一個(gè)constants的tag.與這個(gè)tag對(duì)應(yīng)的<tag-class>是ConstantsTag,對(duì)應(yīng)的<tei-class>是
ConstantsTei.并且定義了這個(gè)tag有三個(gè)屬性className,scope,var.
其實(shí)這個(gè)標(biāo)簽的作用是把一個(gè)了類放到scope指定的范圍里。
類ConstantsTag繼承了TagSupport類
它有clazz ,scope,var 三個(gè)屬性以及對(duì)應(yīng)的set和get方法,通過(guò)這些可以讓標(biāo)簽的屬性與具體的tag類的
屬性關(guān)聯(lián)起來(lái)。即
此自定義標(biāo)簽的class ,scope 和var屬性與這里的clazz ,scope,var 對(duì)應(yīng)。
getScope(String scopeName) 這個(gè)方法的作用就是通過(guò)從上邊定義的那個(gè)scopes里取與scopeName對(duì)應(yīng)的
值。返回的數(shù)據(jù)
類型是int.
覆蓋了TagSupport的 doStartTag方法,此方法的作用是把class 屬性指定的類中的var指定的屬性保存在
scope所指定的范圍內(nèi)。
如果class 為空class的默認(rèn)值是Constants。scope如果為空默認(rèn)值是PageContext.PAGE_SCOPE,var如果
為空則保存全部聲明的屬性。
然后返回 SKIP_BODY(因?yàn)檫@個(gè)標(biāo)簽沒(méi)有真文,所以不需要和正文發(fā)生交互,也不會(huì)判斷正文,所以返回
SKIP_BODY).
覆蓋了父類的release方法,在此方法中釋放占用資源。個(gè)人認(rèn)為它的這個(gè)方法有誤(appfuse 1.9 jsf
)應(yīng)該是scope = null;而不是
scope = Constants.class.getName();
類ConstantsTei 繼承了TagExtraInfo 覆蓋了getVariableInfo方法。
注: 通過(guò)擴(kuò)展類javax.servlet.jsp.TagExtraInfo定義tag extra info類。一個(gè)TagExtraInfo必須實(shí)
現(xiàn)getVariableInfo方法以返回包含下列信息的VariableInfo對(duì)象數(shù)組:
變量名 ,變量類 ,變量是否引用新對(duì)象 , 變量可用性 。
Web容器向getVariableInfo方法傳遞包含每一個(gè)標(biāo)簽屬性的屬性-值元組的名為data的參數(shù)。這些屬性
可以用于為VariableInfo對(duì)象提供腳本變量名和類。
所以這個(gè)類是與腳本變量有關(guān)的。這個(gè)方法的作用是把class指定的類的var屬性,作為一個(gè)腳本變量返回
。如果var為空,就對(duì)全部變量進(jìn)行處理。
返回的腳本變量的類型為String. 變量可以引用新對(duì)象,變量可用的范圍是VariableInfo.AT_END(在結(jié)束
標(biāo)簽之后直到頁(yè)面的結(jié)束 ).
org.appfuse.webapp.util
此包下是一些在web開(kāi)發(fā)過(guò)程中用到的實(shí)用類。
FacesUtils 類,這個(gè)類的所有方法都是靜態(tài)的。
getServletContext() 通過(guò)Facescontext對(duì)象獲得servletContext對(duì)象。
getJsfEl(String value) 這個(gè) 方法的作用是 返回 "#{" + value + "}";
Application getApplication()
這個(gè)方法通過(guò) FactoryFinder 獲取application對(duì)象。
FactoryFinder提供了查找在jsf API中定義的所有factory對(duì)象的算法。如果在 system 中有一個(gè)屬性與
想要查找的factory同名,它的值就做為你想要查找的factory返回.在system 中沒(méi)有找到,如果在你的
web 應(yīng)用的資源路徑里找faces.properties文件。如果文件中包含與所要查找對(duì)象同名的屬性,這個(gè)屬性
就做為這個(gè)factory執(zhí)行類的名字。最后如果存在META-INF/services/{factory-class-name}資源文件(比
如在lib包里的jar文件中)。讀此文件的第一行做為factory實(shí)現(xiàn)類的名字。
factory Name有這么幾種
APPLICATION_FACTORY------與ApplicationFactory對(duì)應(yīng)的屬性名.
FACES_CONTEXT_FACTORY----FacesContextFactory對(duì)應(yīng)的屬性名.
LIFECYCLE_FACTORY--------LifecycleFactory對(duì)應(yīng)的屬性名.
RENDER_KIT_FACTORY-------RenderKitFactory對(duì)應(yīng)的屬性名.
TREE_FACTORY-------------TreeFactory對(duì)應(yīng)的屬性名.
在這里通過(guò)FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY)獲得ApplicationFactory
對(duì)象.然后再通過(guò)它獲得Application對(duì)象.
getValueBinding(String el) 這個(gè)方法如下:
return getApplication().createValueBinding(el);
這個(gè)類是根據(jù)輸入的對(duì)象名創(chuàng)建一個(gè)ValueBinding對(duì)象.比如在jsf的配置文件里定義了一個(gè)managed bean
"userBean",通過(guò)以下方式getValueBinding("#{userBean}")就創(chuàng)建了一個(gè)ValueBinding對(duì)象,通過(guò)此對(duì)象
可以獲得userBean實(shí)例.
getELValue(String el)這個(gè)方法如下:
getValueBinding(el).getValue(FacesContext.getCurrentInstance());
此方法就是獲得與el相對(duì)應(yīng)的實(shí)例.
getManagedBean(String beanName) 此方法代碼大體如下:
getValueBinding(getJsfEl(beanName)).getValue( FacesContext.getCurrentInstance());
:)就是通過(guò)前面定義的一系列方法獲得與beanName對(duì)應(yīng)的 Managed bean實(shí)例.
resetManagedBean 這個(gè)方法的作用是刪除與beanName對(duì)應(yīng)的Managed bean.具體如下:
getValueBinding(getJsfEl(beanName)).setValue(FacesContext.getCurrentInstance(),null);
setManagedBeanInSession(String beanName,Object managedBean)這個(gè)方法的作用是
把managedBean 放到session范圍內(nèi)的屬性beanName里。
getRequestParameter(String name) 從 request范圍取得與parameter對(duì)應(yīng)的參數(shù)。
addInfoMessage(String clientId,String msg)給一個(gè)特定的客戶(由clientId指定)添加一條jsf消息,
消息的安全程度是FacesMessage.SEVERITY_INFO.
addInfoMessage(String msg) 這個(gè)方法就是添加一條jsf消息。如下:
addInfoMessage(null, msg);
addErrorMessage(String clientId, String msg)和 addErrorMessage(String msg)與前邊類似分別是給
特定客戶添加一條錯(cuò)誤消息和添加一條錯(cuò)誤消息。
evalInt(String el)
這個(gè)方法是判斷參數(shù)el是不是某個(gè)對(duì)象的 jsf 表達(dá),
如果是,通過(guò)el構(gòu)建ValueBinding對(duì)象,進(jìn)而獲得此el對(duì)應(yīng)的對(duì)象.如果是Integer 直接返回,否則把它轉(zhuǎn)換
成Integer返回
否則 返回Integer(el);
還有 getRequest(),getResponse(),getSession()方法.
RequestUtil 類的所有方法也是靜態(tài)的。
setCookie(HttpServletResponse response, String name, String value, String path)
這個(gè)是用來(lái)發(fā)送cookie的。以參數(shù)name 和value構(gòu)建一個(gè)cookie,它是非安全的,路徑設(shè)為path.生命期為30天。然后添加到response里。
getCookie(HttpServletRequest request, String name) 根據(jù)name 從參數(shù)request里找到相應(yīng)的cookie.
deleteCookie(HttpServletResponse response, Cookie cookie, String path)
通過(guò)把生命周期設(shè)為0的方式刪除一個(gè)cookie.
getAppURL(HttpServletRequest request)
這個(gè)方法是通過(guò)request來(lái)獲得應(yīng)用的URL.
posted on 2007-07-12 10:43
冰封的愛(ài) 閱讀(1170)
評(píng)論(0) 編輯 收藏 所屬分類:
J2EE