?? FCKeditor,作為現(xiàn)在功能最強大的在線HTML編輯器,網(wǎng)上關(guān)于他的功能介紹以及基本配置已經(jīng)很多了。然而其中不少文章涉及面都比較局限。最近,筆者需要在自己項目中使用到FCKeditor,并用之于和已有的基于JSF的web應(yīng)用整合。從對FCKeditor一竅不通到成功達成整合,我從網(wǎng)上學(xué)到了不少知識,自己也積累了不少經(jīng)驗,因此,也想和大家一起分析這一過程。
??
1.基本配置:
????? 知之為知之,不知google之。關(guān)于FCKeditor的基本配置在網(wǎng)上自有高人指點,這里我也不多耽誤大家時間。主要是談下自己當(dāng)初配置的問題:
??? a.基本路徑:
??????? 注意FCKeditor的基本路徑應(yīng)該是/(你的web應(yīng)用名稱)/(放置FCKeditor文件的文件夾名)/
??????? 我的目錄結(jié)構(gòu)為:
???????

??????? 因此,我的基本路徑設(shè)置為:/fck/FCKeditor/
???? b.文件瀏覽以及上傳路徑設(shè)置:
??????? 我個人的參考如下:
??????
FCKConfig.LinkBrowser?=?true?;
FCKConfig.LinkBrowserURL?=?FCKConfig.BasePath?+?'filemanager/browser/default/browser.html?Connector=connectors/jsp/connector'?;
FCKConfig.LinkBrowserWindowWidth????=?FCKConfig.ScreenWidth?*?0.7?;????????//?70%
FCKConfig.LinkBrowserWindowHeight????=?FCKConfig.ScreenHeight?*?0.7?;????//?70%

FCKConfig.ImageBrowser?=?true?;
FCKConfig.ImageBrowserURL?=?FCKConfig.BasePath?+?'filemanager/browser/default/browser.html?Type=Image&Connector=connectors/jsp/connector';
FCKConfig.ImageBrowserWindowWidth??=?FCKConfig.ScreenWidth?*?0.7?;????//?70%?;
FCKConfig.ImageBrowserWindowHeight?=?FCKConfig.ScreenHeight?*?0.7?;????//?70%?;

FCKConfig.FlashBrowser?=?true?;
FCKConfig.FlashBrowserURL?=?FCKConfig.BasePath?+?'filemanager/browser/default/browser.html?Type=Flash&Connector=connectors/jsp/connector'?;
FCKConfig.FlashBrowserWindowWidth??=?FCKConfig.ScreenWidth?*?0.7?;????//70%?;
FCKConfig.FlashBrowserWindowHeight?=?FCKConfig.ScreenHeight?*?0.7?;????//70%?;

FCKConfig.LinkUpload?=?true?;
FCKConfig.LinkUploadURL?=?FCKConfig.BasePath?+?'filemanager/upload/simpleuploader?Type=File'?;
FCKConfig.LinkUploadAllowedExtensions????=?""?;????????????//?empty?for?all
FCKConfig.LinkUploadDeniedExtensions????=?".(php|php3|php5|phtml|asp|aspx|ascx|jsp|cfm|cfc|pl|bat|exe|dll|reg|cgi)$"?;????//?empty?for?no?one

FCKConfig.ImageUpload?=?true?;
FCKConfig.ImageUploadURL?=FCKConfig.BasePath?+?'filemanager/upload/simpleuploader?Type=Image'?;
FCKConfig.ImageUploadAllowedExtensions????=?".(jpg|gif|jpeg|png)$"?;????????//?empty?for?all
FCKConfig.ImageUploadDeniedExtensions????=?""?;????????????????????????????//?empty?for?no?one

FCKConfig.FlashUpload?=?true?;
FCKConfig.FlashUploadURL?=?FCKConfig.BasePath?+?'filemanager/upload/simpleuploader?Type=Flash'?;
FCKConfig.FlashUploadAllowedExtensions????=?".(swf|fla)$"?;????????//?empty?for?all
FCKConfig.FlashUploadDeniedExtensions????=?""?;????????????????????//?empty?for?no?one 2.與JSF整合。
? FCKeditor與JSF整合的最大問題,在于需要從JSF環(huán)境中相應(yīng)Bean讀取值賦予給FCKeditor,同時從FCKeditor里面讀取結(jié)果賦予給相應(yīng)的數(shù)據(jù)持有Bean。由于這一過程在傳統(tǒng)的JSF標(biāo)簽中是通過值綁定有框架自動完成,因此這里需要我們手動來實現(xiàn)這一過程。
? 以下要展示的demo由兩部分組成:
?? form.jsp顯示編輯內(nèi)容,點擊其submit按鈕跳轉(zhuǎn)至test.jsp,test.jsp調(diào)用FCKeditor對form.jsp中顯示的已有內(nèi)容進行顯示和編輯。編輯完后點擊submit,頁面將重新跳轉(zhuǎn)到form.jsp,顯示修改后的內(nèi)容。
? 其實,這就是一個很基本的編輯功能,在論壇和blog中都可以看到它的身影。
?? 而ContextBean用于持有待編輯的內(nèi)容,它的scope是session范圍。ContextServlet用于讀取FCKeditor修改后的內(nèi)容,并賦予ContextBean中。
??? 首先來看form.jsp
<body>??
????????<f:view>
????????????<h:form>
????????????????<pre>
????????????????<h:outputText?value="#{td.name}"?escape="false"></h:outputText>
????????????????</pre>
????????????????????????????????<br/>
????????????????<h:commandButton?value="submit"?action="#{td.submit}"></h:commandButton>
????????????</h:form>
????????</f:view>
????</body>??? 這個頁面很簡單,其中td對應(yīng)的就是ContextBean,ContextBean.name用于保存編輯內(nèi)容
package?com.dyerac;


public?class?ContextBean?
{
????private?String?name;


????public?String?getName()?
{
????????return?name;
????}


????public?void?setName(String?name)?
{
????????this.name?=?name;
????}


????public?String?submit()?
{
????????
????????return?"edit";
????}
}下面來看test.jsp
?用過FCKeditor的都知道,F(xiàn)CKeditor可以通過三種方式來調(diào)用:
?script, jsp 標(biāo)簽以及java代碼。
這里,為了方便從ContextBean中讀取name屬性內(nèi)容作為其初始值,我使用了第三種方法
其中
FCKeditor?fck=new?FCKeditor(request,"EditorDefault");初始化FCKeditor,第二個參數(shù)即為該FCKeditor實例的id,當(dāng)提交后FCKeditor內(nèi)的內(nèi)容將以該參數(shù)為變量名保存在request中。
比如,這里我選擇了
EditorDefault,所以日后讀取FCKeditor內(nèi)容時,可以通過以下語句:
request.getParameter("EditorDefault")
<body>
????????<form?action="/fck/servlet/ContextServlet"?method="post"?target="_blank">
????????<%FCKeditor?fck=new?FCKeditor(request,"EditorDefault");
??????????FacesContext?fcg=FacesContext.getCurrentInstance();
??????????ContextBean?td=(ContextBean)fcg.getApplication().getVariableResolver().resolveVariable(fcg,"td");
??????????fck.setBasePath("/fck/FCKeditor/");
??????????fck.setValue(td.getName());
??????????fck.setHeight(new?Integer(600).toString());
??????????out.print(fck.create());
?????????%>
?????????<input?type="submit"?value="Submit">
????</body>?修改后的結(jié)果以post方式提交給/fck/servlet/ContextServlet,該url對應(yīng)的即為ContextServlet。
ContextServlet負責(zé)讀取FCKeditor里的內(nèi)容,并賦予給session中的ContextBean。doPost()方法用于實現(xiàn)該功能
public?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)

????????????throws?ServletException,?IOException?
{
????????FacesContext?fcg?=?getFacesContext(request,response);
????????ContextBean?td?=?(ContextBean)?fcg.getApplication()
????????????????.getVariableResolver().resolveVariable(fcg,?"td");
????????String?name=new?String(request.getParameter("EditorDefault").getBytes("ISO-8859-1"),"UTF-8");
????????td.setName(name);
????????RequestDispatcher?rd=getServletContext().getRequestDispatcher("/form.faces");
????????rd.forward(request,?response);
????}需要注意兩個問題,
其一:FCKeditor內(nèi)的中文信息讀取是可能出現(xiàn)亂碼,需要額外的處理:
?? String?name=new?String(request.getParameter("EditorDefault").getBytes("ISO-8859-1"),"UTF-8");
其二:由于servlet處于FacesContext范圍外,因此不能通過FacesContext.getCurrentInstance()來得到當(dāng)前FacesContext,因此ContextServlet定義了自己的方法用于獲取FacesContext:
//?????You?need?an?inner?class?to?be?able?to?call?FacesContext.setCurrentInstance
//?????since?it's?a?protected?method
????private?abstract?static?class?InnerFacesContext?extends?FacesContext

????
{

??????protected?static?void?setFacesContextAsCurrentInstance(FacesContext?facesContext)?
{
????????FacesContext.setCurrentInstance(facesContext);
??????}
????}


????private?FacesContext?getFacesContext(ServletRequest?request,?ServletResponse?response)?
{
??????//?Try?to?get?it?first
??????FacesContext?facesContext?=?FacesContext.getCurrentInstance();
??????if?(facesContext?!=?null)?return?facesContext;

??????FacesContextFactory?contextFactory?=?(FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
??????LifecycleFactory?lifecycleFactory?=?(LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
??????Lifecycle?lifecycle?=?lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);

??????//?Either?set?a?private?member?servletContext?=?filterConfig.getServletContext();
??????//?in?you?filter?init()?method?or?set?it?here?like?this:
??????//?ServletContext?servletContext?=?((HttpServletRequest)request).getSession().getServletContext();
??????//?Note?that?the?above?line?would?fail?if?you?are?using?any?other?protocol?than?http
??????ServletContext?servletContext?=?((HttpServletRequest)request).getSession().getServletContext();

??????//?Doesn't?set?this?instance?as?the?current?instance?of?FacesContext.getCurrentInstance
??????facesContext?=?contextFactory.getFacesContext(servletContext,?request,?response,?lifecycle);

??????//?Set?using?our?inner?class
??????InnerFacesContext.setFacesContextAsCurrentInstance(facesContext);

??????//?set?a?new?viewRoot,?otherwise?context.getViewRoot?returns?null
??????//UIViewRoot?view?=?facesContext.getApplication().getViewHandler().createView(facesContext,?"yourOwnID");
??????//facesContext.setViewRoot(view);

??????return?facesContext;
????}??? ContextServlet處理完了FCKeditor內(nèi)容后,將跳轉(zhuǎn)到form.jsp。
這樣一個簡單的編輯功能就完成了。
3.遺留問題:
?? 我在上傳文件時還是會出現(xiàn)中文亂碼的問題,按照其他人說的那樣把網(wǎng)頁的charset=utf-8改成gb2312一樣會有問題,還請各位高手賜教^_^
另外,關(guān)于整個demo的源代碼如果大家需要,可以留言給我,我用郵箱發(fā)給您。不足之處,還請各位多多指點