欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Jive的其他組件技術(shù)

5  Jive的其他組件技術(shù)

Jive是一個(gè)比較豐富的知識寶藏,從中可以學(xué)習到很多新的實(shí)戰技巧和具體功能實(shí)現方式。前面基本介紹了Jive中的一些主要架構技術(shù),通過(guò)這些技術(shù)可以基本上掌握Jive論壇系統。

Jive中還有很多非常實(shí)用的組件技術(shù)和工具庫,分析學(xué)習可重用技術(shù),可以在自己具體的項目重復使用,大大提高了新系統的開(kāi)發(fā)速度和效率。

Jive的管理功能中提供了將Jive數據庫數據導出到XML文件的管理工具,在這個(gè)工具功能實(shí)現中,使用了樹(shù)形結構的遍歷技術(shù)。

JiveForumThread中的第一個(gè)ForumMessage作為root ForumMessage,以這個(gè)ForumMessage為根節點(diǎn),每個(gè)ForumThread中包含了一套樹(shù)形結構。

TreeWalker是樹(shù)形結構的一個(gè)抽象接口,代碼如下:

public interface TreeWalker {

    //根節點(diǎn)

    public ForumMessagegetRoot();

    //獲得父節點(diǎn)

    public ForumMessagegetParent(ForumMessage child)

            throwsForumMessageNotFoundException;

    //獲得子節點(diǎn)

    public ForumMessagegetChild(ForumMessage parent, int index)

            throwsForumMessageNotFoundException;

    //獲得所有子節點(diǎn)

    public Iteratorchildren(ForumMessage parent);

    //獲得所有的子節點(diǎn),包括子節點(diǎn)的子節點(diǎn)

    public IteratorrecursiveChildren(ForumMessage parent);

    //獲得一個(gè)節點(diǎn)的深度,相對根節點(diǎn)而言

    public int getMessageDepth(ForumMessagemessage);

   

    public int getChildCount(ForumMessageparent);

    public int getRecursiveChildCount(ForumMessageparent);

 

    /**

     * 返回相對父節點(diǎn)的子節點(diǎn)索引。例如

     * <pre>

     *   4

     *   |--2

     *   |--|-- 1

     *   |--|-- 6

     *   |--|-- 8

     *   |--5

     * </pre>

     * getIndexOfChild(4,2) 將返回0

     * getIndexOfChild(4,5) 將返回1

     * getIndexOfChild(2,1) 將返回0

     * getIndexOfChild(2,6) 將返回1

     * getIndexOfChild(2,8) 將返回2

     */

    public int getIndexOfChild(ForumMessageparent, ForumMessage child);

    //一個(gè)節點(diǎn)是否是葉,葉相對枝來(lái)說(shuō),葉沒(méi)有子節點(diǎn)了

    public booleanisLeaf(ForumMessage node);

}

DbTreeWalker TreeWalker的一個(gè)實(shí)現,它是將一個(gè)ForumThread下所有帖子的ID從數據庫中裝入LongTree中。一句LongTree的樹(shù)形結構遍歷核心技術(shù)實(shí)現ForumThread中的帖子結構的遍歷。

LongTree類(lèi)似之前的Cache類(lèi),封裝了樹(shù)形結構遍歷的核心算法,在LongTree中建立了3個(gè)數組long[] keys、char[] leftChildrenchar[] rightSiblings。

一個(gè)節點(diǎn)有兩個(gè)特性:它有子節點(diǎn);它有兄弟節點(diǎn)。leftChildren保存的是這個(gè)節點(diǎn)的子節點(diǎn)的索引;而rightSiblings保存的是這個(gè)節點(diǎn)兄弟節點(diǎn)的索引。例如:

  1000

   |-- 3000

   |-- |--4000

   |-- |--6000

   |-- |--7000

   |-- 5000

1000是個(gè)根節點(diǎn),1000下有兩個(gè)子節點(diǎn)30005000,而3000則有3個(gè)子節點(diǎn)4000、60007000,3000還有一個(gè)兄弟節點(diǎn)5000,使用上述3個(gè)數組是這樣保持信息的:

keys[0] = 1000

keys[1] = 3000

keys[2] = 4000

keys[3] = 5000

keys[4] = 6000

keys[5] = 7000

keys數組中保存的是各個(gè)節點(diǎn)的數值,而leftChildrenrightSiblings數組保存的是keys數組的index,即0、1、2、3、4等數字。

1000節點(diǎn)有兩個(gè)子節點(diǎn),那么其對應的leftChildrenrightSiblings分別是:

leftChildren[0] = 1

leftChildren[0]中的索引0表示當前索引,keus[0]1000,說(shuō)明現在節點(diǎn)是1000;1也表示keys數組的索引,keys[1]的值是3000,所以上一句表示1000的子節點(diǎn)是3000。

1000節點(diǎn)沒(méi)有兄弟節點(diǎn):

rightSiblings[0] = -1

再看看3000節點(diǎn),其keys的索引Index1,其子節點(diǎn)是4000、60007000,取最近一個(gè)4000的索引index放入數組:

leftChildren[1] = 2

這表示1000節點(diǎn)的子節點(diǎn)是4000,那么另外一個(gè)6000節點(diǎn)如何表示?這是以4000節點(diǎn)的兄弟節點(diǎn)表現出來(lái)的。4000節點(diǎn)的keys的索引index2,通過(guò)下列表示:

rightSiblings[2] = 4

其中,4表示6000keys中的索引Index。同樣,第3個(gè)子節點(diǎn)7000表示如下:

rightSiblings[4] = 5

這樣,3000節點(diǎn)有3個(gè)子節點(diǎn)4000、600070004000、60007000是兄弟節點(diǎn))通過(guò)上述簡(jiǎn)單兩句就表現出來(lái)了。

總結一個(gè)父子關(guān)系樹(shù)的表示方法:在父節點(diǎn)中,使用leftChildren保存最靠近父節點(diǎn)的一個(gè)子節點(diǎn)(父節點(diǎn)的第一個(gè)兒子,叫長(cháng)子)的索引,其他子節點(diǎn)則是通過(guò)rightSiblings表明與長(cháng)子是兄弟關(guān)系。

看看LongTress的初始化構造方法,keys數組的值保存的是ForumMessageID,如下:

public LongTree(long rootKey,int size) {

    keys = new long[size+1];                        //初始化

    leftChildren= new char[size+1];               //初始化

    rightSiblings= new char[size+1];              //初始化

 

    // keys[1]中保存的是rootMessage ID

    keys[1] = rootKey;

    leftChildren[1]= 0;                                 //無(wú)子節點(diǎn)

    rightSiblings[1]= 0;                                 //無(wú)兄弟姐妹

}

當加入一個(gè)節點(diǎn)時(shí),其方法如下:

public void addChild(long parentKey,long newKey) {

    // 根據parentKey找出其對應的keys索引index

    char parentIndex= findKey(parentKey, (char)1);

    if (parentIndex== 0) {

            thrownew IllegalArgumentException("Parent key " +parentKey +

                    " notfound when adding child " + newKey + ".");

    }

 

    // newKey創(chuàng )建節點(diǎn)

    keys[nextIndex]= newKey;

    leftChildren[nextIndex]= 0;

    rightSiblings[nextIndex]= 0;

 

    //將新建節點(diǎn)標志為父節點(diǎn)的子節點(diǎn)

    if (leftChildren[parentIndex]== 0) {

        // 如果父節點(diǎn)原來(lái)沒(méi)有子節點(diǎn),那就將新建節點(diǎn)作為其子節點(diǎn)

        leftChildren[parentIndex]= nextIndex;

    }else {

        // 如果父節點(diǎn)有子節點(diǎn),尋找最后一個(gè)子節點(diǎn)

        longsiblingIndex = leftChildren[parentIndex];

       //siblingIndex中循環(huán)查找,直至值為0

        while(rightSiblings[new Long(siblingIndex).intValue()] != 0){

             siblingIndex= rightSiblings[new Long(siblingIndex).intValue()];

        }

        // 將新建節點(diǎn)作為最后一個(gè)字節點(diǎn)加入

        rightSiblings[newLong(siblingIndex).intValue()] = nextIndex;

    }

    // 最后,自動(dòng)增加nextIndex 以便下一個(gè)等待插入

    nextIndex++;

}

Jive將數據導出到XML文件時(shí),就是根據某個(gè)ForumMessageID,通過(guò)TreeWalker找出它的所有子節點(diǎn)ForumMessageID,然后將其內容導出。

5.2  XMLJDOM

XML 稱(chēng)為可擴充標記語(yǔ)言,是類(lèi)似HTML定義文檔標記語(yǔ)言的一個(gè)框架。XML以結構嚴謹著(zhù)稱(chēng),因此用來(lái)保存數據是非常適合的,這樣在數據庫之外,又多了一個(gè)持久化保存數據的方式。

Java中,XML更多時(shí)是作為配置文件數據存儲體形式出現,在之前一般是使用properties來(lái)保存系統的配置文件,如下:

cache.maxsize=1024

cache.minsize=2

這兩句分別設置cache的最大值和最小值,那么在Java中通過(guò)下列語(yǔ)句讀?。?/span>

Properties p = new Properties();

InputStream fin = new FileInputStream("Config.properties");

p.load(fin);

String maxSize = p.getProperty("cache.maxsize ");

String minSize = p.getProperty("cache.minsize ");

這樣就可以獲得配置文件中的兩個(gè)值。

這種配置文件使用方法簡(jiǎn)單直接,但是只適合配置文件不很復雜的情況。在復雜的配置情況下,properties就不是很合適,例如設置系統的可選屬性,一個(gè)系統安裝在不同應用場(chǎng)合,客戶(hù)的要求總有些不一樣,有些功能是可選的,那么需要在配置文件中配置一些可選的功能,以Tomcatserver.xml為例,如下:

<Context path="/register" docBase="D:/javasource/SimpleRegister/defaultroot" debug="1"

                 reloadable="true" crossContext="true">

</Context>

<Context path="/examples" docBase="examples" debug="0"

                 reloadable="true" crossContext="true">

          <LoggerclassName="org.apache.catalina.logger.FileLogger"

                     prefix="localhost_examples_log." suffix=".txt"

              timestamp="true"/>

</Context>

在一個(gè)配置中有很多Context,每個(gè)Contexr都包含Logger等具體配置,XML格式本身是一種樹(shù)形結構的數據格式。在實(shí)際應用中,很多復雜的表示都可以使用樹(shù)形結構來(lái)分解代表。因此,使用XML來(lái)表示這種樹(shù)形結構的數據無(wú)疑是非常合適的。

Jive中,jive_config.xmlJive系統的配置文件。這個(gè)配置文件是在Jive系統安裝時(shí),按照用戶(hù)的選擇動(dòng)態(tài)生成的,其中包含數據庫連接參數、界面顯示顏色、電子郵件配置以及緩沖配置、搜索配置和文件或圖片上傳配置。

分析讀取XML數據有很多工具,如DOMhttp://www.worg/DOM/)和SAXhttp://www.saxproject.org/)。這兩種是標準的XML分析器,可以使用任何語(yǔ)言來(lái)實(shí)現,DOM分析XML數據時(shí),是將整個(gè)文檔一下子讀入內存,如果文檔很大,性能就發(fā)生影響,而SAX則是動(dòng)態(tài)地對每一行分析,無(wú)需全部讀入,因此在分析大文檔時(shí)速度比較快。

但是這兩種分析方法都是圍繞XML樹(shù)形結構展開(kāi)的,在編制這兩種分析器時(shí),會(huì )涉及到大量XML概念的API,需要一定的XML基礎和知識,使用起來(lái)有一定難度。

JDOMhttp://www.jdom.org)封裝了DOM/SAX的具體使用技術(shù),以非常符合Java編程方式的形式來(lái)分析XML,因此使用起來(lái)非常方便。

在分析速度方面,JDOMDOM要快,比SAX慢一點(diǎn)。但用在分析配置文件上,速度不是主要的,因為可以使用lazyinitialization。這類(lèi)似緩存機制,在第一次讀取后就保存在內存中,以后每次直接從內存中獲取。

Jive中,JDOM操作基本是由JiveGlobals完成的。

public class JiveGlobals {

 privatestatic final String JIVE_CONFIG_FILENAME = "jive_config.xml";

privatestatic XMLProperties properties = null;

 

...

//從配置文件獲取配置

 publicstatic String getJiveProperty(String name) {

  loadProperties();

  returnproperties.getProperty(name);

 }

  //JDOM載入配置文件

 privatesynchronized static void loadProperties() {

  if(properties == null) {

   properties= new XMLProperties(jiveHome + File.separator +

           JIVE_CONFIG_FILENAME);

  }

 }

 //將配置保存到配置文件中

 public static void setJiveProperty(Stringname, String value) {

   loadProperties();

   properties.setProperty(name,value);

 }

}

從上面代碼看出,對XML文件讀寫(xiě)非常方便,使用properties.getProperty(name)就可以獲得name的配置值,而properties.setProperty(name, value)一句就可以將name和其值value保存到XML文件中,非常類(lèi)似Hashtable的讀取和存入。

XMLPropertiesJDOM的一個(gè)屬性文件輔助包,它主要是對屬性名進(jìn)行分解和合成,例如XML如下:

<jive>

 <email>

  <fromName>Jive_Administrator</fromName>

  <fromEmail>webmaster@example.com</fromEmail>

  <subject>Yourthread was updated!</subject>

  <body>Hello{name}! The thread {threadName} was updated!</body>

 </email>

<jive>

jive/email/fromName的值是Jive_Administrator,那么如何讀取Jive_Administrator?使用properties.getProperty("email.fromName")就可以。注意到,這里Key的名字組合是 email.fromName,這種特定的寫(xiě)法就是XMLProperties可以支持的,在對XML文件保存細節中,由XMLProperties將這種屬性名稱(chēng)寫(xiě)法具體轉換成XML文檔操作。具體內部代碼如下:

  public String getProperty(Stringname) {

        if(propertyCache.containsKey(name)) {  //從緩存中獲取

            return(String)propertyCache.get(name);

        }

         //email.fromName轉變?yōu)?/span>String數組

         //例如propName[0] = jive; propName[1]= email …

        String[]propName = parsePropertyName(name);

        // 通過(guò)propName數組循環(huán),遍歷XML的樹(shù)形結構層次,尋找出對應的屬性值

        Elementelement = doc.getRootElement();

        for(int i = 0; i < propName.length; i++) {

            element= element.getChild(propName[i]);

            if(element == null) {

                returnnull;

            }

        }

        // 尋找到element后,獲得其內容

        Stringvalue = element.getText();

        if("".equals(value)) {            returnnull;        }

        else{

            // 保存到緩存中

            value= value.trim();

            propertyCache.put(name,value);

            returnvalue;

        }

    }

以上只是分析了JDOMXMLProperties包是如何做屬性配置提取的,正是因為JDOM內部做了很多基礎支持性的細節工作,才使得使用JDOM變得非常方便。

總結使用JDOM對配置文件讀寫(xiě)操作語(yǔ)法如下:

·          獲得配置(查詢(xún)):getProperty(name)。

·          新增和修改:properties.setProperty(name,value)。

·          刪除:properties.deleteProperty(name)。

name的格式是xxx.xxx.xxx,例如:

<jive>

   …

<upload>

        <dir>/home/jdon/jive/upload/</dir>

        <relurl>upload/</relurl>

    </upload>

    …

</jive>

要獲得/home/jdon/jive/upload/,name的格式是upload.dir;要獲得upload/,name的格式是upload.relurl。

注意,如果要在系統中支持上述功能,必須下載JDOM包,還要有DataFormatFilter. java、DataUnformatFilter.java、XMLFilterBase.javaXMLProperties.java支持。這幾個(gè)類(lèi)不包含在JDOM標準包中,作為一個(gè)應用包含在其Sample中。當然也可以直接從Jive中復制出來(lái)使用。

5.3  全文檢索和Lucene

Jive中支持全文檢索,這個(gè)功能主要核心依賴(lài)另外一個(gè)開(kāi)放源代碼項目Lucenehttp://jakarta.apache.org/lucene/docs/index.html)。Jakarta Lucene是一個(gè)高性能全文搜索引擎,可以跨平臺應用于任何搜索應用。

使用Lucene作為搜索引擎,應用系統需要做兩件事情:

1)建立索引文件。將Jive數據庫中的數據內容建立索引文件,這是通過(guò)SearchManager來(lái)完成。SearchManager代碼如下:

public interface SearchManager{

    public booleanisSearchEnabled();

    public voidsetSearchEnabled(boolean searchEnabled);

    /**

    //如果SearchManage正在工作,返回真

    public booleanisBusy();

    //返回索引完成率

    public int getPercentComplete();

    //是否自動(dòng)建立索引

    //通過(guò)TaskEngine.scheduleTask方法實(shí)現定期自動(dòng)索引

    public booleanisAutoIndexEnabled();

    public voidsetAutoIndexEnabled(boolean value);

    //自動(dòng)索引間隔的分鐘數

    public int getAutoIndexInterval();

    public voidsetAutoIndexInterval(int minutes);

    //獲得上次建立索引的時(shí)間

    public DategetLastIndexedDate();

//在實(shí)時(shí)建立索引時(shí),將當前帖子加入索引

    public voidaddToIndex(ForumMessage message);

    public voidremoveFromIndex(ForumMessage message);

    //手動(dòng)更新自上次建立索引后的新內容

    public voidupdateIndex();

    //手動(dòng)重新建立全部的索引

    public voidrebuildIndex();

    //優(yōu)化

    public voidoptimize();

}

·          SearchManager定義了建立索引的一些屬性,建立索引有兩種方式:當有新帖子加入時(shí),通過(guò)調用indexMessage()方法實(shí)時(shí)索引;或者通過(guò)TaskEngine.scheduleTask方法每隔一定時(shí)間建立索引。

·          DbSearchManager作為SearchManager的子類(lèi)實(shí)現,又是一個(gè)線(xiàn)程類(lèi),它是建立索引的主要功能類(lèi)。在DbSearchManager中主要使用了LuceneIndexWriter、 Analyzer、 Document Field等功能類(lèi)來(lái)建立索引。

·          IndexWriter用戶(hù)建立新的索引,當然也可以將文檔加入已經(jīng)存在的索引。

在文本被索引之前,它必須通過(guò)一個(gè)分析器Analyzer。分析器Analyzer 負責從文本中分離出索引關(guān)鍵字。Lucene有幾種不同類(lèi)型的分析器:

·          SimpleAnalyzer是將英文轉換為小寫(xiě)字母,按空格和標點(diǎn)符號切分出英文單詞,

Iam Java這一句,使用SimpleAnalyzer切詞就會(huì )切分出下列詞語(yǔ):

token1=I

token2=am

token3=Java

·          StandardAnalyzer是對英文進(jìn)行了較為復雜的處理。除了按詞語(yǔ)建立索引關(guān)鍵字(token)外,還能夠為特殊名稱(chēng)、郵件地址、縮寫(xiě)格式等建立索引單元,而且對“and”、“ the”等詞語(yǔ)做了過(guò)濾。

·          ChineseAnalyzer是專(zhuān)門(mén)用來(lái)分析中文的索引的。關(guān)于中文分析器,有很多嘗試,如車(chē)東的http://sourceforge.net/projects/weblucene/;zhoujunhttp://www.jdon.com/jive/thread.jsp? forum=61&thread=8400等,該問(wèn)題將在后面章節繼續討論。

一個(gè)索引是由一系列Document組成,每個(gè)Document是由一個(gè)或多個(gè)Field組成,每個(gè)Field都有一個(gè)名字和值,可以把Document作為關(guān)系數據庫中一條記錄,而Field則是記錄中某列字段。一般建立索引如下:

//指定將在哪個(gè)目錄建立索引

String indexDir = "/home/jdon/jive/WEB-INF/jiveHome"; 

//指定將要建立索引的文本

String text = "welcom here,I am Java,";     

Analyzer analyzer = new StandardAnalyzer();   //使用StandardAnalyzer

//建立一個(gè)IndexWriter

IndexWriter writer = new IndexWriter(indexDir,analyzer, true);

//建立Document

Document document  = new Document();

//進(jìn)行切詞、索引

document.add(Field.Text("fieldname",text));

//加入索引中

writer.addDocument(document);

writer.close();

其中,Field根據具體要求有不同用法,Lucene提供4種類(lèi)型的Field: Keyword、 UnIndexed、 UnStored Text。

·          Keyword 不實(shí)現切詞,逐字地保存在索引中,這種類(lèi)型適合一些如URL、日期、個(gè)人姓名、社會(huì )安全號碼、電話(huà)號碼等需要原封不動(dòng)保留的詞語(yǔ)。

·          UnIndexed既不實(shí)現切詞也不索引,但是其值是一個(gè)詞一個(gè)詞地保存在索引中,這不適合很大很長(cháng)的詞語(yǔ),適合于顯示一些不經(jīng)過(guò)直接搜索的結果值。

·          UnStoredUnIndexed正好相反,將被切詞和索引,但是不保存在索引中,這適合巨大文本,如帖子內容、頁(yè)面內容等。

·          Text是實(shí)現切詞、索引,并且保存在索引中。

Jive中,索引的建立以DbSearchManager中加入帖子索引方法為例:

protected final void addMessageToIndex(longmessageID, long userID,

            longthreadID, long forumID, String subject, String body,

            java.util.DatecreationDate, IndexWriter writer) throws IOException

{

    //建立一個(gè)  Document

    Document doc= new Document();

    doc.add(Field.Keyword("messageID",Long.toString(messageID)));

    doc.add(newField("userID", Long.toString(userID), false,true, false));

   doc.add(new Field("threadID",Long.toString(threadID), false, true, false));

    doc.add(newField("forumID", Long.toString(forumID), false,true, false));

    doc.add(Field.UnStored("subject",subject));

    doc.add(Field.UnStored("body",body));

    doc.add(newField("creationDate", DateField.dateToString(creationDate),

                false,true, false));

    //將該Document加入當前索引中

    writer.addDocument(doc);

}

DbSearchManager中同時(shí)也實(shí)現了自動(dòng)建立索引的過(guò)程,通過(guò)在構造方法中生成TimeTask實(shí)例:

timerTask = TaskEngine.scheduleTask(

                    this,autoIndexInterval*JiveGlobals.MINUTE,

                    autoIndexInterval*JiveGlobals.MINUTE);

因為DbSearchManager是線(xiàn)程類(lèi),它在run方法中實(shí)現索引任務(wù)自動(dòng)運行:

TaskEngine.addTask(newIndexTask(false));

2)建立完成后,就可以直接搜索特定的詞語(yǔ)了。搜索語(yǔ)句一般代碼如下:

Searcher searcher = new IndexSearcher((indexDir);  //創(chuàng )建一個(gè)搜索器

//使用和索引同樣的語(yǔ)言分析器

Query query = QueryParser.parse(queryString, "body",new StandardAnalyzer());

//搜索結果使用Hits存儲

Hits hits = searcher.search(query);

//通過(guò)hits得到相應字段的數據和查詢(xún)的匹配度

for (int i=0; i<hits.length();i++) {

      System.out.println(hits.doc(i).get("fieldname "));

};

Jive實(shí)現搜索就復雜得多,它為搜索專(zhuān)門(mén)建立了一個(gè)Query接口:

public interface Query {

    //需要搜索的字符串

    public StringgetQueryString();

    public voidsetQueryString(String queryString);

 

    public DategetBeforeDate();

    public voidsetBeforeDate(Date beforeDate);

 

    public DategetAfterDate();

    public voidsetAfterDate(Date afterDate);

 

    public UsergetFilteredUser();

    public voidfilterOnUser(User user);

 

    public ForumThreadgetFilteredThread();

    public voidfilterOnThread(ForumThread thread);

 

    public int resultCount();

    public Iteratorresults();

    public Iteratorresults(int startIndex, int numResults);

}

Query接口中主要定義了和搜索相關(guān)的一些參數,可以根據具體要求定制,直接使用Query就可以達到搜索的目的,如需要搜索Java is cool,那么使用下列代碼:

ForumFactory forumFactory = ForumFactory.getInstance();

Query query = forumFactory.createQuery(forums);

query.setQueryString("Jiveis cool");

Iterator iter = query.results();

while (iter.hasNext()) {

     ForumMessagemessage = (ForumMessage)iter.nextElement();

     //輸出結果

}

追查代碼會(huì )發(fā)現,上面forumFactory.createQuery(forums)方法實(shí)際內容是new DbQuery(forums, this)。DbQuery作為Query的一個(gè)子類(lèi),它的搜索語(yǔ)句通過(guò)executeQuery()方法中下列語(yǔ)句實(shí)現:

private void executeQuery() {

    try {

       Searchersearcher = getSearcher();  //創(chuàng )建一個(gè)搜索器

       …

       //使用分析器獲得Query對象

       org.apache.lucene.search.QuerybodyQuery =

                QueryParser.parse(queryString, "body",DbSearchManager.analyzer);

      org.apache.lucene.search.QuerysubjectQuery =

                QueryParser.parse(queryString, "subject",DbSearchManager.analyzer);

        //將兩個(gè)Query對象加入BooleanQuery

        BooleanQuerycomboQuery = new BooleanQuery();

        comboQuery.add(subjectQuery,false,false);

        comboQuery.add(bodyQuery,false,false);

        //Jive自己的搜索結果過(guò)濾器

        MultiFiltermultiFilter = new MultiFilter(3);

        intfilterCount = 0;

    

        if(factory.getForumCount() != forums.length) {

             //將其他論壇內容搜索結果過(guò)濾掉

            String[]forumIDs = new String[forums.length];

             for(int i=0; i<forumIDs.length; i++) {

                forumIDs[i]= Long.toString(forums[i].getID());

             }

             multiFilter.add(newFieldFilter("forumID", forumIDs));

             filterCount++;

        }

 

         //日期過(guò)濾器  如只查詢(xún)某日期以后的內容

        if(beforeDate != null || afterDate != null) {

            if(beforeDate != null && afterDate != null) {

                multiFilter.add(newDateFilter("creationDate", beforeDate, afterDate));

                filterCount++;

             }elseif (beforeDate == null) {

                multiFilter.add(DateFilter.After("creationDate",afterDate));

                 filterCount++;

             }else{

                 multiFilter.add(DateFilter.Before("creationDate",beforeDate));

                 filterCount++;

             }

        }

        // 過(guò)濾用戶(hù)

        if(user != null) {

             StringuserID = Long.toString(user.getID());

             multiFilter.add(newFieldFilter("userID", userID));

             filterCount++;

        }

        // 主題過(guò)濾

        if(thread != null) {

             StringthreadID = Long.toString(thread.getID());

             multiFilter.add(newFieldFilter("threadID", threadID));

             filterCount++;

        }

        if(filterCount > 0) {//實(shí)現搜索

             hits= searcher.search(comboQuery, multiFilter);

        }else {

             hits= searcher.search(comboQuery);

        }

        //搜索結果不要超過(guò)最大大小

        intnumResults = hits.length() < MAX_RESULTS_SIZE ?

                    hits.length(): MAX_RESULTS_SIZE;

        long[] messages = new long[numResults];

        for(int i=0; i<numResults; i++) {

           messages[i]=Long.parseLong( ((Document)hits.doc(i)).get("messageID"));

       }

        results= messages;

      }catch (Exception e) {

        e.printStackTrace();

        results= new long[0];

      }

}

Jive的搜索使用了過(guò)濾器,以便過(guò)濾掉不想出現的結果,然后還對搜索結果進(jìn)行了限制轉換,這些在實(shí)際使用中都是必需的。

5.4  Jive的中文問(wèn)題

Jive默認的字符集編碼方式是ISO8859_1,即Latin-1字符集,這是國際標準化組織用來(lái)表示Latin等西方語(yǔ)言使用的字符集。

ISO8859_1字符集非常類(lèi)似常見(jiàn)的ASCII字符集。由于ISO8859_1是使用單字節來(lái)表示,而漢字是采取雙字節來(lái)表示一個(gè)漢字,我國制定了一套專(zhuān)門(mén)用來(lái)表示漢字GB2312GBK編碼字符集。

Java內部運算中,涉及到的所有字符串都會(huì )被轉化為UTF-8編碼來(lái)進(jìn)行運算。那么,在被Java轉化之前,字符串是什么樣的字符集? Java總是根據操作系統的默認編碼字符集來(lái)決定字符串的初始編碼,而且Java系統的輸入和輸出的都是采取操作系統的默認編碼。

因此,如果能統一Java系統的輸入、輸出和操作系統3者的編碼字符集合,將能夠使Java系統正確處理和顯示漢字。這是處理Java系統漢字的一個(gè)原則,但是在實(shí)際項目中,能夠正確抓住和控制住Java系統的輸入和輸出部分是比較難的。

Jive是運行在Web容器中的一個(gè)Servlet/JSP系統。在這個(gè)系統中,輸入途徑有很多種:一種是通過(guò)頁(yè)面表單打包成請求(request)發(fā)往服務(wù)器的;第二種是通過(guò)數據庫讀入;還有第3種輸入比較復雜,JSP在第一次運行時(shí)總是被編譯成Servlet,JSP中常常包含中文字符,那么編譯使用javac時(shí),Java將根據默認的操作系統編碼作為初始編碼。除非特別指定,如在Jbuilder中可以指定默認的字符集。

輸出途徑也有幾種:第一種是JSP頁(yè)面的輸出。由于JSP頁(yè)面已經(jīng)被編譯成Servlet,那么在輸出時(shí),也將根據操作系統的默認編碼來(lái)選擇輸出編碼,除非指定輸出編碼方式;還有輸出途徑是數據庫,將字符串輸出到數據庫。

由此看來(lái),一個(gè)J2EE系統的輸入輸出是非常復雜,而且是動(dòng)態(tài)變化的,而Java是跨平臺運行的,在實(shí)際編譯和運行中,都可能涉及到不同的操作系統,如果任由Java自由根據操作系統來(lái)決定輸入輸出的編碼字符集,這將不可控制地出現亂碼。

正是由于Java的跨平臺特性,使得字符集問(wèn)題必須由具體系統來(lái)統一解決,所以在一個(gè)Java應用系統中,解決中文亂碼的根本辦法是明確指定整個(gè)應用系統統一字符集。

Jive中如果指定默認字符集為某個(gè)字符集,那么就要在所有的輸入輸出環(huán)節都要標識為這個(gè)字符集。但是,前面已經(jīng)提到,要完全在編碼時(shí)做到還是有一定難度,必須對Web程序有相當地掌握和理解,而且步驟較繁瑣。

有一種相對省事的做法,例如統一指定為ISO8859_1,因為目前大多數軟件都是西方人編制的,他們默認的字符集就是ISO8859_1,包括操作系統Linux和數據庫MySQL等。這樣,如果指定Jive統一編碼為ISO8859_1,那么就有下面3個(gè)環(huán)節必須把握:

·          開(kāi)發(fā)和編譯代碼時(shí)指定字符集為ISO8859_1。

·          運行操作系統的默認編碼必須是ISO8859_1,如Linux。

·          JSP頭部聲明:<%@ page contentType="text/html;charset=ISO8859_1" %>。

如果統一指定為GBK中文字符集,上述3個(gè)環(huán)節同樣需要做到,不同的是只能運行在默認編碼為GBK的操作系統,如中文Windows。

所以統一編碼為ISO8859_1GBK雖然帶來(lái)編制代碼的方便,但是也破壞了Java跨平臺運行的優(yōu)越性,只在一定范圍內行得通。

很多情況下,程序員大都是在中文Windows下開(kāi)發(fā)調試Java系統,然后直接部署到Linux等系統上真正運行。而且其中可能涉及到XML文件讀寫(xiě)。XML是對編碼方式要求嚴格的數據存儲體,XML又可以隨著(zhù)代碼移動(dòng)。因此,在進(jìn)行真正大規模Java系統開(kāi)發(fā)運行時(shí),上述臨時(shí)簡(jiǎn)單的變通方式就沒(méi)有效果了。

要從根本上解決Java的中文問(wèn)題,只要將Java系統的統一編碼定義為UTF-8。UTF-8編碼是一種兼容所有語(yǔ)言的編碼方式,惟一比較麻煩的就是要找到應用系統的所有出入口,然后使用UTF-8去“結扎”它。

Jive默認的字符集編碼方式是ISO8859_1,如果都統一為UTF-8,那么也需要做下列幾步工作:

·          開(kāi)發(fā)和編譯代碼時(shí)指定字符集為UTF-8。

·          使用過(guò)濾器,將所有請求(request)轉換為UTF-8;針對不同應用過(guò)濾器有兩種。

·          如果所有請求都經(jīng)過(guò)一個(gè)Servlet控制分配器,那么使用Servletfilter執行語(yǔ)句。

·          request.setCharacterEncoding("UTF-8")。

·          如果不經(jīng)過(guò)Servlet,而直接是JSP,那么每個(gè)JSP頭部設置上述語(yǔ)句。

·          JSP頭部聲明:<%@ page contentType="text/html;charset=UTF-8" %>。

·          設定數據庫連接方式是UTF-8。

以上討論了Jive以及通用Java的中文問(wèn)題。如果整個(gè)應用系統是從開(kāi)始進(jìn)行開(kāi)發(fā),那么統一指定編碼為UTF-8就非常容易做到。如果是在英文源代碼基礎上二次開(kāi)發(fā),那么首先要將原來(lái)的源代碼轉換為統一編碼UTF-8,那么這種轉換工作會(huì )帶來(lái)一定的麻煩。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Jive 的緩存機制
設計模式之Composite(組合)
表演需要開(kāi)場(chǎng)舞?來(lái)看看這個(gè)~Jive
<轉載>如何迅速成為Java高手。
Patterns in Java
JR - 研究文集 - Jive 研究
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久