日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Liferay开发学习(1)

發(fā)布時間:2023/12/8 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Liferay开发学习(1) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Liferay 6.1開發(fā)學(xué)習(xí)(一):環(huán)境搭建

一、資源準(zhǔn)備

以下資源內(nèi)容可以在Liferay的官方網(wǎng)站下載,1-3在http://www.liferay.com/downloads/liferay-portal/available-releases下載,Liferay IDE在http://www.liferay.com/downloads/liferay-projects/liferay-ide處下載。

  • liferay-plugins-sdk-6.1.1(Plugins SDK)
  • liferay-portal-6.1.1-ce-ga2(Bundled with Tomcat)
  • liferay-portal-src-6.1.1-ce-ga2(Portal Source,可選)
  • liferay IDE 1.6
  • Java SDK(開發(fā)Java程序當(dāng)然要安裝,請配置好環(huán)境變量)
  • 請將以上資源解壓,推薦在某一個盤下面建立一個Liferay的目錄,將IDE、SDK、Liferay-portal-6.1.1-ce-ga2和源碼后解壓后放到這個目錄下面。

    二、配置SDK

    打開Liferay IDE,Window-->Preferences-->Liferay-->Installed Plugin SDK,點擊右邊的Add…按鈕,選擇Liferay plugins SDK的解壓目錄,如下圖所示,點擊OK,完成SDK的配置。

    三、配置Liferay運行環(huán)境(以Tomcat為例)

    打開Liferay IDE,Window-->Preferences-->Server-->Runtime Environment,點擊右邊Add…,在彈出的服務(wù)器選擇里面選擇Liferay,Inc-->Liferay v6.1 CE (Tomcat 7),請在“Create a new location server”打上勾。

    點擊Next,選擇liferay-portal-6.1.1-ce-ga2的解壓目錄,如下圖:

    點擊Finish完成Tomcat的配置;或者點擊“Next”,此步驟可以在Liferay source location處選擇Liferay的源碼,或者跳過,推薦關(guān)聯(lián)一下Liferay的源碼,其他的兩個可選,點擊Finish完成Tomca的配置。

    四、運行Liferay

    經(jīng)過上面的三步,在Liferay IDE(Eclipse 4.2)的下方的server面板處,可以看到Liferay 6.1 CE Server,現(xiàn)在點擊運行。稍等片刻,待Tomcat啟動完成后,打開瀏覽器輸入http://localhost:8080/,在Liferay第一次運行的時候會出現(xiàn)一個配置向?qū)?#xff08;此功能為Liferay 6.1開始新增)。

    可以在此配置Liferay門戶名稱、使用語言、管理員的姓名、電子郵件,數(shù)據(jù)庫的連接信息(先在數(shù)據(jù)庫里面建立數(shù)據(jù)庫lportal)等內(nèi)容。如上圖所示,如果出現(xiàn)“數(shù)據(jù)庫連接不能建立。請檢查您的連接設(shè)置。”請檢查數(shù)據(jù)庫是否已經(jīng)建立,或者數(shù)據(jù)庫名、帳號、密碼等信息是否正確。

    靜心等待Liferay的初始化,可能需要幾分鐘時間,當(dāng)Liferay初始化完成后,會自動跳轉(zhuǎn)到配置保存成功的頁面。

    根據(jù)Liferay的提示進(jìn)行密碼設(shè)置、密碼提示問題設(shè)置等,然后跳轉(zhuǎn)到Liferay的主頁。

    五、Liferay IDE的其他配置

    設(shè)置工作區(qū)編碼

    Liferay的開發(fā)環(huán)境我們需要工程的編碼為UTF-8,新安裝的Eclipse的默認(rèn)編碼為GBK,修改方式為WindowàPreferencesàGeneralàWorkspace,在這下面的Text file encoding處選擇other,UTF-8。點擊OK保存。

    代碼提示、控制臺緩沖區(qū)的大小

    可以參考前面的一篇博客:MyEclipse/Eclipse的一些技巧

    中文字體偏小

    可以參考之前一篇博客:解決eclipse3.7中文字體小

    六、Liferay的大概使用介紹

    在四的基礎(chǔ)上,在右上角可以看到有一個訪問,點擊可以看到有控制面板、我的公共主頁、我的個人主頁、Liferay(這里顯示的是在配置向?qū)幵O(shè)置的門戶名稱)。這幾個內(nèi)容是什么意思呢?

    控制面板:這個算是liferay的后臺管理。

    我的公共主頁:其他人可以看到的自己的頁面內(nèi)容,一般放置的如個人博客等展示給其他人看的內(nèi)容。

    我的個人主頁:個人主頁的東西是只有自己可以看到,其他人看不到的,一般放置自己的日程,收集的站點,常用的小工具等等內(nèi)容,是自己的私有空間。

    在控制面板里面主要分為個人信息、站點設(shè)置、門戶設(shè)置、服務(wù)器信息等。如果是一般權(quán)限的用戶只能看到個人信息。一般開發(fā)的管理功能的頁面均放置在此控制面板處,后面介紹如何將自己開發(fā)的Portlet,放置在這里。

    現(xiàn)在回到“我的公共頁面”或者“我的個人主頁”。依次介紹一下頂部左邊各按鈕的作用。

    編輯控制:打上勾之后顯示portlet的控制按鈕,可以勾上和反選看一下效果。如果勾上仍然沒有出現(xiàn)portlet的控制按鈕,而說明當(dāng)前登錄的用戶沒有此portlet的控制權(quán)限。

    管理:管理里面有頁面、頁面布局、站點頁面、站點內(nèi)容四個菜單。頁面和站點頁點功能類似,差別只在于點進(jìn)去后的默認(rèn)位置不同;站點內(nèi)容和后臺的控制面板處站點的內(nèi)容一樣。頁面布局是調(diào)整當(dāng)前頁面使用什么樣的布局,如一欄,兩欄,三欄等這些內(nèi)容。

    添加:點擊添加顯示的是可以添加的portlet,默認(rèn)的只有幾個,點擊更多,可以看到所有的有權(quán)限的portlet(不同的登錄用戶,根據(jù)權(quán)限的不同看到的portlet不同)。可以添加一些看看效果。

    上頁內(nèi)容只是Liferay的一些大概介紹,不熟悉的可以隨便點點,熟悉一下相關(guān)內(nèi)容。

    七、其他

    1、可以嘗試修改一個Liferay里面的eclipse.ini的里面的JVM內(nèi)存配置,可以提高eclipse的響應(yīng),我將里面的-Xms和-Xmx均調(diào)到了768M。

    2、可以修改一下Eclipse的代碼提示等,參看http://www.huqiwen.com/2012/06/25/some-skill-about-myeclipse-eclipse/

    3、Liferay的學(xué)習(xí)可以多看看Liferay官方網(wǎng)站的文檔和WIKI,雖然質(zhì)量不是很可,但也可以學(xué)到不少內(nèi)容。

    http://www.liferay.com/documentation/liferay-portal/6.1/development

    http://www.liferay.com/community/wiki

    Liferay 6.1開發(fā)學(xué)習(xí)(二):創(chuàng)建一個Portlet工程

    使用Liferay的SDK創(chuàng)建一個簡單的Portlet,此Portlet不包括業(yè)務(wù)邏輯、不包括數(shù)據(jù)庫,只有簡單的頁面展現(xiàn),用以說明Portlet的開發(fā)過程。

    一、創(chuàng)建Portlet工程

    1、打開Liferay IDE,File-->New-->Liferay Project

    2、為Portlet工程取名為Study,點擊完成。或者點擊下一步,默認(rèn)選擇Liferay MVC。

    補(bǔ)充說明:

    Portlet:這個是一般做Liferay開發(fā)選擇的項目,一般說Liferay插件工程,通常都是指的Portlet工程。他的結(jié)構(gòu)和內(nèi)容和普通的WEB工程區(qū)別不大。

    Hook:Liferay的Hook是什么東西呢?這個單詞中文可以翻譯成鉤子。是用于重寫或覆蓋Liferay的一些默認(rèn)方法或頁面。為開發(fā)提供了一種在不直修改Liferay核心源碼的情況下修改Liferay核心功能的方法。

    Ext:擴(kuò)展工程的開發(fā)方法是Liferay早期版本推薦的開發(fā)方法,在6.x版本之后對ext開發(fā)模式逐漸不再推薦,主要使用Portlet的開發(fā)方法。擴(kuò)展開發(fā)可以繼承Liferay的Portal的大部分接口方法,而Portlet里面可以使用的接口方法均是Services包里面暴露的API。但是和Liferay的核心工程耦合太大,當(dāng)Liferay的版本升級時對Ext工程的影響太大,基本需要重新修改。所以一般不推薦使用Ext模式。

    Layout:布局模板,Liferay的布局是可以定制的,如一個頁面中是兩欄式還是三欄式,每個欄里面又有幾行等等,可以使用此模式進(jìn)行快速開發(fā)。

    Theme:主題包。Liferay IDE提供的可以幫助開發(fā)人員、設(shè)計人員快速開發(fā)Liferay主題包的功能,通過此模式提供的向?qū)Чぞ叩?#xff0c;為主題包的開發(fā)大大的提供了便利。

    Portlet部署

    Liferay的開發(fā)大量依賴Ant(也可以使用maven),在Liferay的開過程中,編譯、代碼生成、打包、部署等都是基于Ant完成的。

    1、Liferay 的IDE在Liferay的portlet開發(fā)模式下,ant面板默認(rèn)是可見的,如果找不到可以通過Window-->Show View-->Ant(如果沒有可以在other里面找到)

    2、在ant頁板里面,點擊Add-buildfiles將Build.xml文件添加進(jìn)來。

    3、點擊Study-portlet前面的小三角,在出現(xiàn)的下拉菜單里面,雙擊deploy,等待Liferay完成部署操作。

    如果在此時出現(xiàn)如下錯誤:

    Task cannot continue because ECJ is not installed.

    ECJ was automatically installed. Please rerun your task.

    原因是ECJ包沒有找到,ECJ是什么?ECJ, the Eclipse Compiler for Java, is an open source incremental compiler used by the Eclipse JDT. It is an option for Liferay builds and is in many cases faster than Javac or Jikes. The jar for ECJ is included in Liferay release 4.4.0 and later.http://www.liferay.com/community/wiki/-/wiki/Main/ECJ這是官方解釋。大概意思是ECJ是一個編譯優(yōu)化包,可以提升比Javac和JIKES更好的編譯速度。要想使編譯通過,有兩個兩個方法:

    方法一:禁用ECJ。在Liferay的SDK下面找到build.Administrator.properties,此處中間的Administrator名稱不一定是這樣的,具體體系名稱是根據(jù)當(dāng)前系統(tǒng)的用戶名生成的。在里面添加如下內(nèi)容

    javac.compiler=modern
    #javac.compiler=org.eclipse.jdt.core.JDTCompilerAdapter

    方法二:將ECJ的包添加到ant的路徑里面。ecj.jar包可以在Liferay的工程的源碼包\lib\development下面找到。將此包添加到ant的路徑里面。Windows-->preferences-->Ant-->Runtime,在右邊的Classpath-->Ant Home Entries(Default) -->Add External JARs,將ecj包添加進(jìn)來。

    4、啟動Tomcat。此portlet工程會自動部署。

    5、打開http://localhost:8080/,登錄系統(tǒng)。點擊左上角的添加-->更多-->示例,在這里面可以看到我們剛建立的study portlet,點擊添加,可以將此portlet添加到頁面上。

    Portlet工程結(jié)構(gòu)

    一個Portlet工程的大概結(jié)構(gòu)如下:

    1、src:這里存儲Java相關(guān)文件包,后面會看到還有一個services包。

    2、web.xml:此web.xml和普通的web工程的web.xml文件一樣。

    3、build.xml,此文件為ant的構(gòu)建文件,一般不需要修改繼承自SDK。

    4、Liferay-plugin-package.properties,此文件為包工程的元數(shù)據(jù)信息文件,一般開發(fā)不需要關(guān)注。

    5、portlet.xml:portlet定義描述文件,這個文件是標(biāo)準(zhǔn)的portlet 2.0(JSR 268)規(guī)范的文件。在這里定義的信息為portlet的名稱、初始化參數(shù)、模式類型、portlet的相關(guān)信息、權(quán)限等。在此文件里面我們可以看到view-template對應(yīng)的的是/view.jsp,當(dāng)我們在Liferay里面添加此portlet后,看到的頁面內(nèi)容就是view.jsp里面的內(nèi)容。下面的security-rol-ref定義的是哪些角色擁有此portlet的權(quán)限。

    6、Liferay-portlet.xml:此文件是liferay擴(kuò)展的portlet的內(nèi)容,portlet.xml文件里面是標(biāo)準(zhǔn)的Portlet內(nèi)容,所有的Portal容器的portlet.xml文件描述、結(jié)構(gòu)都是一樣的。但liferay基于自身平臺的需求,又添加了一個Liferay-portlet.xml來擴(kuò)展portlet的信息。在這里可以看到角色映射,以及Liferay的一些個性化信息,后面有需要的時候詳細(xì)說明。

    7、liferay-display.xml:在上一個步驟里面我們在添加portlet的時候,看到study這個portlet是位于示例這個目錄下面的,此文件就是定義相關(guān)的portlet是放置在哪個目錄下面顯示的。

    說明:

    在Liferay里面,portlet的名稱一般不要重復(fù),portlet.xml,liferay-portlet.xml,lifray-display.xml這三個文件之間的關(guān)聯(lián)就是通過portlet 名稱做標(biāo)識進(jìn)行關(guān)聯(lián)。


    Liferay 6.1開發(fā)學(xué)習(xí)(三):Portlet簡述

    在上一篇文章里面介紹的那個Portlet是在創(chuàng)建工程時默認(rèn)創(chuàng)建的Portlet頁面,可以對Portlet有一個大概的認(rèn)識,但是很難全面。本篇文章對于Liferay中基于MVC的Portlet創(chuàng)建做一個相對詳細(xì)的描述。

    一、Portlet是什么?

    Portlet是基于java的web組件,由portlet容器管理,并由容器處理請求,生產(chǎn)動態(tài)內(nèi)容。Portals使用portlets作為可插拔用戶接口組件,提供信息系統(tǒng)的表示層。作為利用servlets進(jìn)行web應(yīng)用編程的下一步,portlets實現(xiàn)了web應(yīng)用的模塊化和用戶中心化。 portlet規(guī)范,即jsr(Java Standardization Request )168/268,是為了實現(xiàn)portal和portlet的互操作。它定義了portlet和portlet容器之間的和約,讓portlet實現(xiàn)個性化、表示和安全的api集。規(guī)范還定義了怎樣在portlets應(yīng)用中打包portlets。(引自百度百科:http://baike.baidu.com/view/58961.htm)

    Liferay是portlet規(guī)范的實現(xiàn),對于portlet規(guī)范實現(xiàn)的主流產(chǎn)品還有IBM、Oracle等的Portal產(chǎn)品,主流產(chǎn)品的詳細(xì)可以參看:http://www.huqiwen.com/2012/06/11/what-is-liferay/?此篇文章中關(guān)于Liferay市場地位處的圖片。很以很多時候我們將Liferay稱為一個Portal容器,也就是一個提供Portlet運行的環(huán)境。

    二、創(chuàng)建一個Portlet

    1、基于上一節(jié)的Study這個portlet工程的基礎(chǔ)。點擊Liferay IDE上的liferay工具欄,有三個按鈕,點擊中間按鈕,New Liferay Portlet。如下圖,點擊下一步。

    Portlet plugin project:這里選擇要創(chuàng)建的portlet屬于哪個插件工程。

    Source folder:類的放置位置,一般默認(rèn)。

    Portlet Class:要創(chuàng)建的Portlet的控制類的名稱,可以將此類看作Struts中的Action類。

    Java package:包名。

    Superclass:選擇要繼承哪個類。一般默認(rèn),也就是MVCPortlet。下面這幾個類的關(guān)系如下:MVCPortlet是LiferayPortlet的子類,LiferayPortlet是GenericPortlet的子類。在MVCPortlet中封裝了一些方便開發(fā)的方法,所以一般使用MVCPortlet,如果有特殊需求可以使用他們的父類。

    2、在此步驟看到的是Portlet的相關(guān)信息,如模式,JSP位置等,此步驟是portlet.xml文件的可視化編輯,此步驟的所有選項都可以通過編輯portlet.xml完成。點擊下一步。

    Porltet Info:這里顯示的是Porltet的名稱,顯示名稱,標(biāo)題等。一般默認(rèn),不需要修改。

    Portlet Modes:這里是portlet的模式,View、Edit、Help這三種模式,是portlet規(guī)范里面定義的。

    Liferay Portlet Modes:看名知義,Liferay Portlet模式。一般默認(rèn)即可。Portlet默認(rèn)的三種模式,Liferay認(rèn)為不能滿足實際的需求,所以又新增了這幾種模式。如果選擇多個模式,就可以在portlet的設(shè)置里面看到,可以通過設(shè)置進(jìn)行切換,方便進(jìn)行一些特殊需求,如:config可以用來開發(fā)可配置Porltet,管理員可以為指定的Portlet定制相關(guān)的參數(shù)等。

    JSP folder:JSP的存放位置,一般默認(rèn)的命名是html/porltet名稱,一般默認(rèn)即可。html是相對于docroot的,完整路徑是docroot/html/demo/view.jsp。

    Create resource bundle file:綁定資源文件,主要是國際化。如果想要porltet的名稱是中文的,測必須使用資源文件,liferay推薦工程中的所有文字描述類的內(nèi)容都使用資源文件來定義,這樣方便國際化,也能避免出現(xiàn)一些可能的亂碼問題。這里先不選,后面詳講國際化。

    3、此步驟是Liferay-portlet.xml和liferay-display.xml的可視化編輯。點擊完成即可。

    Icon:此portlet的圖標(biāo)。

    Allow mutiple instaces:是否允許在同一個頁面中有多個porltet的實例,默認(rèn)為否。

    CSS:當(dāng)前porltet的自定義CSS。一般默認(rèn)。

    JavaScript:當(dāng)前portlet自定義JS。一般默認(rèn)。

    CSS classname:當(dāng)前portlet的命名空間,防止CSS和其他porltet沖突。

    Category:當(dāng)前的portlet,顯示在哪個分類下面,這里是Liferay-display.xml文件的可視化編輯。

    三、MVCPortlet的簡單使用

    可以看到在工程的com.huqiwen.study包下面生成了一個Demo的java文件,如果只是讓portlet顯示/html/demo/view.jsp里面的內(nèi)容,則不需要在Demo.java文件里面添加內(nèi)容。如果需要讓view.jsp后從臺初始化一些信息,則需要重寫doView文法。view模式顯示時調(diào)用doView方法,edite模式顯示時調(diào)用doEdite方法,config模式顯示時調(diào)用doConfig方法,依此類推。

    在此大部分情況下可以將renderRequest當(dāng)然HttpServletRequest使用。如果要轉(zhuǎn)換可以通過PortalUtil.getHttpServletResponse(portletResponse)來進(jìn)行轉(zhuǎn)換。

    可以使用renderRequest.setAttribute(arg0, arg1)方法,在前臺頁面通過JSTL等進(jìn)行取值。

    這里不詳述,和普通的WEB程序基本一樣。

    四、其他

    在二里面創(chuàng)建的內(nèi)容都可以通過修改portlet.xml,liferay-portlet.xml,liferay-display.xml等來進(jìn)行修改調(diào)整。創(chuàng)建向?qū)О闹皇且恍┳钔ㄓ玫膬?nèi)容,一些高級的參數(shù)還需要通過修改porltet.xml和liferay-portlet.xml來完成。

    通過向?qū)J(rèn)porltet的view展現(xiàn)的JSP命名為view.jsp。此名稱可以在docroot下面修改成相應(yīng)的內(nèi)容,實際開發(fā)中建議命名中和業(yè)務(wù)相關(guān)的,方便后期查找識別,如用戶的可以命名成userView等,修改名稱的同時需要修改Porltet.xml里面init-param對應(yīng)的名稱,否則會出現(xiàn)找不到頁面的情況。

    Liferay 6.1開發(fā)學(xué)習(xí)(四):Service Builder

    一、什么是Service Builder?

    Service Builder是Liferay IDE(SDK)提供的一種代碼生成方案,開發(fā)人員只需要編輯一個數(shù)據(jù)庫的實體描述文件,即可根據(jù)本XML文件生成Spring層代碼、Hibernate層代碼、SQL、SQL索引創(chuàng)建文件、Spring和hibernate的配置文件等,可以大提高開發(fā)人員的效率。簡單說就是根據(jù)數(shù)據(jù)庫描述文件,生成service層和持久化層的代碼,開發(fā)人員只需要關(guān)注控制層即可。

    二、Service Builder的使用

    1、首先需要有一個Portlet的插件工程,創(chuàng)建方法,參考http://www.huqiwen.com/2012/09/01/liferay-6-1-development-studey-2-create-portlet-project/

    2、打開Liferay IDE,點擊工具欄中Liferay工具的中間按鈕,New Liferay Service Builder,彈出的向?qū)缦?#xff0c;填寫相關(guān)信息,點擊完成。

    Plugin Project:將用于哪個工程,如果有多個工程,請看仔細(xì)。

    Service file:數(shù)據(jù)庫描述文件的文件名,使用向?qū)Р豢筛?#xff08;可以手動改,后面詳述)

    Package path:包名路徑,這里是定義基礎(chǔ)的包名路徑,建議一般規(guī)則為:公司域名+portlet+功能模塊名

    Namespace:命名空間,如果沒有指定數(shù)據(jù)庫的表名,則會在前面添加上此命名空間。

    Author:作者名,默認(rèn)讀取系統(tǒng)變量。

    Include sample entiry in new file:在自動生成的xml文件中是否包含示例,如果是新手,建議打勾。

    3、編輯service.xml文件。在liferay IDE里面提供了service的開視化編輯。簡單介紹一下主要屬性的含義。

    Name:實例名稱,就是通常的JavaBean的名稱。

    Local Service:本地服務(wù),一般選中。

    Remote Service:遠(yuǎn)程服務(wù),用于為生成Web Service做支持,如果不需要不要選中。

    Human Name:人性化名稱。一般留空即可,此處的名字用于生成文檔時使用,如果留空使用Name。

    Table:數(shù)據(jù)庫名稱,如果不填寫,使用Name。

    Uuid:是否生成一個uuid的字段,具體的根據(jù)數(shù)據(jù)庫設(shè)計情況而定。可以使用也可以不使用。推薦使用。

    Uuid accessor:是否使用uuid存取實體,根據(jù)情況而定。可以使用也可以不使用。推薦使用。

    Persistence Class:持久化類的名稱,推薦留空,讓自動生成。

    Data source:數(shù)據(jù)源,一般留空。。

    Session Factory:數(shù)據(jù)庫會話工廠,一般留空。

    TX Manager:事務(wù)管理,一般留空。

    Cache enabled:開啟緩存,推薦選中。

    JSON enabled:開啟JSON,生成的代碼中包含實體的JSON序列化和反序列化,根據(jù)情況而定。如果不使用JSON,請不要勾選。

    4、在Columns里面添加字段,填寫字段名稱,類型等。如果要使用特殊的數(shù)據(jù)庫名稱,或者字段有其他需求,請點開Columns,在下面逐個字段上修改。Db Name對應(yīng)的為數(shù)據(jù)庫的字段名稱,其他一般留空即可。

    5、Order,查詢結(jié)果根據(jù)哪個字段排序列。

    6、Finders:查詢方法。service builder默認(rèn)會生成基本的增刪改查方法,如果有一些根據(jù)字段查詢某些數(shù)據(jù),返回的可以是一個實體也可以是一個List。

    <finder name="userId" return-type="user"><finder-column name="userId" /></finder>

    這個的意思是生成一個方法叫findyByUserId的方法,傳入的參數(shù)是userId,返回的類型是User。(這個例子只是為說明,一般如果userId是主鍵,service builder生成的方法里面,不寫此finder,已經(jīng)包含此方法)

    finder-column這里可以填寫多個參數(shù),return-type,如果是Collection則返回類型是List。

    Finders方法,可以根據(jù)實際情況進(jìn)行填寫,對于使用finders仍不能滿足的方法,后面詳解。

    7、點擊ant里面servicer-builder按鈕,等待Liferay進(jìn)行代碼生成。或者將可視化編輯器切換到Diagram,點擊右鍵,service builder。

    三、Service Builder生成代碼的使用。

    如果是第一次使用Service Builder,請按如下步驟操作。

    1、WEB-INF目錄下面找到service目錄,點擊右鍵Build Path-->Use as Source Folder。service包里面主要包括生成的代碼里面的接口方法,方便我們進(jìn)行跨工程的代碼調(diào)用。src里面都 實現(xiàn)包。

    2、Service Builder的使用,一般有兩種方法。一種是獲取一個Service。

    CmsArticleLocalService cmsArticleServie = CmsArticleLocalServiceUtil.getService();

    然后使用此xxService調(diào)用相關(guān)方法

    一種是直接使用xxLocalServiceUtil調(diào)用相關(guān)方法。大部分情況下使用xxLocalServiceUtil進(jìn)行方法調(diào)用。

    3、創(chuàng)建一個modle實例一般使用如,xxLocalServiceUtil.createXX()方法。

    四、自定義方法

    雖然liferay自動生成的代碼里面包含了常用方法,足以應(yīng)付一般場景,但是有些特殊場景需要一些特殊的方法,如何添加自定義方法呢?

    1、找到src下面和此service builder相關(guān)的的xxx.service.impl包,找到xxxLocalServiceImpl的文件,打開在此類里添加相關(guān)的自定義方法。

    2、如果是要為modle添加自定義方法,請在xxx.modle.impl包里面的,xxImpl文件里面添加自定義方法。

    3、修改完成后,再次執(zhí)行Service Builder,會將這些方法自動的添加到其他相關(guān)接口、類里面。Liferay的Service Builder方法一般只允許修改上述兩個類,其他的類一般不要修改,因為修改后如果再次執(zhí)行service builder會被覆蓋掉。

    五、修改字段長度

    Liferay自動生成的代,如String字段,默認(rèn)長度是75。如果有特殊的需求,可以在src/META-INF/portlet-model-hints.xml里面修改相應(yīng)的字段映射長度。找到相應(yīng)的實體,字段,如下:

    <field name="InfoId" type="String" ><hint name="max-length">300</hint></field>

    這樣就可以將InfoId的數(shù)據(jù)庫字段長度定義為300。修改完成重新執(zhí)行service-builder進(jìn)行文件生成。

    六、其他技巧

    1、一個service.xml文件里面可以有多個實體名。

    2、如果要建立多個service.xml文件,可以在WEB-IN目錄下面建立一個文件夾,比如叫service-builder用來存儲service.xml文件,不同的service.xml執(zhí)行不同的命名,如User-Service.xml等。手動建立,不必使用向?qū)А?/p>

    3、如果按照步驟2操作,有多個service.xml文件,則不能執(zhí)行ant里面的service-builder文件,因為ant只會尋找web-inf目錄下面的services.xml文件。所以要在xx-service.xml文件里面切換到Diagram編輯模式,點擊右鍵,build Service,這樣會對當(dāng)前XML文件進(jìn)行構(gòu)建。

    4、即使使用了2、3的方法,也不要刪除web-inf目錄下面的service.xml文件,可以保留一份,不然最終部署后的web.xml描述文件里會少生成一些內(nèi)容,導(dǎo)致插件工程不能正常運行。

    5、同一個插件工程中,不同的xx-services.xml文件必須使用不同的包名,一個services.xml里面可以有多個實體,但不同的services.xml里面必須使用不同的包名,否則會導(dǎo)致生成的的spring配置文件出現(xiàn)覆蓋情況。

    Liferay 6.1開發(fā)學(xué)習(xí)(五):編譯調(diào)試修改源碼

    Liferay是一個開源的項目,開源項目的好處有兩個,一方面我們可以通過閱讀源碼提高水平,了解一些技術(shù)的實現(xiàn)原理,另一方面是如果開源的產(chǎn)品不能滿足我們的實際需求,可以通過修改源碼實現(xiàn)。Liferay CE版可以免費獲取源碼,EE版需要購買過產(chǎn)品才能獲取源碼。

    以下文件雖然是基于Liferay 6.1.1所寫,但Liferay 6.2.0版本同樣適用,方法、過程、需要注意事項等均一致

    一、導(dǎo)入源碼

    源碼可以從Liferay的官方網(wǎng)站上下載。http://www.liferay.com/downloads/liferay-portal/available-releases

    下載后解壓源碼,可以使用Eclipse的File-->Import-->General-->Existing Projects in to Workspace。將解壓的源碼導(dǎo)入到Eclipse中。

    導(dǎo)入源碼后,如果是6.1.1的源碼,可能會出現(xiàn)如下的錯誤:Project 'portal-trunk' is missing required source folder: 'portal-web/test'。此錯誤是說在build path下面找不到test目錄。解決方法有兩個(6.2.0中導(dǎo)入源碼后,也有類似問題,解決方法同下面兩個原理一樣):

    1、在portal-web下面建立一個名為test的目錄。

    2、打開源碼工程目錄下面的.classpath文件(使用文本編輯器打開,editplus或notepad++),在其中找到<classpathentry excluding="**/.svn/**|.svn/" kind="src" path="portal-web/test"/>(大概在11行),將此行注釋掉或刪除。然后回到Eclipse中刷新工程(選中工程按F5,或在右鍵菜單中選擇刷新)。

    二、編譯源碼

    既然要調(diào)試源碼,首先是需要能夠?qū)υ创a進(jìn)行編譯。Liferay的源碼不是一個普通的Web工程,不能使用普通的方法進(jìn)行編譯部署。但liferay官方已經(jīng)提供了相應(yīng)的ant腳本進(jìn)行編譯部署,但首先還需要一些簡單的設(shè)置。

    1、打開liferay的源碼目錄,找到app.server.properties文件。

    2、將些文件復(fù)制一份,重命名為app.server.{username}.properties的文件,其中的{username}為當(dāng)前系統(tǒng)的帳號名稱。如我的系統(tǒng)帳號是huqiwen,則將其命名為app.server.huqiwen.properties即可。具體的可以打開CMD,以里面顯示用戶名為準(zhǔn)。如下圖:

    3、打開此文件,找到app.server.parent.dir=${project.dir}/../bundles。將后面的${project.dir}/../bundles替換為下載的綁定Liferay的Tomcat的路徑,如我的為E:/code/liferay6.1/liferay-portal-6.1.1-ce-ga2,則修改后的地址為:?app.server.parent.dir=E:/code/liferay6.1/liferay-portal-6.1.1-ce-ga2。注意:從地址欄里面復(fù)制的地址為正斜杠,請修改成反斜杠。

    4、現(xiàn)在Eclipse的ant面板里面點擊,add buildfiles,將portal源碼里面的build.xml文件添加到ant面板里面。

    5、點開此build文件,先點擊compile,再點擊deploy,即可將源碼編譯部署到tomcat中。

    三、debug源碼

    在二的基礎(chǔ)上deploy后,即可對liferay的相關(guān)源碼進(jìn)行編譯調(diào)試。如果是第一次進(jìn)行debug,可能會跳轉(zhuǎn)到顯示Source not found,此時,點擊下面的“edit source lookup path”,在彈出的對話框里面點擊Add -->Java Project,在這里將我們的Portal-trunk工程勾選上,點擊OK等,即可開始Liferay的源碼調(diào)試。

    四、常見問題

    1、在編譯的時候出現(xiàn)如下錯誤

    Task cannot continue because ECJ is not installed.

    ECJ was automatically installed. Please rerun your task.

    這個問題在前面的博客里面提到過,http://www.huqiwen.com/2012/09/01/liferay-6-1-development-study-2-create-portlet-project/

    解決方法為:

    原因是ECJ包沒有找到,ECJ是什么?ECJ, the Eclipse Compiler for Java, is an open source incremental compiler used by the Eclipse JDT. It is an option for Liferay builds and is in many cases faster than Javac or Jikes. The jar for ECJ is included in Liferay release 4.4.0 and later.http://www.liferay.com/community/wiki/-/wiki/Main/ECJ這是官方解釋。大概意思是ECJ是一個編譯優(yōu)化包,可以提升比Javac和JIKES更好的編譯速度。要想使編譯通過,有兩個兩個方法:

    方法一:禁用ECJ。在Liferay的SDK下面找到build.Administrator.properties,此處中間的Administrator名稱不一定是這樣的,具體體系名稱是根據(jù)當(dāng)前系統(tǒng)的用戶名生成的。在里面添加如下內(nèi)容

    javac.compiler=modern
    #javac.compiler=org.eclipse.jdt.core.JDTCompilerAdapter

    方法二:將ECJ的包添加到ant的路徑里面。ecj.jar包可以在Liferay的工程的源碼包\lib\development下面找到。將此包添加到ant的路徑里面。Windows-->preferences-->Ant-->Runtime,在右邊的Classpath-->Ant Home Entries(Default) -->Add External JARs,將ecj包添加進(jìn)來。

    2、在編譯源碼的時候出現(xiàn):

    Please set the environment variable ANT_OPTS to the recommended value of
    "-Xmx1024m -XX:MaxPermSize=512m".

    這個提示的意思是說當(dāng)前的JVM參數(shù)設(shè)置的太小了,不夠liferay編譯使用,需要增加JVM內(nèi)存的分配,并建議將Xmx參數(shù)設(shè)置成1024m,MaxPermSize設(shè)置成512m。這是因為liferay的源碼比較大,內(nèi)容比較多,使用了大量的classloader等,需要比較大的內(nèi)存。

    解決方法上面已經(jīng)給出提示了將環(huán)境變量(其實就是JVM的參數(shù))推薦設(shè)置成上面的提示。

    1)在Liferay工程的源碼里面的build.xml上點擊右鍵-->Run as-->External Tool Configurations

    2)在tab標(biāo)簽里面找到Environment,點擊new,在name里面輸入ANT_OPTS,在value里面輸入-Xmx1024m -XX:MaxPermSize=512m,然后點擊apply。

    3)再次運行ant的編譯,即可正常編譯。

    3、如果出現(xiàn)類似如下錯誤,請參考上文的“二、編譯源碼”

    Tomcat is not installed in E:/liferay/6.2/bundles/tomcat-7.0.42. If you already have Tomcat
    installed, make sure the property "${app.server.tomcat.dir}" points to your
    Tomcat installation. If you wish to automatically install Tomcat into

    Liferay 6.1開發(fā)學(xué)習(xí)(六):國際化

    Liferay的開發(fā)不建議直接在代碼中使用中文等內(nèi)容,建議使用國際化的方式,從資源文件中讀取語言等信息,Liferay在平臺對封裝了許多操作資源文件的類,我們只需要按照此規(guī)則既可方便的實現(xiàn)國際化。

    一、Portlet屬性的國際化

    在前面創(chuàng)建的Portlet的時候,portlet的名稱等都是英文的,在添加portlet的時候,顯示的也是英文的,如何將這些信息顯示成中文呢?如將下面Study顯示成中文。

    1、檢查portelt.xml的XML文件中的此portlet的信息,是否包含下面的代碼,這個是關(guān)鍵,如果沒有手動的添加到portlet-info標(biāo)簽的上面。如查在portlet的創(chuàng)建向?qū)Ю锩婀催x了“Create resource bundle file”,則會自動生成。

    <resource-bundle>content/Language</resource-bundle>

    2、工程的src目錄下面找到content包,如果沒有則創(chuàng)建,如果有則打開。在里面新建Language_zh_CN.properties文件,我們的portlet中文信息寫在此文件里面。

    3、在此文件中寫入“javax.portlet.title=此處寫相應(yīng)的標(biāo)題文字”,可以直接寫中文,eclipse的properties編輯器,會自動的轉(zhuǎn)換成unicode代碼。一般我們只寫title就可以,如果有特別需求,可以加上javax.portlet.keywords,javax.portlet.short-title等信息。

    4、現(xiàn)在重新打包部署此工程,再次添加portlet,即可看到portlet的名稱變成了中文。

    注意:<resource-bundle>content/Language</resource-bundle>這里的內(nèi)容定義了,我們存放語言文件的目錄在content目錄下面的Language文件,這里也可以定義成自己喜歡的,只要按照此規(guī)則即可。

    二、內(nèi)容的國際化

    上面的國際化是portlet屬性信息的國際化,如果是我們想在代碼中使用這些國際化信息呢?比如提示語、按鈕名稱等等。這個地方的方法就和普通的java代碼的國際化一樣,在上面的語言文件中寫入相應(yīng)的key,在代碼中讀取即可。

    1、如我們要將“參數(shù)名稱”這個詞國際化,則在Language_zh_CN.properties中寫入:

    propertyName=\u53c2\u6570\u540d\u79f0

    后面的是參數(shù)名稱的unicode碼,我們在編輯器中直接寫入中文,編輯器會自動轉(zhuǎn)換,如果不能轉(zhuǎn)換可以使用JDK的命令如:

    native2ascii -encoding UTF-8 Language_zh_CN.properties.native Language_zh_CN.properties

    進(jìn)行中文編碼的轉(zhuǎn)換。

    2、在代碼中調(diào)用:

    JSP中:LanguageUtil.get(pageContext,"propertyName")

    JAVA代碼中:LanguageUtil.get(portletRequest.getLocale(), "propertyName")。其中的第一個參數(shù)為Local,也可以使用Locale.CHINESE

    三、Liferay Portlet屬性國際化的修改

    在一中提到的portlet屬性的國際化存在一個問題,也就是我們一個語言文件中只能定義一個portlet的屬性信息,如果我們在一個插件工程中需要國際化多個portlet的屬性信息怎么辦?在Liferay的官方論壇、Wiki里面也有不少人討論此問題,但Liferay的解釋就是不支持!在一個資源文件里面只能寫一個portlet的屬性信息。

    個人覺得這一點非常不好,如我的一個插件工程中有十幾個portlet,那么難道需要定義十幾個語言資源文件或者拆分成十幾個Portlet?如果支持下面這樣:

    javax.portlet.title.MyPortletTitle = My Portlet Title

    如果是這樣的才是很合理的,Liferay平臺里面的Portlet的信息就是這樣的形式國際化的,但是插件里面不支持。Liferay平臺本身是使用的Strtus resource bundle,所以和我們的不太一樣。

    既然官方不支持,我們就自己動手改造了,好在Liferay是開源的,我們修改他的源碼自己實現(xiàn)就可以了。

    方法如下:

    1、參考上一篇文章,http://www.huqiwen.com/2012/09/21/liferay-6-1-development-study-5-compile-debug-deploy/,如果編譯部署關(guān)聯(lián)Liferay的源碼

    2、在源碼里面找到PortletResourceBundle.java這個類(小提示:可以在eclipse中使用快捷鍵ctrl+shift+r來快速定位此文件)。找到其中的handleGetObject方法,修改成如下,下面有注釋,顯示了哪里修改的:

    @Overrideprotected Object handleGetObject(String key) {if (key == null) {throw new NullPointerException();} String value = null;if (parent != null) {try {value = parent.getString(key);}catch (MissingResourceException mre) {//hqw 2012.09.09 add beginString titlekey = key.concat(StringPool.PERIOD).concat(_portletInfo.getTitle());if (Validator.isNotNull(titlekey)) {titlekey = titlekey.toLowerCase();}try {value = parent.getString(titlekey);} catch (MissingResourceException mre2) {}//end}} if ((value == null) || (value == ResourceBundleUtil.NULL_VALUE)) {value = _getJavaxPortletString(key);} if ((value == null) && ResourceBundleThreadLocal.isReplace()) {value = ResourceBundleUtil.NULL_VALUE;} return value;}

    在我debug時,發(fā)現(xiàn)liferay只是通過javax.portlet.tiltle這個key值尋找,那我們在給他加上具體的title值就可以了。現(xiàn)在修改后的不但兼容他原來的,而且又支持javax.portlet.title.MyPortletTitle = My Portlet Title。這樣的多好

    3、現(xiàn)在使用ant進(jìn)行deploy源碼,再次啟動tomcat就發(fā)現(xiàn),現(xiàn)在的國際化已經(jīng)支持我們需要的形式了。

    Liferay 6.1開發(fā)學(xué)習(xí)(七):Layout布局模板開發(fā)

    Liferay提供了layout功能,可以方便的自由布局,用戶或者管理員可以根據(jù)選用的布局模板對頁面進(jìn)行自由布局。Liferay默認(rèn)中提供了幾種常用的layout模板,如單欄目、雙欄目(20%/80%,30%/70%)等幾種常用的,但是這些布局模板并不能滿足我們實際的需求,一些復(fù)雜的布局需要自己開發(fā)。

    LayoutTPL開發(fā)

    布局模板是一個tpl文件,本身結(jié)構(gòu)非常簡單。基于Liferay IDE可以進(jìn)行可視化的、拖動的形式進(jìn)行布局TPL的開發(fā)。方法如下 :

    1、在Eclipse的工具條上,點擊New Liferay Project,在plugin type里面選擇Layout,點擊finish。則完成了Layouttpl工程的建立。

    2、工程里面對于開發(fā)有用的文件主要有四個:

    *.tpl:這個文件是定義PC訪問時布局模板的文件。

    *.wap.tpl:定義手機(jī)訪問時的而已模板文件。

    *.png:這個圖片是用于顯示布局模板的縮略圖,方便在選擇模板的時候預(yù)覽此模板的樣式。

    liferay-layout-templates.xml:此文件位于WEB-INF目錄下面,用于定義此布局模板的元數(shù)據(jù)信息。

    3、通常情況下,我們只需要編輯*.tpl文件即可。如下圖,為我拖出來的一個TPL文件。

    4、可以通過鼠標(biāo)可視化的形式,添加column(列)、row(行)等,通過控制點來顯示列寬的百分比等。

    布局模板的發(fā)布

    主題創(chuàng)建修改完成后,點擊ant中的deploy進(jìn)行發(fā)布即可。

    其他說明:

    layoutTPL的開發(fā)非常簡單。通過Liferay IDE通夠?qū)崿F(xiàn)快速開發(fā)。有一些小技巧

    1、可以在一個TPL工程里面建立多個布局模板,只需要在liferay-layout-templates.xml里面對這些文件進(jìn)行定義描述即可。

    2、如果在拖動中不能拖出自己想要的寬度百分比,可以進(jìn)行source模式,手動的修改這些百分比,為 aui-w24,w后面的數(shù)值即是百分比。

    3、如果不需要進(jìn)行移動訪問,*.wap.tpl的內(nèi)容可以不用管。

    4、建議添加*.png這個縮略多,方便在添加切換的時候預(yù)覽。

    Liferay 6.1開發(fā)學(xué)習(xí)(八):主題開發(fā)

    Liferay可以為不同的頁面、社區(qū)、組織等提供不同的主題。方便實現(xiàn)用戶的個性化配置,同時Liferay提供的IDE方便開發(fā)人員進(jìn)行主題的個性化開發(fā)。

    Liferay主題的創(chuàng)建

    1、在Eclipse的工具條上,點擊New Liferay Project,在plugin type里面選擇Theme,點擊finish。則完成了theme工程的建立。

    2、Liferay的主題開發(fā)是在他提供的一個模板的基礎(chǔ)上進(jìn)行修改。我們將個性化的內(nèi)容放置于_diffs目錄下面,在deploy的時候,liferay會自動的將此文件的內(nèi)容合并到主題中,并覆蓋原先相應(yīng)的內(nèi)容。如果沒有覆蓋的則采用默認(rèn)的樣式等。

    3、liferay的主題主要有四部分組成,CSS、images、js、template。這幾部分中前三部分,不需要特別說明。template里面是使用Velocity編寫的模板,方便我們修改他相應(yīng)的模板內(nèi)容。

    4、依次說明:

    CSS

    CSS里面的文件是分類的,如forms.css里面是定義的表單相關(guān)的,navigation.css里面是定義的導(dǎo)航相關(guān)的,layout.css是定義的布局相關(guān)的等等。比如我們需要修改導(dǎo)航的樣式,則在_diffs目錄下面建立css目錄,并將上面的navigation.css復(fù)制到_diffs/css/下面。我們在此文件上修改,liferay IDE會自動的編譯覆蓋原先的內(nèi)容。

    如果我們需要定義的CSS內(nèi)容,不是liferay本身提供的,而是我們自己新建立的樣式,則推薦將此樣式寫在_diffs/css/custom.css里面。

    JS

    js的內(nèi)容一般不做修改,也沒有必要在主題包里面定義太多的JS相關(guān)的內(nèi)容。

    images

    將和自己編輯的主題相關(guān)的圖片存于images目錄下面。如果需要在代碼中引用,可以使用

    String imgpath = themeDisplay.getPathThemeImages();

    這里取到的imgpath,即為images目錄。

    templates

    模板文件,用于定義常用的portlet、導(dǎo)航、通用的等模板文件。可以根據(jù)自己的實際需求進(jìn)行修改。和普通的Velocity一樣,如果對于Velocity不熟悉的,可以大概了解一下,使用起來和普通的HTML沒有太大的區(qū)別。

    主題的發(fā)布

    主題創(chuàng)建修改完成后,點擊ant中的deploy進(jìn)行發(fā)布即可。

    其他說明

    在_diffs目錄里面只需要復(fù)制自己要修改的內(nèi)容,不需要修改的則不需要復(fù)制過來,如下圖:

    1、我需要修改layout.css,則只需要從上級的CSS目錄里面將此文件復(fù)制過來,在此文件上進(jìn)行修改。不需要修改navigation.css則不用復(fù)制。其他的也類似。

    2、圖片,我需要將自定義的圖片保存到common目錄下面,則需要要創(chuàng)建一個comon目錄,在引下面存放自己的文件即可。

    3、tumbnail.png文件是存放的主題的縮略圖,方便在切換主題時預(yù)覽。

    Liferay 6.1開發(fā)學(xué)習(xí)(九):Hook開發(fā)簡介

    一、Hook是什么

    hook是什么在http://www.huqiwen.com/2012/09/01/liferay-6-1-development-study-2-create-portlet-project/里面有一個大概的介紹。Liferay提供hook的目的是減少二次開發(fā)的代碼與liferay核心工程的耦合,通過hook我們主要可以主要做以下六件事情:

    1、覆蓋事件處理程序:如程序啟動事件(application.startup.events)、登錄注銷事件(login.events.pre、login.events.post)、session的創(chuàng)建銷毀事件等。

    2、語言包:比如對liferay的某些翻譯不滿意,需要自定義,則可以使用hook覆蓋liferay的語言包。

    3、liferay工程的portlet JSP內(nèi)容:比如想在頂部的top_bar里面添加內(nèi)容、想修改liferay的用戶編輯界面、想修改用戶登錄界面等等。

    4、覆蓋portal.properties里面的屬性配置:可以在hook工程里面覆蓋一些liferay的portal.properties里面屬性配置,但是請注意,在hook工程里面只能覆蓋部分的屬性設(shè)置。不能覆蓋的如果需要可以在root/WEB-INF/classes里面添加portal-ext.properties,這個同可以覆蓋所有的。

    5、覆蓋liferay的services里面的方法,如UserLocalService、GroupLocalService、OrganizationLocalService等等。

    6、Liferay的Model監(jiān)聽程序,比如user、group、blog等的創(chuàng)建、更新、查看;插件的部署;集群的消息傳遞等等監(jiān)聽程序。

    二、使用Liferay IDE進(jìn)行hook開發(fā)

    1、在liferay IDE中,New Liferay Project-->選擇hook-->輸入project Name,點擊完成,即可創(chuàng)建一個hook工程。

    2、在IDE的工具條中,選擇New Liferay hook,選擇我們要創(chuàng)建的hook類型,如下圖:

    custom JSp:為自定義的JSP文件

    portal properties:覆蓋portal屬性

    Services:這個可以可以做兩件事情一是覆蓋事件處理程序;二是覆蓋service類

    Lanuage properties:這個覆蓋或者新增國際化的語言文件。

    3、以Custom JSPs為例,點擊下一步,如下圖

    盡量的使用 Add from Liferay。這樣我們可以在彈出的界面中選擇相應(yīng)的我們要覆蓋的JSP路徑。點擊完成。

    4、現(xiàn)在demo-hook工程目錄下的docroot/custom_jsps下面將出現(xiàn)我們上面選擇的路徑的JSP文件,此文件下的JSP路徑一定要和Liferay root下的待覆蓋的JSP路徑相符。現(xiàn)在就可以編輯此JSP來覆蓋我們想覆蓋的內(nèi)容,打開此JSP可以看到這里面的內(nèi)容和portal下面的JSP內(nèi)容完全一樣,修改想修改的部,點擊ant的deploy即可發(fā)布。

    5、對于示例中的top_js.jspf文件,可以做什么呢?top_js.jspf此文件是portal的頭部JS的加載程序。比如我要在我的portlet工程里面引用jQuery庫,則可以在top_js.jsp里面將jQuery的庫引進(jìn)來,這樣在portlet的工程里面不用每個頁面都需要引用jQuery,可以避免一個頁面中多個portlet引用jQuery引起的沖突。引用方法如下

    在top_js.jspf的最后部分添加:

    <script type="text/javascript" src="/html/js/jquery-1.8.0.min.js"></script>

    同時,在custom_jsps/html下面建立js目錄,并將jquery-1.8.0.min.js庫復(fù)制到此目錄下面即可。

    6、對于portal.properties的覆蓋和語言包的覆蓋類似。Services的覆蓋略有不同,在下一篇文章里面詳述。

    Liferay 6.1開發(fā)學(xué)習(xí)(十):在Liferay中使用Ajax

    在現(xiàn)在的Web開發(fā)中,Ajax的使用非常頻繁,合理的使用Ajax也是提高用戶體驗的一個重要手段,在Liferay中使用Ajax其實非常方便,但是和普通的web程序稍有差異。

    一、簡單示例

    客戶端代碼編寫

    1、在Liferay中創(chuàng)建一個簡單的Portlet頁面,可以取名為ajaxPortlet,具體的創(chuàng)建過程可以參考;http://www.huqiwen.com/2012/09/03/liferay-6-1-development-study-3-portlet-explicate/

    2、在liferay中ajax的請求地址要使用portlet:resourceURL,a這樣定義:<portlet:resourceURL var="ajaxUrl"/>,而不是普通請求的portlet:actionURL。

    3、編輯view.jsp頁面,在頁面中添加<portlet:resourceURL var="ajaxUrl"/>,引入Jquery的包(使用jquery做ajax請求),然后編寫一個簡單的ajax請求代碼。

    function ajaxTest(){$.post('<%=ajaxUrl%>',{p_p_resource_id:'test1'},function(data){$('#message').html(data);})}

    這個代碼的意思就是請求一下服務(wù)端,然后將得到的結(jié)果顯示到id為message的html元素中。

    4、這樣客戶端的代碼就是編寫完成。具體的詳細(xì)代碼參看下面中的附件。

    服務(wù)端代碼編寫

    1、在portlet的控制類中重寫serveResource方法。

    2、在此方法中添加相應(yīng)的處理類,此處的處理方法和普通的servlet一樣,可以使用下面的代碼。

    @Overridepublic void serveResource(ResourceRequest resourceRequest, ResourceResponse resourceResponse) throws IOException, PortletException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = null;try {out = response.getWriter();} catch (IOException e) {e.printStackTrace();}String result = "這是服務(wù)端返回的結(jié)果信息:";out.println(result);out.flush();out.close();super.serveResource(resourceRequest, resourceResponse);}

    可以看到其實和普通的servlet處理基本上是一模一樣。

    二、多ajax請求

    上面的示例雖然簡單,但仔細(xì)一想就會發(fā)現(xiàn)有一個問題,如果在一個頁面中有多個ajax請求怎么辦?我們要依靠一個resourceID來區(qū)分不同的請求,同樣也是分客戶端和服務(wù)端。

    客戶端

    方法1:在resourceURL里面添加一個屬性id,如<portlet:resourceURL var="ajaxUrl2" id="test2"/>

    方法2:在rsourceURL里面添加一個參數(shù),如:

    <portlet:resourceURL var="ajaxUrl1"><portlet:param name="p_p_resource_id" value="test1"/> </portlet:resourceURL>

    方法3:在ajax請求時添加相應(yīng)的參數(shù),如:

    function ajaxTest(){$.post('<%=ajaxUrl1%>',{p_p_resource_id:'test1'},function(data){$('#message').html(data);})}

    方法4:直接在URL里面拼接

    服務(wù)端

    服務(wù)端的處理只有一個,取得此resourceID,方法為String resourceID = resourceRequest.getResourceID();然后根據(jù)不同的resourceID判斷處理不同的ajax請求。返回和一般的處理一樣。

    其他

    在處理返回結(jié)果時,如果不想使用普通的servlet的處理方式,可以使用liferay的ServletResponseUtil.sendFile()方法,此方法主要是用來處理文件的,但用于處理ajax的請求也非常方便。

    demo代碼下載:點擊此處下載

    Liferay 6.1開發(fā)學(xué)習(xí)(十一):調(diào)度器-定時任務(wù)

    在liferay的開發(fā)中經(jīng)常需要執(zhí)行一些定時調(diào)度任務(wù),一般情況下在普通的web開發(fā)中我們使用quartz來做調(diào)度,但是在Liferay中已經(jīng)對于調(diào)度做了一個封裝,方便我們在開發(fā)中執(zhí)行調(diào)度任務(wù),liferay中封裝了兩種方法方便我們做調(diào)度擴(kuò)展。

    一、基于Portlet的調(diào)度

    如某個的調(diào)度是在某個portlet中使用的,則可以使用一面的方法:

    1、? 編寫一個類,實現(xiàn)接口:com.liferay.portal.kernel.messageing.MessageListener。如下圖所示。其中的doReceive()方法是定時執(zhí)行的內(nèi)容。

    2、? 在liferay-portlet.xml里面注冊這個調(diào)度類,添加如下代碼:

    <scheduler-entry> <scheduler-event-listener-class> xxx.cmsnewsgather.NewsGatherMessageListener(上面此類的全路徑) </scheduler-event-listener-class><trigger><simple><simple-trigger-value>15</simple-trigger-value><time-unit>minute</time-unit></simple></trigger> </scheduler-entry>

    scheduler-event-listener-class:里面的類為第一步里面編寫的類

    simple-trigger-value:里面為調(diào)度周期的數(shù)值,time-unit為調(diào)度周期的單位。上面的意思為每15分鐘執(zhí)行一次。此時間也可以從配置文件中讀取。則將此標(biāo)簽完成<property-key>newsgather.gather.time</property-key>,其中的newsgather.gather.time為屬性文件(portal.properties)里面配置的值

    Time-unit:表示周期的周期可以為:day、hour、minute、second、week這幾個單位。

    3、? 上面的代碼即完成了一個調(diào)度器的開始,內(nèi)容為每15分鐘執(zhí)行一次第一步類里面的doReceive()方法。

    二、基于servlet的調(diào)度

    注:此方法適用于lifery6.0.6,不適用于liferay6.1.x

    1、同上,編寫一個實現(xiàn)com.liferay.portal.kernel.messageing.MessageListener的類。

    2、在相應(yīng)工程下面的web.xml里面添加servlet的注冊信息,如下:

    <servlet><servlet-name>Lucene Servlet</servlet-name>?????? <servlet-class> xx.xx.servlet.xxxServlet </servlet-class><load-on-startup>2</load-on-startup> </servlet>

    3、在上面的servlet的init(ServletConfig servletConfig)方法里面添加如下內(nèi)容:

    super.init(servletConfig); SchedulerEntry schedulerEntry = new SchedulerEntryImpl();?schedulerEntry.setEventListenerClass(xxxMessageListener.class.getName());schedulerEntry.setTimeUnit(TimeUnit.MINUTE);schedulerEntry.setTriggerType(TriggerType.SIMPLE);schedulerEntry.setTriggerValue(15);?try { SchedulerEngineUtil.schedule( schedulerEntry, PortalClassLoaderUtil.getClassLoader()); }

    其中的xxxMessageListener為第一步編寫的類。分別在setTimeUnit和setTriggerValue里面設(shè)置調(diào)度的周期單位和時間。

    三、兩者的區(qū)別及適用情況

    對于方法一是推薦使用的,但是有時候我們可能需要在程序中來設(shè)置調(diào)度周期,但是方法一需要在liferay-portlet.xml里面將調(diào)度的周期和時間就固定了。我們需要做一下變通,如在新聞采集的自動采集的代碼里面就使用的方法一,在liferay工程中的日程管理也是使用了此功能。此方法適用于下面情況

    • 需要在程序中設(shè)置調(diào)度周期
    • 但是對于時間的精確度需求不是非常高,可以有一定的誤差

    如新聞采集的自動采集,如果我們需要對一個網(wǎng)站進(jìn)行新聞的自動采集,我們一般將這個周期設(shè)置成幾個小時重復(fù)執(zhí)行一次,我們可以在liferay-portlet.xml里面設(shè)置成這個調(diào)度是10分鐘或者30分鐘執(zhí)行一次檢查,這個時候我們在doReceive()里面調(diào)用的代碼不是具體的執(zhí)行采集的代碼,而是檢查現(xiàn)在的這個時間是否在下調(diào)度周期中,如果是則執(zhí)行采集,如果不是則跳過。

    對于方法二而言,適用于以下情況:

    • 需要執(zhí)行調(diào)度的代碼不明確屬于某一個portlet。
    • 需要精確控制時間。

    只要滿足上面的任何一個條件,都適合使用方法二,方法二里面的調(diào)度時間可以從數(shù)據(jù)庫中讀取也可以從配置文件中讀取。

    Liferay 6.1開發(fā)學(xué)習(xí)(十二):文件上傳處理

    Liferay中提供了完善的文件處理,從liferay 6.1開始在文件的處理方面,不再區(qū)分文檔和圖片,統(tǒng)一為文件媒體庫。在普通的portlet插件工程中,如果想將文件上傳到Liferay的文檔庫中,大的階段可以分為兩個流程:一、在portlet中將上傳的文件取到,二調(diào)用Liferay的API將文件上傳到文檔庫中。

    (注:這里的文件上傳只講服務(wù)端的處理,至于客戶端也就是瀏覽器使用普通的表單文件上傳,還是使用swffileupload或者ajax提交等與服務(wù)端沒有關(guān)系,處理方法都是一樣的)

    一、在portlet中取到上傳的文件

    這兩的獲取有兩種方法,一種是普通的fileupload的處理方法,一種是使用liferay的API

    1、使用fileupload的處理方法:

    此種方法的獲取和在普通的servlet里面使用fileupload的方法一樣,核心代碼如下 :

    DiskFileItemFactory factory = new DiskFileItemFactory();//PortletFileUpload upload = new PortletFileUpload(factory); ServletFileUpload upload = new ServletFileUpload(factory);upload.setSizeMax(1024 * 1024 * 200);HttpServletRequest servletRequest = PortalUtil.getHttpServletRequest(request);List<FileItem> items = upload.parseRequest(servletRequest);

    注:也可以使用此行代碼,如果使用了此行則下面的HttpServletRequest servletRequest = PortalUtil.getHttpServletRequest(request)就可以不要,在upload.parseRequest里面?zhèn)鱝ctionRequest。但是此方法在weblogic環(huán)境下面會出錯,所以如果要在weblogic下面運行,請使用下面的servletFileUpload。

    其他代碼就和在普通的Servlet里面使用fileupload一樣,這里不再多寫。

    2、使用Liferay的API獲取上傳文件

    推薦使用下面的代碼進(jìn)行文件上傳。

    UploadPortletRequest uploadPortletRequest = PortalUtil.getUploadPortletRequest(actionRequest);String sourceFileName = uploadPortletRequest.getFileName("file");String contentType = uploadPortletRequest.getContentType("file");long size = uploadPortletRequest.getSize("file"); // File file = uploadPortletRequest.getFile("file");InputStream is = uploadPortletRequest.getFileAsStream("file");

    :其中的getFileName中的file為<input type="file" name="file">中的name值,具體的可以要看自己的調(diào)整。

    二、將獲取到的文件上傳到Liferay的文檔庫

    1、上傳文件

    在portlet中獲取到我們上傳的文件,只算是完成了第一步。取到了上傳的文件,怎么傳到Liferay的文件庫中呢?使用如下的接口

    DLAppLocalServiceUtil.addFileEntry(long userId, long repositoryId, long folderId,java.lang.String sourceFileName, java.lang.String mimeType,java.lang.String title, java.lang.String description,java.lang.String changeLog, byte[] bytes,com.liferay.portal.service.ServiceContext serviceContext)

    此接口的參數(shù)逐個說明:

    long userId:上傳此文件的用戶id

    long repositoryId:倉庫存儲ID,此ID一般為groupid

    long folderId:文件夾ID,可以自己創(chuàng)建,或使用liferay默認(rèn)的如:DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_BASIC_DOCUMENT等,最好是自己根據(jù)上傳資源的情況分類,如新聞的存到新聞文件,博客的存成博客文件等

    String sourceFileName:上傳文件的源文件名

    String mimeType:算是文件類型,可以使用mimeType = MimeTypesUtil.getContentType(fileName);根據(jù)文件名獲取。

    String title:文件標(biāo)題,這個與SourceFileName的區(qū)別在于,此title是最終顯示在系統(tǒng)上的,可以由用戶輸入,源文件名稱是上傳獲取的文件名稱,不能手動改變。可以留空。

    String description:關(guān)于此文件的描述,可以留空。

    String changeLog:文件修改日志,可以留空。

    byte[] bytes:文件的正文件,字節(jié)數(shù)組。

    ServiceContext serviceContext:此類可以通過以下代碼

    ServiceContext serviceContext = ServiceContextFactory.getInstance(DLFileEntry.class.getName(), request);

    獲取。此對象里面包含了一些環(huán)境信息,如groupid,companyid,權(quán)限,門戶路徑,當(dāng)前語言,userId等信息。

    在實際應(yīng)用中可以自己將上面的這個接口再做一層封裝,作為一個公共的文件上傳接口,以供其他需要文件上傳的地方調(diào)用,具體的請自行封裝,這里就不再帖我封裝的代碼。

    2、獲取文件路徑

    上面的文件上傳之后返回的是一個FileEntry的對象,如果獲取到上傳的文件的路徑呢,方法如下,可以定義一個方法,用來返回文件路徑,此方法對圖片、各式文件都是有效。

    public static String getFilePath(FileEntry fileEntry) {if (null!=fileEntry) {return "/documents/" + fileEntry.getRepositoryId() + "/" + fileEntry.getFolderId() + "/"+ HttpUtil.encodeURL(HtmlUtil.unescape(fileEntry.getTitle()), true) + "/" + fileEntry.getUuid();}else {//如有需要,此處可以定義一個默認(rèn)圖片return StringPool.BLANK;}

    或者下面的這個方法,下面的這個更簡便一些

    public static String getFilePath(FileEntry fileEntry) {if (null!=fileEntry) {return "/documents/" + fileEntry.getRepositoryId() + "/" + fileEntry.getUuid();}else {//如有需要,此處可以定義一個默認(rèn)圖片return StringPool.BLANK;}

    有時候如果文件是一個圖片,上傳的圖片可以很大,如何獲取一個縮略圖呢?如下:

    public static String getSmallImagePath(FileEntry fileEntry){
    String path = getFilePath(fileEntry);
    return path+"?imageThumbnail=1";
    }

    Liferay 6.1開發(fā)學(xué)習(xí)(十三):彈出層/彈出對話框的使用

    在日常的開發(fā)中,為了提高用戶體驗,經(jīng)常會使用彈出層或者彈出框。在Liferay中可以使用AUI的標(biāo)簽及封裝的JavaScript代碼方便的達(dá)到這一目的。針對彈出內(nèi)容的不同,彈出對話框大體上可以分為三種形式,彈出div層、彈出普通的HTML頁或JSP頁面、彈出portlet。

    一、彈出div層

    有幾種寫法,本質(zhì)上是一樣的,一種是普通的JavaScript代碼,一種是使用aui標(biāo)簽。

    1、普通的javascript代碼

    <script>function test(){AUI().use('aui-dialog', function(A) {var popup = new A.Dialog({bodyContent: A.one('#webDav').html(),centered: true,destroyOnClose: true,modal: false,title: '彈出層測試',width: 500,buttons: [{label: '確定',handler: function() {alert('點擊了確定');}},{label:'取消',handler:function(){this.close();}}]}).render();}); } </script>

    代碼看起來有點小復(fù)雜,其實很簡單,逐步的說明一下:

    var popup:?這是定義當(dāng)前的彈出層對象。在其他地方可以使用popup.close()關(guān)閉當(dāng)前的對話框。

    bodyContent:?A.one('#webDav').html():表示彈出層的正文,這里是彈出一個id為webDav的對象。A.one('#webDav').html()這是aui代碼的寫法(aui其實是YUI的衍生版,所以和YUI的用法基本上一樣),表示選擇id為webDav的對象,取其中的html代碼。

    centered:彈出后是否居中,默認(rèn)為false.

    destroyOnClose:是否在半閉時銷毀

    modal: 是否模態(tài)否,也就是是不是鎖定背景是否讓背景可以編輯,值為true/false,默認(rèn)為false,為true時背景不可以編輯。

    title:彈出層的標(biāo)題,使用單引號或雙引號。

    width:彈出層的寬度,必須為數(shù)字,不能用百分比。如果不寫為自適應(yīng)。

    height:彈出層的高度,如果不寫為自適應(yīng)。

    buttons:在彈出層上面定義的按鈕。非必須。我們一般添加確定和取消兩個。多個按鈕之間使用逗號分割,text的內(nèi)容為按鈕的顯示值,handler為綁定的方法

    2、使用aui標(biāo)簽

    <aui:script use="aui-dialog">var create = A.one('#createNew');create.on('click',function(event) {var popup = new A.Dialog({bodyContent: A.one('#webDav').html(),centered: true,modal: true,title: '彈出層測試',width: 500}).render();}); </aui:script>

    和上面的的基本上差不多,這里是在createNew的對象上綁定了一個click的方法,如果此對象被點擊了,執(zhí)行彈出層代碼。其他的和上面的一樣。

    上面使用的是aui標(biāo)簽,所以需要在頁中引入

    <%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>

    3、使用Liferay.provide

    此種方法和上面的非常類似,如下:

    <aui:script> Liferay.provide(window,'showDialog',function() {var A = AUI();var dialog = new A.Dialog({bodyContent: A.one('#webDav').html(),destroyOnClose: true,modal: false,title: '這是標(biāo)題',width: 900}).render();},['aui-dialog'] ); </aui:script>

    寫法和上面的沒有太多的區(qū)別,只是寫法的不同。showDialog 這個參數(shù)其實就是函數(shù)名,在其他地方可以直接調(diào)用此方法來彈出下面的彈出層,如果是要傳參數(shù)可以直接寫在showDialog(arg)這個里面。上面的的function里面添加此參數(shù)。如function(arg),在下面直接使用arg參數(shù)即可。

    二、彈出一個HTML頁面或者是JSP頁面。

    彈出一個頁面的方法和上面的基本上相同,具體看下面的示例。

    <aui:script> Liferay.provide(window,'showDialog',function() {var A = AUI();var url= "要彈出的頁面的地址";var dialog = new A.Dialog({destroyOnClose: true,modal: false,title: '這是標(biāo)題',width: 900}).plug(A.Plugin.IO,{uri: url}).render();},['aui-dialog'] ); </aui:script>

    不同之處是加了一個plug來顯示待彈出的頁面地址。在dialog里面也可以添加bodyContent屬性,里面可以添加上在彈出的過程的提示語,比“頁面正在加載中請稍候……”,在url加載后將替換上面的內(nèi)容。

    三、彈出一個portlet頁面。

    使用二里面的方法也可以彈出一個portlet頁面,但是有時候會不能正常工作,步驟2的彈出的原理還是彈出一個div,在這個div里面加載目標(biāo)頁面的內(nèi)容。彈出portlet頁面我們需要彈出一個iframe,這樣就可以使彈出的portlet頁面正常工作。方法如下:

    <aui:script>Liferay.provide(window,'showPortletUrl',function(url) {var instance = this;Liferay.Util.openWindow({cache: false,dialog: {align: Liferay.Util.Window.ALIGN_CENTER,after: {render: function(event) {this.set('y', this.get('y') + 50);}},width: 1000},dialogIframe: {id: 'siteManagementIframe',uri: url},title: '管理頁面',uri: url});},['liferay-util-window']); </aui:script>

    在上面的方法中我是將待彈出的porltet的URL以參數(shù)的形式傳進(jìn)來的,調(diào)用的時候方法為:showPortletUrl(url)。dialogIframe中的id為彈出的iframe的id名,uri為待加載的portlet頁面地址。

    注意:如果要彈出porltet,請講windowState設(shè)為pop_up,也就是LiferayWindowState.POP_UP這個變量。

    Liferay 6.1開發(fā)學(xué)習(xí)(十四):在自己的Portlet中使用Liferay的全文檢索

    在Liferay中的全文檢索是使用的Lucene,方便我們的對內(nèi)容進(jìn)行全文檢索。liferay中對文章、文檔、博客、wiki、留言等實現(xiàn)了全文檢索,如何在我們自己的Portlet中使用Liferay的全文檢索呢?

    實例場景如下:

    我們自己實現(xiàn)了一個CMS,沒有使用Liferay中的Journal類,比如存放新聞的類叫做CmsArticle。我們現(xiàn)在需要對這個新聞進(jìn)行全文檢索,可以檢索新聞?wù)摹?biāo)題、摘要、作者等,同時可以進(jìn)行范圍搜索,如只搜索標(biāo)題、只需要正文或全部等。

    一、建立索引類

    繼承BaseIndexer類,編寫一個索引類,如叫做CmsArticleIndexer。重寫里面的相關(guān)搜索方法。一般需要重寫

    getClassNames

    getSummary

    doDelete

    doGetDocument

    doReindex

    getPortletId

    等幾個方法,其他的方法可以根據(jù)需要進(jìn)行重寫。

    簡單貼幾個主要的方法的內(nèi)容:

    protected Document doGetDocument(Object obj) throws Exception {CmsArticle article = (CmsArticle)obj; long companyId = article.getCompanyId();long groupId = getParentGroupId(article.getGroupId());long scopeGroupId = article.getGroupId(); ……………………省略相關(guān)字段的獲取和上面的一樣 Document document = new DocumentImpl(); document.addUID(PORTLET_ID, groupId, articleId);document.addKeyword(Field.COMPANY_ID, companyId);document.addKeyword(Field.PORTLET_ID, PORTLET_ID);document.addKeyword(Field.GROUP_ID, groupId);document.addKeyword(Field.SCOPE_GROUP_ID, scopeGroupId);document.addKeyword(Field.USER_ID, userId); //將不同的字段添加到索引中document.addDate(Field.MODIFIED_DATE, modifedDate);document.addText(Field.TITLE, title);document.addText(Field.CONTENT, ArticleUtil.getArticleText(content));document.addText(Field.DESCRIPTION, description);document.addText(Field.USER_NAME, userName);document.addKeyword(Field.ENTRY_CLASS_NAME, CmsArticle.class.getName());document.addKeyword(Field.ENTRY_CLASS_PK, articleId); //這個為必須的,否則會搜索不到內(nèi)容document.addKeyword(Field.ROOT_ENTRY_CLASS_PK, resourcePrimKey);document.addKeyword(Field.TYPE, type); return document;}

    下面是重建索引的方法,方法很簡單,根據(jù)傳入的companyId或者也可以使用groupid,將某個范圍下面的內(nèi)容進(jìn)行依次取出添加到索引庫里面,這里使用了分頁,如果數(shù)據(jù)量較小可以不用分頁,但數(shù)據(jù)量大時務(wù)必分頁,否則會將內(nèi)存耗盡。

    //索引調(diào)用的方法 protected void doReindex(String[] ids) throws Exception {long companyId = GetterUtil.getLong(ids[0]); reindexArticles(companyId); } //從傳入的companyId里面依分頁將數(shù)據(jù)取出添加到索引庫里面 protected void reindexArticles(long companyId) throws Exception {int count = CmsArticleLocalServiceUtil.getCmsArticleCountByCompanyId(companyId,APPROVED_STATUS); int pages = count / Indexer.DEFAULT_INTERVAL; for (int i = 0; i <= pages; i++) {int start = (i * Indexer.DEFAULT_INTERVAL);int end = start + Indexer.DEFAULT_INTERVAL;reindexArticles(companyId, start, end);}} //索引內(nèi)容,在這里可以對新聞的狀態(tài)等進(jìn)行判斷,如只索引審批或發(fā)布過的,未審批的不進(jìn)行索引 protected void reindexArticles(long companyId, int start, int end)throws Exception { List<CmsArticle> articles = CmsArticleLocalServiceUtil.getCmsArticlesByCompanyId(companyId, APPROVED_STATUS,start, end); if (articles.isEmpty()) {return;} Collection<Document> documents = new ArrayList<Document>(); for (CmsArticle article : articles) {Document document = getDocument(article);documents.add(document);} //更新索引 SearchEngineUtil.updateDocuments(getSearchEngineId(),companyId, documents);}

    上面貼出來的是一些主要方法,可以根據(jù)不同的需求進(jìn)行調(diào)整,不滿足的可以參考Indexer相關(guān)類的實現(xiàn),liferay里面有博客、wiki、文章等索引實現(xiàn),的都是很好的學(xué)習(xí)參數(shù)資料,方法為在源碼的Indexer類名上按ctrl+T,查看他的相關(guān)實現(xiàn)或繼承類。

    二、注冊索引類

    將上面寫的索引類注冊到portlet中。打開liferay-portlet.xml文件,在相關(guān)的portlet中添加

    <indexer-class>xxx.xxx.xxx.cmsarticle.search.CmsArticleIndexer</indexer-class>

    這樣就將此索引類注冊到portlet中了。

    注冊有什么好處呢?

    1、可以在控制面板中的更新插件處,對某一個指定的portlet重建索引。

    2、在控制面板中當(dāng)點擊重建所有搜索索引時,可以調(diào)用到此索引類進(jìn)行索引重建立。

    3、如果設(shè)置了portal在啟動時更新索引,則liferay可以調(diào)到此類進(jìn)行索引更新。

    簡而言之主是注冊之后,可以讓Liferay來管理索引,方便的進(jìn)行統(tǒng)一的索引管理、重建等。

    三、搜索

    建立完了索引,工作只算完成了一小部分,還有搜索。搜索的過程比建立索引的過程要簡單的多,核心代碼只要兩行。

    //實例化索引類 Indexer indexer = IndexerRegistryUtil.getIndexer(CmsArticle.class); //進(jìn)行搜索 Hits results = indexer.search(searchContext); //從結(jié)果里面取Document Document[] docs = results.getDocs();

    第一步不需要特別說明,就是對相關(guān)索引類進(jìn)行初始化。第二步里面的搜索參數(shù)是一個searchContext,這是一個什么東西呢?這是Liferay包裝的一個參數(shù)類,可以在里面設(shè)置一些常用的搜索參數(shù),如關(guān)鍵詞、搜索分頁條件等。我們一般可以這樣使用:

    //實例化一個SearchContext SearchContext searchContext = SearchContextFactory.getInstance(request); //start和end是分頁用,如我們只要取前20條,為start=0,end=20 searchContext.setStart(start);searchContext.setEnd(end);searchContext.setKeywords(keyWords);

    既然有分頁,則需要知道結(jié)果的總條數(shù)才可以,results.length()返回的就的命中的結(jié)果數(shù)量,也就是搜索結(jié)果的總數(shù)。根據(jù)start、end、總條數(shù)即可進(jìn)行分頁處理。

    完整的搜索處理類核心代碼

    Indexer indexer = IndexerRegistryUtil.getIndexer(CmsArticle.class); SearchContext searchContext = SearchContextFactory.getInstance(request); int start = (pageNumber-1) * pageSize;int end = pageNumber * pageSize;//取消搜索權(quán)限,liferay的搜索權(quán)限是否過濾是根據(jù)searchContext里面是否能獲取到的userId來區(qū)分的searchContext.setUserId(0);searchContext.setStart(start);searchContext.setEnd(end);searchContext.setKeywords(keyWords); //這里是自定義的搜索范圍,liferay默認(rèn)是全部,這里是為了實現(xiàn)只搜索標(biāo)題、只搜索正文等而添加的的searchContext.setAttribute(ArticleSearchConstants.SEARCH_SCOPE, searchScope);int countResult = 0;try {Hits results = indexer.search(searchContext); //取得搜索關(guān)鍵詞的分詞詞元String[] terms = results.getQueryTerms();//獲取結(jié)果總數(shù)countResult = results.getLength();Document[] docs = results.getDocs();for (int i=0;i<docs.length;i++) {Document document = docs[i];String title = document.get(Field.TITLE);//對標(biāo)題進(jìn)行關(guān)鍵詞高亮String hightLightTitle = StringUtil.highlight(title, terms);//從索引中提取正文片段,如果找不到就取正文的前200個字String snippet = results.getSnippets()[i];String content = snippet;if (Validator.isNull(snippet)) {content = StringUtil.shorten(document.get(Field.CONTENT), 200);}//高亮摘要String higthLightContent = StringUtil.highlight(content, terms);//取新聞的IDString articleId = document.get(Field.ENTRY_CLASS_PK);//取新聞的groupIdlong groupId = GetterUtil.getLong(document.get(Field.GROUP_ID)); //這里可以將數(shù)據(jù)的數(shù)據(jù)封裝到相關(guān)的搜索結(jié)果類里面,進(jìn)行界面上的顯示,下面的搜索結(jié)果類的封裝省略}} catch (SearchException e) {e.printStackTrace();}

    四、其他說明

    1、如何在添加文章或內(nèi)容時對內(nèi)容建立索引?

    可以另建立一個索引線程,在內(nèi)容添加的時候?qū)⒋祟愄砑拥剿饕?#xff0c;刪除時從索引中刪除。核心的是使用下面的方法。

    indexer.reindex(article);

    indexer.delete(article);

    2、如何重建所有索引?

    可以在控制面板中,服務(wù)器-->插件安裝-->找到此portlet,旁邊有一個重建索引的按鈕,點擊即可完成對索引的重建。

    3、索引文件存儲于哪個地方?

    默認(rèn)存儲于/data/lucene目錄下面

    Liferay 6.1開發(fā)學(xué)習(xí)(十五):可配置portlet開發(fā)

    一、什么是可配置portlet

    其實portlet本來就是可以配置的,但我們的開發(fā)大部分情況下只使用view模式,edit和config模式一般沒有使用,對于使用editor和config等模式的portlet,我們可以將他們稱為可配置portlet。通過使用可配置portlet,可以做許多個性化定制。

    應(yīng)用場景:

    1、如果在首頁上有展現(xiàn)專題的地方,可以建立一個專題展現(xiàn)的portlet,這個地方要展現(xiàn)的內(nèi)容為一個圖片或多個圖片,點擊圖片可以跳轉(zhuǎn)相應(yīng)的鏈接。但是專題可能需要變化,則這里可以添加一個config或edit模式來讓管理員通過配置參數(shù)來定制。

    2、如首頁的新聞欄目,設(shè)計時是展現(xiàn)的A欄目,但是實際中用戶可能有變化,需要換成其他欄目,同樣可以通過可配置portlet來滿足。

    3、如提供RSS訂閱,我們可以在配置項里面設(shè)置RSS的輸出方法為標(biāo)題或者是摘要或者是全文,標(biāo)準(zhǔn)可以為atom或者rss2.0等配置。

    4、如有一個指標(biāo)展現(xiàn),用戶需求為可定制的,用戶A可以選擇柱狀圖、用戶B可以選擇折線圖、用戶C可以選擇餅圖等。

    包括但不限于以上場景,需要通過配置來適用不同的情況,為用戶提供可配置選項的地方都可以使用可配置portlet。

    可配置portlet的開發(fā)方式

    可配置portlet的開發(fā)方式,我按數(shù)據(jù)的存儲方式的不同,大概的分為兩種。一種為使用PortletPreferences存儲的,一種為自定義數(shù)據(jù)表結(jié)構(gòu)存儲的。

    使用PortletPreferences存儲的方式為將配置數(shù)據(jù)以鍵值對的形式存儲于PortletPreferences的相關(guān)屬性字段里面。以portlet的實例ID做為識別進(jìn)行存儲信息,適用于配置信息不算太復(fù)雜的場景。

    如果配置信息比較復(fù)雜,推薦建立相關(guān)的數(shù)據(jù)庫,將配置信息存儲于數(shù)據(jù)庫中。本文主要介紹存儲于PortletPreferences中的方法,存儲于數(shù)據(jù)庫和普通的portlet的數(shù)據(jù)存儲方法類似。

    如果按模式的不同,又可以分為edit、config、help等不同的模式。這些對應(yīng)于建立portlet時選用的modes的不同而不同,這里主要介紹config模式。其他模式類似。

    使用Config模式

    1、需要有一個建立好的portlet。portlet的創(chuàng)建,參考前面的portlet簡述:http://www.huqiwen.com/2012/09/03/liferay-6-1-development-study-3-portlet-explicate/

    2、在Liferay-portlet.xml里面找到此portlet的相關(guān)配置,在里面添加configuration-action-class元素,如下:

    <portlet><portlet-name>customjspportlet</portlet-name><icon>/icon.png</icon><configuration-action-class>xx.xxx.xxx.customjspportlet.CustomJspConfigurationAction</configuration-action-class><instanceable>true</instanceable><header-portlet-css>/css/main.css</header-portlet-css><footer-portlet-javascript>/js/main.js</footer-portlet-javascript><css-class-wrapper>customjspportlet-portlet</css-class-wrapper></portlet>

    3、建立CustomJspConfigurationAction類,此類繼承自DefaultConfigurationAction即可。

    4、重寫其中的render方法。如下。

    public String render(PortletConfig portletConfig, RenderRequest renderRequest, RenderResponse renderResponse){ String portletId = renderRequest.getParameter("portletResource");PortletPreferences preferences = PortletPreferencesFactoryUtil.getPortletSetup(renderRequest, portletId); renderRequest.setAttribute("customjspConfig_page_title",preferences.getValue("customjspConfig_page_title", StringPool.BLANK));renderRequest.setAttribute("customjspConfig_page_link",preferences.getValue("customjspConfig_page_link", StringPool.BLANK)); return "/html/CustomJspPortlet/config.jsp"; }

    這個方法是點擊portlet中的配置時進(jìn)入的方法。在這個方法里面做以下幾件事情。

    1):我們獲取到了當(dāng)前portlet的PortletPreferences。

    2):從PortletPreferences里面獲取key為customjspConfig_page_title和customjspConfig_page_link的數(shù)據(jù),并將他們放到request里面。

    3):告訴Liferay我的配置頁的JSP的路徑是哪個。

    5、編寫config.jsp頁面。config.jsp頁面里面是我們要配置的一此參數(shù)信息,大部分情況下是一個展現(xiàn)的表單。主要內(nèi)容可以參考如下(從項目中截取的部分代碼,為說明問題已經(jīng)簡化):

    <form action="<liferay-portlet:actionURL portletConfiguration="true" />" name="<portlet:namespace />fm" id="<portlet:namespace />fm" method="post"> <ul><li><span>標(biāo)題:</span><input tabindex="1" type="text" name="<portlet:namespace />customjspConfig_page_title" id="<portlet:namespace />customjspConfig_page_title" value="<%=title%>" /></li><li><span>鏈接地址:</span><input id='<portlet:namespace />custom_page_link' name='<portlet:namespace />customjspConfig_page_link' type="text" value="<%=link %>" /> </li><li><input type="button" value="" οnclick="<portlet:namespace />saveConfig()"></li> </ul> </form>

    這里的關(guān)鍵點為form的action,所有這種模式的可配置portlet的action都可以固定為:<liferay-portlet:actionURL portletConfiguration="true" />。

    6、服務(wù)端保存配置信息的處理。步驟5中的action會進(jìn)入步驟3建立的配置類的processAction方法。在上面的配置類里重寫processAction方法。里面的內(nèi)容如下:

    public void processAction(PortletConfig portletConfig, ActionRequest actionRequest, ActionResponse actionResponse)throws Exception {String portletResource = ParamUtil.getString(actionRequest, "portletResource"); PortletPreferences preferences = PortletPreferencesFactoryUtil.getPortletSetup(actionRequest, portletResource); if (Validator.isNotNull(preferences)) { //從request里面取數(shù)據(jù)String title = ParamUtil.getString(actionRequest, "customjspConfig_page_title");String link = ParamUtil.getString(actionRequest, "customjspConfig_page_link"); //將數(shù)據(jù)以鍵值對的形式填充到preferences里面preferences.setValue("customjspConfig_page_title", title);preferences.setValue("customjspConfig_page_link", link); //存儲數(shù)據(jù)到數(shù)據(jù)庫中,持久化數(shù)據(jù)preferences.store();SessionMessages.add(actionRequest, "success");}super.processAction(portletConfig, actionRequest, actionResponse);}

    到這里已經(jīng)完成了可配置portlet的配置部分的開發(fā)。

    在view.jsp中使用配置數(shù)據(jù)

    前面步驟開發(fā)的配置數(shù)據(jù)的目標(biāo)是為了在view.jsp中使用,在view.jsp中使用可以在view.jsp的action中使用,也可以直接在view.jsp中直接提取,方法為:

    PortletPreferences preferences = renderRequest.getPreferences();String title = preferences.getValue("customjspConfig_page_title", StringPool.BLANK);String link = preferences.getValue("customjspConfig_page_link", StringPool.BLANK);

    通過這樣的方法即可取到前面的配置信息,取取的數(shù)據(jù)具體怎么展現(xiàn),怎么使用,根據(jù)不同的業(yè)務(wù)場景有所不同。


    總結(jié)

    以上是生活随笔為你收集整理的Liferay开发学习(1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    亚洲区精品视频 | av网址aaa | 精品视频99 | 中文字幕 国产 一区 | 四虎影视成人精品国库在线观看 | 色综合久久综合中文综合网 | 久久精品99国产国产精 | 四虎成人精品永久免费av九九 | 欧美一区二区精品在线 | 一区二区三区久久精品 | 欧美日韩一区二区三区在线免费观看 | 免费日韩电影 | 欧美性护士 | 久久狠狠一本精品综合网 | 欧美日韩免费在线视频 | 三上悠亚一区二区在线观看 | 久久久久久久久久久久电影 | 亚洲欧洲精品一区二区精品久久久 | 一区二区三区免费在线 | 丁五月婷婷 | 在线观看视频国产 | 成人国产精品av | 91av国产视频 | 日韩精品极品视频 | 免费男女羞羞的视频网站中文字幕 | 国内精品久久久久久久久久清纯 | 亚洲精品网址在线观看 | 91视频观看免费 | av解说在线 | 国内久久久久 | www黄| 免费色视频在线 | 中文字幕日韩在线播放 | 日韩激情三级 | 在线日韩中文字幕 | 久久国产美女视频 | 亚洲最新av网址 | 国产成人精品免费在线观看 | 欧美日韩国产网站 | 在线观看国产一区二区 | 日本三级国产 | 狠色狠色综合久久 | 黄色毛片视频免费观看中文 | 欧美久久精品 | 日韩中文字 | 香蕉久草 | 麻豆免费观看视频 | 亚洲精品久久激情国产片 | 国产精品一区在线播放 | 免费亚洲成人 | 免费看v片网站 | 国产99久久九九精品免费 | 四虎8848免费高清在线观看 | 一级黄色大片 | 久99视频 | 国产精品成人久久久久久久 | 国产露脸91国语对白 | 中文字幕精品一区久久久久 | 亚洲欧美va | 欧美日bb| 久久激情综合网 | 亚洲伊人网在线观看 | 人人澡人人添人人爽一区二区 | 成人毛片在线观看 | 久久国产欧美日韩精品 | 国产一级免费片 | www.玖玖玖| 91精品久久久久久综合五月天 | 黄色视屏在线免费观看 | www.五月天色 | 久久最新网址 | 中文字幕视频一区二区 | 免费黄av | 久久亚洲专区 | 久久激情婷婷 | 国产精品成人免费 | 欧美一级免费片 | 欧美日韩中文另类 | 亚洲另类视频 | 青春草免费视频 | 亚洲成人免费在线观看 | 日韩精品视频免费在线观看 | 在线观看av不卡 | 日本最新中文字幕 | 精品一区二区三区香蕉蜜桃 | 亚洲国产精品99久久久久久久久 | 黄色大片免费播放 | 婷婷去俺也去六月色 | 亚洲成人免费 | 久久99在线 | 久久国产精品99久久久久 | 黄网站污 | 特级毛片aaa | 91av九色| 91精品办公室少妇高潮对白 | 91精品久久久久久久久久入口 | 天天操综 | 免费视频区 | 欧美a在线免费观看 | 国产精品久久在线观看 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 精品国产伦一区二区三区免费 | 天天摸天天干天天操天天射 | 五月天激情电影 | 久久性生活片 | 黄色成人av网址 | 国产成人高清在线 | 免费观看成人av | 久久精品91久久久久久再现 | 午夜久操 | 亚洲精品视频在线观看网站 | 精品视频久久 | 麻豆视频91| 欧美视频不卡 | 欧美性生活小视频 | 色香蕉网 | 免费av观看网站 | 狠狠干综合 | 一区二区三区免费在线观看视频 | 高清在线一区二区 | 在线国产一区 | 亚洲第一区在线播放 | 97国产人人| 免费h精品视频在线播放 | 久久久久久中文字幕 | 亚洲精品综合欧美二区变态 | www欧美日韩 | 超碰久热 | 国产伦精品一区二区三区照片91 | 在线观看涩涩 | 久久黄视频 | 香蕉视频在线免费 | www.成人久久 | 91激情视频在线 | 国产在线中文 | 奇米影视四色8888 | 久久草av | 不卡的av在线播放 | 亚洲电影一级黄 | a黄色一级 | 亚洲精品久久视频 | 99麻豆久久久国产精品免费 | 欧美成人黄色 | 99这里精品 | 91精品国产自产在线观看永久 | 在线韩国电影免费观影完整版 | 在线91av | 亚洲免费a | 午夜国产福利在线观看 | 三级av免费| 日韩午夜电影网 | 国产视频在线观看一区 | 一本—道久久a久久精品蜜桃 | 日日日天天天 | av在线一级 | 亚洲最新精品 | 伊人国产女 | 国产精品午夜在线 | 亚洲精品国产精品国自产观看 | 三级av小说 | 黄网站污| 日三级在线 | 欧美视频在线二区 | 最近中文字幕在线中文高清版 | 日p视频 | 欧美日韩精品区 | 久久久久久久久影院 | 欧美日韩不卡一区二区三区 | 天天av综合网| 激情婷婷丁香 | 免费男女网站 | 成人毛片在线视频 | 天天搞天天干 | 黄色aaa级片 | 涩涩网站在线观看 | 成人免费色 | 欧美久久久久 | 99精品国产福利在线观看免费 | 福利片免费看 | 69国产成人综合久久精品欧美 | 亚洲成色 | 久久久久久久久久电影 | 精品国产乱码久久久久久久 | 国产精品久久久久久久久久久久 | 欧美日韩aa| 国产精品视频永久免费播放 | 在线观看成人一级片 | 有码中文字幕在线观看 | 亚洲精品国产拍在线 | 96久久欧美麻豆网站 | 日韩毛片在线一区二区毛片 | 成人a级黄色片 | 91禁在线看 | 天天爱av导航 | 亚洲国产精品成人va在线观看 | 五月天婷婷综合 | 久久久久久久久免费视频 | 中文电影网| 人成在线免费视频 | 国产不卡视频在线 | 亚洲天天摸日日摸天天欢 | 国产精品欧美久久久久久 | 精品国产视频在线 | 欧美一二区视频 | av久久久久久| 日本久久久久久 | 草樱av| 久久久久久久99精品免费观看 | 国产精品毛片一区二区三区 | 不卡视频国产 | 91av资源网| 丁香激情五月 | 欧美 亚洲 另类 激情 另类 | 婷婷去俺也去六月色 | 久久久久亚洲精品成人网小说 | 成人一区二区三区在线 | 日韩免费区 | 国产又粗又猛又爽 | 99精品在线免费在线观看 | 天天操夜夜拍 | 久久久久久综合 | 很污的网站 | 麻豆影视在线观看 | 日韩国产精品一区 | 亚洲涩涩网 | 久久综合免费视频 | 在线观看视频亚洲 | 亚洲精品在线资源 | 麻豆国产网站入口 | 中文在线字幕免费观看 | 激情综合六月 | 国产精品av电影 | 最新av在线网站 | 欧美激精品 | 亚洲免费高清视频 | 人九九精品 | 色婷婷精品大在线视频 | 国产精品免费大片视频 | 麻豆传媒在线免费看 | av免费在线免费观看 | 久久久久成人精品免费播放动漫 | 一区二区三区免费网站 | 精品99在线视频 | 国产成人精品久久亚洲高清不卡 | 97日日| 999成人免费视频 | 开心激情婷婷 | 欧美视屏一区二区 | 中文字幕中文 | 国产免费看 | 亚洲乱码久久久 | 在线观看aaa | 国产精品一区二区在线免费观看 | 久久99精品久久久久久三级 | 久草视频99 | 爱干视频 | 99久在线精品99re8热视频 | 精品色999 | 日韩成人中文字幕 | 成人资源网 | 天天干天天干天天干天天干天天干天天干 | 激情婷婷在线观看 | 久久久久一区二区三区四区 | 国产美女主播精品一区二区三区 | 国产精品精品久久久 | 日韩成人精品在线观看 | 亚洲精品久久久久www | 黄色成人在线 | japanesexxxhd奶水 91在线精品一区二区 | 一区二区视频在线播放 | 中文字幕亚洲精品日韩 | 五月婷香 | 中文字幕视频一区 | 日韩欧美视频免费在线观看 | 欧美成人999 | 欧美日韩成人 | 国产91在线免费视频 | 亚洲午夜久久久久久久久 | 国产精品嫩草55av | 97香蕉久久国产在线观看 | 涩涩网站在线观看 | 国产精品久久久久一区二区三区共 | 国产资源在线播放 | 91亚洲精品乱码久久久久久蜜桃 | 日本特黄一级片 | 91精品国产麻豆国产自产影视 | 久久精视频 | 久久免费精品一区二区三区 | 国产精品免费麻豆入口 | 久久九九影视 | 夜夜躁狠狠躁日日躁视频黑人 | 五月导航 | 精品伦理一区二区三区 | 九九免费观看全部免费视频 | 亚洲理论在线观看电影 | 国产精品毛片一区二区 | 免费观看一级视频 | 国内视频1区 | 日韩精品中文字幕有码 | 久草精品视频 | 久久久久免费精品国产小说色大师 | 天天射天天舔天天干 | 国产97在线观看 | 在线日韩中文 | 国产护士hd高朝护士1 | 色婷婷av一区二 | 国产福利精品视频 | 国产高清在线一区 | 国产成人免费在线观看 | 国产手机在线 | 国产涩涩在线观看 | 视频国产区 | 亚洲精品视频在线播放 | www.久艹| 午夜久久视频 | 天天干天天摸 | 色婷婷国产 | 久久久精品久久 | 麻豆精品传媒视频 | 99 精品 在线| 国产精品免费在线观看视频 | 国产成人精品免费在线观看 | 日韩精品最新在线观看 | 日韩精品一区二区三区视频播放 | 色偷偷网站视频 | 亚洲传媒在线 | 91精品国产欧美一区二区成人 | 午夜久久视频 | 亚洲最新av网站 | 免费看色的网站 | 91精品久久久久 | 菠萝菠萝在线精品视频 | 亚洲人久久久 | 99免在线观看免费视频高清 | 99在线精品免费视频九九视 | 国产999精品久久久久久绿帽 | 成人av免费在线播放 | 欧美夫妻性生活电影 | 一区二区精品在线视频 | 国产在线毛片 | 成人在线观看资源 | 网站你懂的 | 国产视频在线观看一区 | 婷婷中文字幕在线观看 | 亚洲高清精品在线 | 国产在线看一区 | 99精品国产免费久久久久久下载 | av片一区 | 久久字幕网 | 欧美日韩国产在线观看 | www.综合网.com | 国产日本在线播放 | 国产成人三级在线播放 | 天天艹天天干天天 | 亚洲成a人片在线观看中文 中文字幕在线视频第一页 狠狠色丁香婷婷综合 | 免费观看完整版无人区 | 久草视频在线播放 | 久久精品国产免费看久久精品 | 91av99| 国产香蕉视频在线播放 | 天天操天天舔天天干 | 最近免费观看的电影完整版 | 欧美在线观看视频一区二区 | 免费男女羞羞的视频网站中文字幕 | www.色午夜.com| 黄污网站在线 | 久久久久免费网站 | 亚洲午夜久久久久久久久久久 | 丁香婷婷自拍 | 99久久99久国产黄毛片 | 91成人在线观看高潮 | 夜夜躁日日躁 | 国产人成免费视频 | 91一区二区三区在线观看 | av免费黄色 | 国产在线小视频 | 久久成人人人人精品欧 | 久草影视在线观看 | 人人爱天天操 | 久久精品一区二区 | 色欧美成人精品a∨在线观看 | 日韩欧美在线影院 | 午夜视频免费在线观看 | aaa日本高清在线播放免费观看 | 在线精品播放 | 久久久噜噜噜久久久 | 黄色av网站在线免费观看 | 中文字幕视频 | 人人爽人人片 | 日本久久视频 | 中文字幕一区二区三区乱码在线 | 狠狠色丁香久久婷婷综 | 91麻豆国产福利在线观看 | 免费黄色a级毛片 | 日韩最新中文字幕 | 日本在线观看中文字幕 | 亚洲狠狠婷婷综合久久久 | 天天干天天拍天天操天天拍 | 在线观看视频97 | 91精品啪在线观看国产线免费 | 黄色大片日本 | 国产黄在线看 | 亚洲午夜精品在线观看 | 六月激情婷婷 | 这里有精品在线视频 | 五月婷婷香蕉 | 欧美激情精品久久久 | 久久视频网址 | 久久草视频 | 日韩一级理论片 | 日日摸日日添夜夜爽97 | 波多野结衣亚洲一区二区 | 五月婷婷av| 在线亚洲小视频 | 中文字幕一区二区三区在线播放 | 国产二区视频在线 | 国产激情小视频在线观看 | 成人性生交大片免费看中文网站 | 天天干,天天射,天天操,天天摸 | 久草精品视频在线观看 | 欧美精品中文在线免费观看 | 国产一区二区精品久久91 | 国产麻豆电影在线观看 | 日韩在线三级 | 国产精品99爱 | 中午字幕在线 | 伊人视频 | 久久久国产精品电影 | 亚洲精品综合欧美二区变态 | 久久久精品视频网站 | 亚洲国产成人精品久久 | 亚洲国产美女精品久久久久∴ | 免费视频久久久久久久 | 久久午夜国产 | 黄色午夜| 日韩欧美极品 | 狠狠干成人 | 在线观看一区视频 | 久久久久久久久久久久国产精品 | adc在线观看 | 91精品欧美一区二区三区 | 国产一二三在线视频 | 在线观看av小说 | 8x成人在线 | 中文字幕人成乱码在线观看 | 久久久av电影 | 日韩av影片在线观看 | 日日干天天 | 狠狠色伊人亚洲综合网站色 | 国产高清无线码2021 | 成片视频在线观看 | 天天av天天 | 欧美色888 | 国产成人三级在线观看 | 日日夜夜网站 | 久久久久久久综合色一本 | 在线视频 成人 | 超碰官网 | 天天色天天色 | 婷婷九月丁香 | www.人人干 | 丁香色婷 | 中文字幕亚洲情99在线 | 丝袜美女视频网站 | 大荫蒂欧美视频另类xxxx | 日韩电影在线观看一区二区 | 免费的国产精品 | 日韩av一区二区三区在线观看 | 在线播放亚洲激情 | 精品电影一区 | 亚洲视频一区二区三区在线观看 | 日韩免费三级 | 99精品国产aⅴ | 色婷婷六月| 国产视频首页 | 日本精品视频在线播放 | 国产专区第一页 | 久久私人影院 | 在线日韩一区 | 国产高清精 | 久久久18 | 久久久精品视频网站 | 亚洲无吗视频在线 | 98超碰在线 | 国产一二区精品 | 韩国av免费在线观看 | 国产一级精品在线观看 | 成人网色 | 在线免费观看国产视频 | 国产小视频国产精品 | 麻豆免费在线播放 | 黄色片网站av | 国产精品高清在线 | 欧美日韩国产欧美 | 天天操狠狠操夜夜操 | 亚洲丝袜一区二区 | 免费成人在线视频网站 | 日韩av电影免费在线观看 | 国产精品一区二区免费 | 人人澡澡人人 | 久久久久久久99精品免费观看 | 国产中文 | 最新日韩在线观看视频 | 日日操日日干 | 国色综合| 成人v| 中文字幕一二 | 国产小视频精品 | 很黄很黄的网站免费的 | 99久久精品免费看国产四区 | 天天摸夜夜添 | 欧美成人a在线 | 久久久久久黄色 | 日韩精品一区二区三区第95 | av在线a| 久久电影中文字幕视频 | 日日干天天插 | 贫乳av女优大全 | 夜夜骑日日操 | 婷婷视频在线播放 | 久久精品综合视频 | 色狠狠综合天天综合综合 | av网站有哪些 | 91中文字幕在线观看 | 狠狠狠的干 | 日韩大陆欧美高清视频区 | 久久99精品久久久久久秒播蜜臀 | 激情网婷婷 | 黄色影院在线免费观看 | 免费91在线| 黄毛片在线观看 | 亚洲精品视频在线观看免费视频 | 亚洲黄色在线看 | 国产精品自产拍在线观看 | 日本精品视频在线观看 | 九色91在线视频 | 久99久在线视频 | 国产精久久久久久久 | 国产亲近乱来精品 | 亚洲一级特黄 | 在线观看成年人 | 久久夜色精品国产欧美一区麻豆 | 狠狠狠色狠狠色综合 | 免费热情视频 | 视频99爱 | 中文字幕在线播放视频 | 日操操| 99视频在线免费观看 | 亚洲春色综合另类校园电影 | 国产一级片播放 | 99视频在线看 | 9999激情| 久草在线视频新 | 久久国产美女 | 国产一区二区三区黄 | 99久久国产免费看 | av久久久 | 午夜性生活 | 夜夜操天天操 | 狠狠色香婷婷久久亚洲精品 | 日韩欧美精品一区 | 久久精品一区二区国产 | 久久这里有精品 | 日韩区欠美精品av视频 | 99视频久久 | 亚洲黄色影院 | 欧美日韩大片在线观看 | 日本精品久久久一区二区三区 | 国产精品视频在线观看 | 亚洲精品成人av在线 | 国产 亚洲 欧美 在线 | 亚洲一区二区三区miaa149 | 伊香蕉大综综综合久久啪 | 成年人天堂com | 韩国av免费在线 | 欧美激情第八页 | 久草网在线视频 | 黄色一级大片在线免费看国产一 | 欧美日韩不卡一区 | 91视频在线观看大全 | 超碰在线最新地址 | 91超在线 | 国产精品2区 | 国产精品美女久久久久久2018 | 狠狠干网址 | 91精品国产电影 | 91成人在线观看高潮 | 伊人中文网 | 亚洲黄色在线观看 | 97久久精品午夜一区二区 | 碰超在线97人人 | 欧美孕妇与黑人孕交 | 国产91精品高清一区二区三区 | 久久久国产电影 | 色偷偷88888欧美精品久久 | 久久av在线 | 亚洲精品国偷自产在线91正片 | 婷婷亚洲激情 | 天天干,天天草 | 免费a网 | 午夜影视剧场 | 国产91精品在线观看 | av线上免费观看 | a天堂最新版中文在线地址 久久99久久精品国产 | 欧美日韩一区二区三区视频 | 欧美成人理伦片 | 亚洲精品午夜国产va久久成人 | 在线黄色国产电影 | 天天插天天射 | av在线小说 | 国产精品都在这里 | 超碰97在线资源站 | 亚洲成人资源在线 | 91日韩在线专区 | 国产精品99久久久久人中文网介绍 | 91chinesexxx| 97色婷婷 | 天天综合视频在线观看 | 国产一级在线播放 | 天天夜夜亚洲 | 亚洲人成在 | 91九色在线观看 | 99综合电影在线视频 | 精品免费 | 人人爽人人爽人人片av免 | 在线直播av | 美女av免费看 | 一区二区视频播放 | 欧美国产精品久久久久久免费 | 亚洲精品www. | 精品视频不卡 | 成人免费看视频 | 在线成人一区 | 97色噜噜| 在线观看mv的中文字幕网站 | 日韩精品免费在线视频 | 国产精品v欧美精品v日韩 | 三日本三级少妇三级99 | 五月开心网| 99久久国产免费看 | 国产视频久久久久 | 精品国产资源 | 五月婷激情 | 伊人视频 | 激情av一区二区 | 中文字幕久久精品一区 | 中文字幕av有码 | 在线精品亚洲一区二区 | 少妇bbb搡bbbb搡bbbb | 天天干天天干天天干天天干天天干天天干 | 特级黄色视频毛片 | 日韩在线观看一区二区三区 | 国产淫片免费看 | 国产91九色视频 | 欧美黑人性猛交 | 国产精品免费人成网站 | 中文不卡视频在线 | 欧美久久久久久久久久 | 国产在线精品国自产拍影院 | 国产一级二级三级视频 | 成人av免费在线播放 | 欧美三级免费 | 超碰97人 | 中午字幕在线观看 | 亚洲女欲精品久久久久久久18 | 国产精品18久久久久久久久 | 成人性生爱a∨ | 人人爽人人舔 | 免费的成人av | 久久久久网站 | av电影av在线 | 国产一级91 | 18性欧美xxxⅹ性满足 | 婷婷开心久久网 | 91精品视频播放 | av在线免费在线观看 | 色免费在线 | 国产午夜麻豆影院在线观看 | 日韩精品一区二区三区视频播放 | 久久久免费av| 国产一区二区影院 | 亚洲欧美日韩一二三区 | 亚洲精品乱码久久久久久写真 | 国产视频二 | 欧美成人视 | 在线观看午夜av | 久久久久亚洲精品成人网小说 | 成人久久18免费网站图片 | 久久天天躁夜夜躁狠狠85麻豆 | 97品白浆高清久久久久久 | 一区二区三区四区精品视频 | 视频一区二区精品 | 久久精品视频2 | 国产伦精品一区二区三区无广告 | 精品99在线| 欧美色噜噜噜 | 天天操天天弄 | 福利片免费看 | 午夜视频在线观看一区二区三区 | 久久久久久久99精品免费观看 | 96精品高清视频在线观看软件特色 | 久草精品视频在线播放 | 福利视频精品 | 亚洲精品美女免费 | 亚洲天堂网在线视频观看 | 狠狠干狠狠色 | 亚洲精品黄色 | av高清免费在线 | 去看片| 国产精品久久久久aaaa九色 | 国产va在线观看免费 | 福利久久久 | 国产电影一区二区三区四区 | 特级a老妇做爰全过程 | 二区精品视频 | 国产精品日韩精品 | 久久久污 | 婷婷在线色 | 一区二区三区影院 | 99精品在线直播 | 99久久99久久综合 | 免费福利视频网 | 97超碰人人在线 | 国产三级国产精品国产专区50 | 99久免费精品视频在线观看 | 成人免费在线电影 | 99精品国产一区二区三区麻豆 | 欧美91视频 | 日韩精品免费在线观看视频 | 亚洲女欲精品久久久久久久18 | 亚洲精品乱码久久久久久蜜桃动漫 | 久久综合中文色婷婷 | 久久国产精品一国产精品 | 精品99免费视频 | 国产精品一区免费在线观看 | 超碰99人人 | 欧美视频网址 | av网站播放| 国产精品青草综合久久久久99 | 日韩美av在线 | 99久高清在线观看视频99精品热在线观看视频 | 久草视频在线免费看 | 在线观看国产高清视频 | 69国产盗摄一区二区三区五区 | 日本在线观看一区 | 91激情视频在线 | 日韩一二区在线观看 | 在线国产不卡 | 久久精品婷婷 | 91亚洲精品久久久蜜桃网站 | 国产精品美女视频 | 天天射天天搞 | 成人国产精品久久久久久亚洲 | www久久久久 | 日韩精品久久久久久久电影竹菊 | 日韩欧美在线观看一区 | 精品国产一区二区三区久久久蜜月 | 国产在线高清视频 | 超碰人人做 | 久久新| 丁香婷婷综合五月 | 美女视频黄的免费的 | 亚洲va欧美 | 91亚洲欧美| 在线 视频 亚洲 | 美女福利视频网 | 日韩中文字幕视频在线观看 | 国产一区在线免费观看 | 国产精品毛片一区二区 | 麻豆视频观看 | 500部大龄熟乱视频使用方法 | 在线观看亚洲免费视频 | 欧美一级特黄高清视频 | 免费精品在线 | 91丨九色丨91啦蝌蚪老版 | 丁香婷婷激情国产高清秒播 | 九九精品视频在线看 | 手机看国产毛片 | av黄色在线| 久久福利国产 | 一本—道久久a久久精品蜜桃 | 精品国产电影一区二区 | 亚洲欧美日韩一区二区三区在线观看 | 精品视频国产 | 欧美精品在线观看免费 | 免费av在线播放 | 国产黄色精品 | 国产日韩精品久久 | 国产精品免费观看网站 | 国产精品久久久久永久免费观看 | 成人久久毛片 | 天天天天天天操 | 97综合在线 | 91亚洲成人 | 天天操夜夜拍 | 久久精品99国产精品亚洲最刺激 | 久99久中文字幕在线 | 亚洲成人av片在线观看 | 伊人五月天 | 国产麻豆果冻传媒在线观看 | 久久在线免费视频 | 色婷婷综合久久久久 | 一级电影免费在线观看 | 色婷婷狠狠18 | 99精品国产一区二区 | 国产黄色片在线免费观看 | 狠狠婷婷| 欧洲一区精品 | 不卡视频一区二区三区 | 婷婷激情影院 | 日韩欧美精品免费 | 超碰成人av | 在线观看免费日韩 | 国产精品 日韩 | 亚洲影视九九影院在线观看 | 国产精品 中文字幕 亚洲 欧美 | 91精品国产自产老师啪 | 日日干天天干 | 久热色超碰| 午夜精品一区二区三区在线视频 | 国产成人免费观看久久久 | 国产五十路毛片 | 久草网站 | 国产日韩一区在线 | 少妇bbb| 五月婷婷丁香综合 | 在线v片免费观看视频 | 国产精品视频免费 | 最新精品国产 | 丰满少妇在线 | 国产色 在线 | 激情喷水 | 精品女同一区二区三区在线观看 | 欧美极品裸体 | 在线免费观看视频 | 成人av免费在线观看 | 亚洲欧洲精品一区二区精品久久久 | 国产精品一区二区三区在线 | 天天天操天天天干 | 国产精品高清av | 国产色视频网站 | 色综合 久久精品 | 久人人| 日韩在线视频国产 | 欧美日韩国产二区 | 久久久国产在线视频 | 91av大全| 懂色av一区二区三区蜜臀 | 国产成人免费在线 | 在线激情av电影 | 免费福利在线观看 | 天天插狠狠干 | 亚洲视频在线免费观看 | 日韩免费看视频 | 精品久久91 | 超碰人人在 | 国产精品久久影院 | 国产网站在线免费观看 | 97操操 | 91麻豆福利| 日本aaa在线观看 | 99超碰在线观看 | 欧美精品久久久 | 国产精品一区二区视频 | www91在线观看 | 亚洲视频在线观看网站 | 亚洲伦理一区 | 99精品国产兔费观看久久99 | 欧美va电影| 中文字幕大全 | 亚洲毛片一区二区三区 | 日韩美在线观看 | 亚洲永久免费av | 亚洲国产网址 | 久久特级毛片 | 久久www免费人成看片高清 | 免费在线观看日韩欧美 | 亚洲一二视频 | 亚洲在线视频播放 | 菠萝菠萝蜜在线播放 | 成年人天堂com | 国产在线视频一区二区三区 | 麻豆精品国产传媒 | 日日躁夜夜躁xxxxaaaa | 亚洲成人黄色网址 | 在线 国产一区 | 婷婷www| 精品在线99 | 日韩电影一区二区三区在线观看 | 国产成人av网址 | 日本韩国欧美在线观看 | 伊人影院在线观看 | 国产区在线看 | 国产成人免费网站 | 国产精品一区二区久久久久 | 特级黄色电影 | 国产精品区一区 | 国产最新在线 | 最近中文字幕大全中文字幕免费 | 国产精品久久久久久久久久久免费看 | 国产精品综合在线观看 | 婷婷综合导航 | 91免费高清在线观看 | 精品国产一区二区三区在线观看 | 一级黄色大片 | 中文av在线播放 | 粉嫩av一区二区三区免费 | 国产麻豆精品一区二区 | 欧美激情另类 | 国产中文字幕av | 在线直播av | 精品夜夜嗨av一区二区三区 | 亚洲精品色视频 | 国产一级特黄电影 | 国产 av 日韩| 91av在线播放 | 国产精品美女免费看 | 摸bbb搡bbb搡bbbb | 亚洲精品免费视频 | 日韩二区在线观看 | 久久久麻豆精品一区二区 | 日韩理论电影网 | 极品久久久久久久 | 在线国产激情视频 | 97看片吧 | 午夜精品久久久久久99热明星 | www.狠狠插.com | 日韩精品91偷拍在线观看 | 国内精品久久久久久久影视简单 | 天天爽天天爽夜夜爽 | 色午夜| 九九久久久久久久久激情 | 久草a在线 | 中文字幕 婷婷 | 成人午夜剧场在线观看 | 亚洲免费在线播放视频 | 国产精品麻豆91 | 久久精国产 | 欧美大码xxxx | 中文字幕资源网在线观看 | 麻豆果冻剧传媒在线播放 | 亚洲精品乱码久久久久久久久久 | 91高清视频免费 | 中文字幕在线观看你懂的 | 99视频99| 中文av网| 亚洲国产无 | 国产一区二区三区四区大秀 | 欧美日韩国产欧美 | 国产又粗又硬又爽视频 | 国产精品18久久久久久久 | 一区二区三区韩国免费中文网站 | 亚洲专区视频在线观看 | 91视频免费播放 | 日韩国产精品一区 | 久久涩视频 | 婷婷在线网站 | av成人在线电影 | 99r在线| 久久综合99 | 草久视频在线观看 | 日韩美一区二区三区 | 日韩理论片在线观看 | 日韩av在线高清 | 国产96精品 | 国产黄色一级片 | www.久久久com | 爱情影院aqdy鲁丝片二区 | 高潮久久久久久 | 午夜在线观看影院 | 中文字幕av在线电影 | 狠狠操操| 高清av网站| 韩日精品中文字幕 | 日韩精品黄 | 久久国产手机看片 | 日日夜夜婷婷 | 久久成人免费电影 | 天天操天天操天天 | 91成人在线视频 | 免费看一级特黄a大片 | 91视频com| 91久久久国产精品 | 91精品国产99久久久久久久 | 精品久久影院 | 国产视频精品久久 | 国产日韩精品一区二区在线观看播放 | 亚洲专区在线视频 | 九九视频精品免费 | 五月天婷婷在线播放 | 91av免费看| 欧美最猛性xxxx | 最新日韩中文字幕 | 亚洲国产一区二区精品专区 | 国产黄色片在线 | 精品亚洲免a | 中文字幕 国产精品 | 五月天天av |