2007年7月26日

          Mondrian是一個開放源代碼的Rolap服務器,使用java開發的。它實現了xmla和jolap規范,而且自定義了一種使用mdx語言的客戶端接口。Mondrian是olap服務器,而不是數據倉庫服務器,因此Mondrian的元數據主要包括olap建模的元數據,不包括從外部數據源到數據庫轉換的元數據。也就是說Mondria的元數據僅僅包括了多維邏輯模型,從關系型數據庫到多維邏輯模型的映射,存取權限等信息。在功能上,Mondrian支持共享維和成員計算,支持星型模型和雪花模型的功能。
          Mondrian中使用物理的xml文件存儲元數據,它的設計者規定了xml文件的格式。下面簡單介紹一下它是如何存儲元數據的。

          Element Description
          根元素
          <Schema> Collection of Cubes, Virtual cubes, Shared dimensions, and Roles.
          邏輯元素
          <Cube> A collection of dimensions and measures, all centered on a fact table.
          <VirtualCube> A cube defined by combining the dimensions and measures of one or more cubes.
          <Dimension>
          <DimensionUsage> Usage of a shared dimension by a cube.
          <Hierarchy>
          <Level>
          <Property>
          <Measure>
          物理元素
          <Table> Fact- or dimension table.
          <View> Defines a 'table' using a SQL query, which can have different variants for different underlying databases.
          <Join> Defines a 'table' by joining a set of queries.
          存取控制
          <Role> An access-control profile.
          <SchemaGrant> A set of rights to a schema.
          <CubeGrant> A set of rights to a cube.
          <HierarchyGrant> A set of rights to a hierarchy and levels within that hierarchy.
          <MemberGrant> A set of rights to a member and its children.
          其他
          <Parameter>
          <Table>
          <Table>



          一個模式定義一個多維數據庫,它包括一個邏輯模型,由立方體,層次,成員和邏輯模型到物理模型的映射構成。一個邏輯模型由可以用MDX語言來查詢。Mondrain的模型由xml文件來描述。現在創建模式的唯一途徑是用文本編輯a器編輯xml文件。Xml的語法不是太復雜,因此沒有想象中的那么難。目前正在開發一個圖形界面的程序來創建和修改模式。
          一個模式最重要的組成部分是立方體,度量和維:在一個主題域中立方體是維和度量的集合。一個度量是一個可測量的數值,比如產品銷售的數量或者詳細清單的價格
          一個維是一個屬性或者是屬性的集合, 通過維你可以將度量劃分到字類中。比如:你希望將銷售產品按顏色,顧客性別,售出的商店分為八個部分,那么顏色,性別,商店都是維。

          下面是一個簡單的模型定義的例子:
          <Schema>
          <Cube name="Sales">
          <Table name="sales_fact_1997"/>
          <Dimension name="Gender" foreignKey="customer_id">
          <Hierarchy hasAll="true" allMemberName="All Genders" primaryKey="customer_id">
          <Table name="customer"/>
          <Level name="Gender" column="gender" uniqueMembers="true"/>
          </Hierarchy>
          </Dimension>
          <Dimension name="Time" foreignKey="time_id">
          <Hierarchy hasAll="false" primaryKey="time_id">
          <Table name="time_by_day"/>
          <Level name="Year" column="the_year" type="Numeric"
          uniqueMembers="true"/>
          <Level name="Quarter" column="quarter"
          uniqueMembers="false"/>
          <Level name="Month" column="month_of_year" type="Numeric"
          uniqueMembers="false"/>
          </Hierarchy>
          </Dimension>
          <Measure name="Unit Sales" column="unit_sales"
          aggregator="sum" formatString="#,###"/>
          <Measure name="Store Sales" column="store_sales"
          aggregator="sum" formatString="#,###.##"/>
          </Cube>
          </Schema>

          這個模型包含了一個銷售cube,這個cube有兩個維,時間和性別維;兩個度量,銷售數量和銷售總額。
          我們可以在這個模型上寫一個 MDX 查詢:
          select {[Measures].[Unit Sales], [Measures].[Store Sales]} on columns,
          {[Time].[1997].[Q1].descendants} on rows
          from [Sales]
          where [Gender].[F]
          這 個查詢涉及到了銷售立方體, 每一個維 [Measures], [Time], [Gender], 這些維的多個成員. 結果如下:
          [Time] [Measures].[Unit Sales] [Measures].[Store Sales]
          [1997].[Q1] 0 0
          [1997].[Q1].[Jan] 0 0
          [1997].[Q1].[Feb] 0 0
          [1997].[Q1].[Mar] 0 0

          下面詳細地介紹一下模式定義:
          一個立方體是一個或者多個維和度量的集合,通常是一個事實表,這里是 ‘sales_fact_1997". 事實表保存了需要計算的列和包含維的參考表.
          <Cube name="Sales">
          <Table name="sales_fact_1997"/>
          ...
          </Cube>
          這里用 <Table> 元素定義事實表. 如果事實表 不在默認的模式中, 你可以用"schema"屬性指定一個明確地模式,例如:
          <Table schema="foodmart" name="sales_fact_1997"/>
          你也可以利用 <View> 和 <Join> 結構來創建更復雜的sql .
          度量
          銷售立方體定義了兩個維 "Unit Sales" 和 "Store Sales".
          <Measure name="Unit Sales" column="unit_sales"
          aggregator="sum" formatString="#,###"/>
          <Measure name="Store Sales" column="store_sales"
          aggregator="sum" formatString="#,###.00"/>
          每個度量有一個名字,對應事實表中的一列, 采用一個聚集函數 (usually "sum").
          一個可選的格式字符串指定了值如何被打印. 這里我們選擇銷售數量不帶小數的輸出(因為銷售數量是整數) ,銷售總額帶2位小數 . 符號',' 和 '.' 是對地區敏感的, 因此如果是在意大利運行, 銷售總額可能會出現 "48.123,45". 你可以用 advanced format strings來實現更嚴格的效果.度量值不是從列中來的,而是從立方體的單元中來的

          性別維由單一的層次組成,僅有一層。
          <Dimension name="Gender" foreignKey="customer_id">
          <Hierarchy hasAll="true" primaryKey="customer_id">
          <Table name="customer"/>
          <Level name="Gender" column="gender" uniqueMembers="true"/>
          </Hierarchy>
          </Dimension>
          對于任意給定的銷售, 性別維是指購買改產品的客戶的性別. 它通過連接事實表"sales_fact_1997.customer_id"和維表"customer.customer_id"
          來表示 。"gender" 包括兩個值, 'F' 和 'M', 因此性別維包含的成員: [Gender].[F] and [Gender].[M]. 因為 hasAll="true", 系統產生一個特別的 'all' 層, 僅包括一個成員 [All Genders].
          一個維可以包含多個層次:
          <Dimension name="Time" foreignKey="time_id">
          <Hierarchy hasAll="false" primaryKey="time_id">
          <Table name="time_by_day"/>
          <Level name="Year" column="the_year" type="Numeric"
          uniqueMembers="true"/>
          <Level name="Quarter" column="quarter"
          uniqueMembers="false"/>
          <Level name="Month" column="month_of_year" type="Numeric"
          uniqueMembers="false"/>
          </Hierarchy>
          <Hierarchy name="Time Weekly" hasAll="false" primaryKey="time_id">
          <Table name="time_by_week"/>
          <Level name="Year" column="the_year" type="Numeric"
          uniqueMembers="true"/>
          <Level name="Week" column="week"
          uniqueMembers="false"/>
          <Level name="Day" column="day_of_week" type="String"
          uniqueMembers="false"/>
          </Hierarchy>
          </Dimension>
          第一個層次沒有指定名稱.缺省的情況下,一個層次擁有和它的維相同的名稱。,因此第一個層次成為"Time".這些層次沒有太多的共同之處,他們甚至沒有相同的表,除非它們連接了實施表中的同一列"time_id"。在一個維上存在兩個層次的原因是這樣對最終用戶是有用的. 如果一個維上存在兩個層次, MDX會強制不允許在一個查詢中同時用到他們.
          A dimension can live in the fact table:
          <Cube name="Sales">
          <Table name="sales_fact_1997"/>
          ...
          <Dimension name="Payment method">
          <Hierarchy hasAll="true">
          <Level name="Payment method" column="payment_method" uniqueMembers="true"/>
          </Hierarchy>
          </Dimension>
          </Cube>
          每個維包含有多層組成的一個層次,

          大多數維都是僅有一個層次,但有時候一個維有多個層次。比如:你可能希望在時間維上從天聚集到月,季度和年;或者從天聚集到周和年。這兩種層次都是從天到年,但是聚集的路徑不同。大多數層次有全成員,全成員包括層次的所有成員,因此能夠代表他們的總合。它通常命名為'All something',比如:'All stores'.




          星型模式和雪花模式
          mondrian支持星型模式和雪花模式。下面介紹一下雪花模式的建模,它需要用到操作符 <Join>.比如:
          <Cube name="Sales">
          ...
          <Dimension name="Product" foreignKey="product_id">
          <Hierarchy hasAll="true" primaryKey="product_id" primaryKeyTable="product">
          <Join leftKey="product_class_id" rightAlias="product_class" rightKey="product_class_id">
          <Table name="product"/>
          <Join leftKey="product_type_id" rightKey="product_type_id">
          <Table name="product_class"/>
          <Table name="product_type"/>
          </Join>
          </Join>
          ...
          </Hierarchy>
          </Dimension>
          </Cube>
          這里定義一個 "Product" 維 由三個表構成. 事實表連接 表"product" (通過外鍵 "product_id"),表"product"連接表"product_class" (通過外鍵 "product_class_id"),表"product_class"連接表 "product_type" (通過外鍵 "product_type_id"). 我們利用 <Join> 元素的循環嵌套, <Join>帶有兩個操作對象; 操作對象可能是表,連接或者查詢 。
          按照操作對象行的數目來安排次序,表 "product" 的行數最大, 因此它首先出現連接事實表;然后是表 "product_class"和 "product_type",在雪花的末端擁有的行數最小.
          注意外部元素 <Join>有一個屬性 rightAlias. 這是必要的,因為join 的右邊(是內部元素 <Join> ) 有可能是許多表組成的.這種情況下不需要屬性leftAlias,因為列 leftKey 很明確的來自表 "product".

          共享維
          當為一個連接生成SQL的時候, mondrian 需要知道連接哪一個列. 如果一正在連接一個多表連接, 你需要告訴它連接這些表里的哪一個表,哪一個列.
          因為共享維不屬于一個cube,你必須給它們一個明確的表 (或者數據源). 當你在一個特別的cube里用他們的時候, 你要指定外鍵 foreign key. 下面的例子顯示了 Store Type 維被 連接到 Sales cube ,用了外鍵 sales_fact_1997.store_id, 并且被連接到Warehouse cube ,用了外鍵 warehouse.warehouse_store_id :
          <Dimension name="Store Type">
          <Hierarchy hasAll="true" primaryKey="store_id">
          <Table name="store"/>
          <Level name="Store Type" column="store_type" uniqueMembers="true"/>
          </Hierarchy>
          </Dimension>

          <Cube name="Sales">
          <Table name="sales_fact_1997"/>
          ...
          <DimensionUsage name="Store Type" source="Store Type" foreignKey="store_id"/>
          </Cube>

          <Cube name="Warehouse">
          <Table name="warehouse"/>
          ...
          <DimensionUsage name="Store Type" source="Store Type" foreignKey="warehouse_store_id"/>
          </Cube>




          虛擬 cubes
          父子層次
          一個使用方便的層次 有一個嚴格的層的集合, 成員與層緊密的聯系.比如,在 Product 層次中, 任何產品名稱層的成員在商標層上都有一個父親 ,商標層上的成員在產品子目錄層也都有一個父親. 這種結構對于現實世界中的數據有時候太嚴格了.
          一個父子層次只有一層 (不計算 'all' 層), 但是任何成員可以在同一層上有父親成員. 一個典型的例子是Employees 層次:
          <Dimension name="Employees" foreignKey="employee_id">
          <Hierarchy hasAll="true" allMemberName="All Employees" primaryKey="employee_id">
          <Table name="employee"/>
          <Level name="Employee Id" uniqueMembers="true" type="Numeric"
          column="employee_id" nameColumn="full_name"
          parentColumn="supervisor_id" nullParentValue="0">
          <Property name="Marital Status" column="marital_status"/>
          <Property name="Position Title" column="position_title"/>
          <Property name="Gender" column="gender"/>
          <Property name="Salary" column="salary"/>
          <Property name="Education Level" column="education_level"/>
          <Property name="Management Role" column="management_role"/>
          </Level>
          </Hierarchy>
          </Dimension>
          這里parentColumn 和nullParentValue是重要的屬性:
          屬性parentColumn 是一個成員連接到它父親成員的列名。在這種情況下, 它是指向雇員經理的外鍵。元素<Level>的子元素 <ParentExpression> 是與屬性 parentColumn 有相同作用的,但是元素允許定義任意的SQL表達式, 就像元素 <Expression>. 屬性 parentColumn (或者 元素<ParentExpression>) 是維一向Mondrian指出 層次有父子結構的。
          屬性 nullParentValue 是指明成員沒有父成員的值 。 缺省情況下 nullParentValue="null", 但是因為許多數據庫不支持null, 建模時 用其他值來代替空值,0和-1.

          物理結構
          member reade
          member reader 是訪問成員的方法. 層次通常以維表為基礎建立的 , 因此要用sql來構造.但是甚至你的數據沒有存在于 RDBMS, 你可以通過一個 Java 類來訪問層次。(自定義 member reader)
          Here are a couple of examples:
          DateSource (to be written)生成一個時間層次. 按常規,數據倉庫工具生成一個表 ,每天包含一行。但是問題是這個表需要裝載,并且隨著時間的變化能夠添加更多的行。 DateSource 在內存中按照要求生成日期成員.
          FileSystemSource (to be written) 按照目錄和文件的層次描述文件系統。 Like the time hierarchy created by DateSource, this is a virtual hierarchy: the member for a particular file is only created when, and if, that file's parent directory is expanded.
          ExpressionMemberReader (to be written) 創建了一個基于表達式的層次。
          自定義member reader 必須實現接口 mondrian.rolap.MemberSource. 如果你需要實現一個更大的成員操作集合, 需要實現接口 interface mondrian.rolap.MemberReader; 否則, Mondrian在 mondrian.rolap.CacheMemberReader中封裝 你的 reader類.你的 member reader 必須有一個公共的構造函數,這個構造函數擁有參數(Hierarchy,Properties),拋出未檢查的錯誤.
          Member readers 用 元素<Hierarchy> 的屬性memberReaderClass來聲明; 任何 <Parameter> 子元素通過屬性構造函數來傳遞.
          這是一個例子:
          <Dimension name="Has bought dairy">
          <Hierarchy hasAll="true" memberReaderClass="mondrian.rolap.HasBoughtDairySource">
          <Level name="Has bought dairy" uniqueMembers="true"/>
          <Parameter name="expression" value="not used"/>
          </Hierarchy>
          </Dimension>
          Cell readers
          <Measure name="name" cellReaderClass="com.foo.MyCellReader">
          類 "com.foo.MyCellReader" 實現了接口interface mondrian.olap.CellReader.


          存取控制
          可以定義存取控制的屬性(角色), 作為模式的一部分, 并且可以在建立連接的時候設置角色。
          定義角色
          角色可以通過 元素<Role>來設置 , 它是元素<Schema> 的直接的子元素.
          下面是一個關于角色的例子:
          <Role name="California manager">
          <SchemaGrant access="none">
          <CubeGrant cube="Sales" access="all">
          <HierarchyGrant hierarchy="[Store]" access="custom" topLevel="[Store].[Store Country]">
          <MemberGrant member="[Store].[USA].[CA]" access="all"/>
          <MemberGrant member="[Store].[USA].[CA].[Los Angeles]" access="none"/>
          </HierarchyGrant>
          <HierarchyGrant hierarchy="[Customers]" access="custom" topLevel="[Customers].[State Province]" bottomLevel="[Customers].[City]">
          <MemberGrant member="[Customers].[USA].[CA]" access="all"/>
          <MemberGrant member="[Customers].[USA].[CA].[Los Angeles]" access="none"/>
          </HierarchyGrant>
          <HierarchyGrant hierarchy="[Gender]" access="none"/>
          </CubeGrant>
          </SchemaGrant>
          </Role>
          元素 <SchemaGrant> 定義了模式中缺省的對象方問權限. 訪問屬性可以是 "all" 或者 "none"; 這個屬性可以被具體的權限對象繼承. 在這個例子中, 因為 access="none", 用戶只能瀏覽"Sales" 立方體, 這里明確的賦予了這個權限.
          元素 <CubeGrant> 定義了立方體的訪問權限. 就像 <SchemaGrant>, 屬性access 可以是"all" 或者 "none", 并且能夠被cube中具體的子對象繼承.
          元素 <HierarchyGrant>定義了層次的訪問權限. 屬性access 可以是"all", 意思是所有的members都是可見的; "none",意思是 hierarchy的存在對用戶是隱藏的; "custom", 你可以利用屬性 topLevel 定義可見的最高層 (阻止用戶 進行上卷操作, 比如瀏覽稅收 上卷到 Store Country 層); 或者用屬性 bottomLevel 定義可見的最底層 (這里阻止用戶查看顧客個人的細節數據);或者控制用戶查看哪一個成員集合,通過嵌套定義元素 <MemberGrant>.
          你也可以只定義元素 <MemberGrant> ,如果模式的<HierarchyGrant> 有屬性access="custom". Member grants 賦予 (或者取消) 訪問給定的成員, 以及它的所有子成員.
          posted @ 2008-03-26 22:30 edsonjava 閱讀(926) | 評論 (0)編輯 收藏
           
          改了不少JPivot/mondrian代碼,還修正了jpivot一個bug。

          對JPivot的jfreechart和drillthrough顯示做了增強,終于可以拿出去給人用了。

          先說說性能問題: 先是找了一臺閑置的IBM X445 PC Server,4×2GHZ CPU,8G內存,2×146G硬盤,操作系統 windows 2000 , 開啟AWE 3G參數。然后裝Oracle 10g,數據倉庫模式,使用了4G AWE內存共約4.5GB內存。再建成一張1600萬用戶數據寬表,寬表一律使用bitmap索引,還有其他20個左右維表。 然后就簡單了,寫mondrian Cube,配JPivot。 最后搞下來的結果是:基本上mondrian 每次做group by 操作最長不超過30秒,一般在20秒左右。用戶基本可以接受。問了使用NCR的朋友,說NCR使用自己的數據庫,也基本是這樣的一個性能。 PS:偷偷問一聲,在這基礎上,性能還能改進否?

           

          再說說方向問題: 我們現在使用2個OLAP,一個是jpivot + mondrian ,屬于ROLAP;另一個是BO intelligence + essbase,屬于MOLAP。目前的感覺是,由于DB性能強悍,導致ROLAP和MOLAP在性能上相差不大。同時ROLAP可以直接和報表系統共用同一張表。而MOLAP則需要使用工具來打CUBE做數據轉換,這樣在開發和維護工作量上,MOLAP比ROLAP大。 另外往往業務部門分析到最后,就是要看明細數據了,這個時候MOLAP的前端工具往往不能做好支持。而jpivot則無此問題。 綜上所述,我目前好像還沒看到必須用MOLAP的理由,聽說華為原來用M$ 的OLAP,后來好像支持不住了,就直接用回了BO 報表,呵呵。

           

          JPivot的問題: 操作太復雜,必須對OLAP的概念有清晰的了解,普通用戶無法使用。與mondrian 集成不夠緊密。mondrian不提供數據鉆取功能,該功能是jpivot自己做的,所以會導致數據類型格式丟失。鉆取詳細數據量無限制,導致內存溢出。界面比較難看,操作方式非主流使用jpivot自己的mvc框架,不易其他框架集成 總體來說,jpivot目前已經不是一個玩具了,完全可以用于企業級的操作,而且定位在高端業務分析人員。


          拿出來開源比較困難,一方面jpivot在不停升級,另一方面我在修改的時候不顧一切,在jpivot中亂引用了mondrian代碼,還把mondrian部分無用代碼全刪了。這樣,我就在這個帖里把能共享部分都在這里帖出來。 首先是我優化后的界面。 1.圖標用了pentaho里面的圖標。 2.jpivot里面其實支持3D餅圖,只是選項未開,我先將jfreechart升級成1.0.2,又對餅圖、線圖等做了美觀。 3.drillthrough是jpivot相對其他olap產品的殺手級功能,但是有不少細節未完善。我基本都一一補上。 在界面上可以看出,我添加了一個CSV導出功能(改了WCF庫),同時限制最大導出20萬行記錄(改了jpivot)。界面上顯示的“訪問次數”是measure的名字,實際上應該顯示“訪問時間”,該問題暫時無解。另外修正了一下numberformat、dateformat不正確的一些問題。 4.excel導出時,格式很難看,但是由于excel本身只支持256色,無法顯示web上的底色,所以我修改了只顯示藍色的border,底色一律為白。 附件中rar里面是web的CSS文件、Excel的生成文件和jpivot的圖表生成部分代碼,感興趣的朋友各取所需吧


          另外還把jpviot完全整合到我自己的系統中去了,呵呵。 可以在系統web界面上編寫Cube和MDX定義,Cube和MDX為一對多關系。Cube通過xsd來做校驗。開發Cube和MDX的時候可以隨時做預覽。 然后再把一個MDX在界面發布成一個單獨的OLAP分析。 下一步的目標是將數據權限與jpivot做整合,由于Cube的xml是由系統自動生成的,所以mondrian的role配置也可以由系統根據配置自動生成。 這部分代碼涉及我的系統和框架比較深,所以不帖代碼了哈,大家自己搞搞2天也就出來了


          還做了個及其變態的功能,就是把界面上所有顯示的jpivot cell,一個個的去取出鉆取數據的measure,然后生成csv文件,打成zip包給用戶下載或發到其他接口。 當時我化了整整一個禮拜鉆研mondrian代碼,希望可以不用那么傻傻個一個個去鉆,結果失敗...

          我在用Jpivot的時候,發現用mondrian是影響取數性能其中的一個瓶頸........ 經研究.....我們自己修改了jpivot和wcf的一些代碼來適應我們自己的項目.........以下是我做的一些修改.....想聽聽大家的意見 1.脫離mondrian.直接寫dll的方式取數,然后生成XML數據 .我發現脫離mondrian自己寫了一個DLL去調用MSSQL 2000 的OLAP,數度很快........... 2 .修改界面的顯示方式 上面也說道.Jpivot的界面一個不好看,二是用起來很不方便.比如取維度等的時候....一層一層的進去實在很麻煩.... a.修改取維度的方式 我們參照ms的做法 做成一個了一個樹的取數,研究jpivot里面的代碼.如果直接用jpivot的代碼取數據十分慢.這樣我自己通過AJAX和Jpivot結合,動態生成樹的結構,然后在樹上取維度的時候,直接通過鼠標托到選擇維度textbox上.........依照條件生成相應MDX....顯示數據..... b.修改數據顯示的樣式.和取維度,生成MDX分開了. 顯示數據我用了另外一種方式顯示.就是用Frame分為上下兩層.....上下兩層可以通過按鈕擴大整個頁面........ 3. 集成在自己的框架中 集成在自己的框架中,我個人覺得是比較麻煩的一件事情.一點小事沒有搞好就很麻煩...因為我們是用JSF開發的.所以依照Jpivot....自己寫了一些組件來輔助開發,我自己開發主要改成比較像ms 2000 的olap分析方法... 還未完成的需求 JFreeChar的功能還需要加強. 個人感覺:jpivot是很不錯.可是不能一拿來就用..我發現好多人用jpivot都要修改好多東西....但是修改起來又比較麻煩....java,j2ee,xml ,xslt,javascript,taglib.....好多東西都要懂.....
          posted @ 2008-03-26 22:28 edsonjava 閱讀(2244) | 評論 (1)編輯 收藏
           

          This documentation is related to the displaytag 1.1.x releases.

          The latest available release is 1.1.1

          Displaytag 1.1 offers several enhancements over 1.0: the most notable news are support for partial lists and enhanced decorator APIs, but there is also a lot more. Be sure to read the migration guide for upgrading an existing application from displaytag 1.0. A full changelog is also available.

          Overview

          The display tag library is an open source suite of custom tags that provide high-level web presentation patterns which will work in an MVC model. The library provides a significant amount of functionality while still being easy to use.

          What can I do with it?

          Actually the display tag library can just... display tables! Give it a list of objects and it will handle column display, sorting, paging, cropping, grouping, exporting, smart linking and decoration of a table in a customizable XHTML style.

          The tables in the sample images below were generated from lists using the <display:table> tag:

          sample tables produced with the display:table tag
          posted @ 2008-02-23 23:47 edsonjava 閱讀(525) | 評論 (0)編輯 收藏
           
          近在論證java領域的開源BI前端框架,把隨手記得東西和大家分享下.
          因為只看了幾天,有沒時間整理所以看起來比較亂,也不是很深入。

          目前在java領域較常見的BI前端框架(商業智能項目)主要有以下幾個Pentaho,spagoBi, OpenI, JASPER intelligence等開源框架。

           他們都有自己的強項和不足,下面簡要介紹下:

          輕量級的:

          OpenI使用Mondrian和Jpivot框架,報表引擎是jasper report,數據挖掘接口是R-Project,

          相對來說開發和學習比較簡單,而且OpenI支持使用MS的數據倉庫(xmla),但是其國際化比較失敗(中文亂碼),要深入改造。

           JASPER intelligence也是個輕型項目,對jasper report的支持最好,所以報表部分比較好。

           重量級的:

          PentahospagoBi是兩個比較大的框架了,集成了相當多的開源項目,JfreeReport、Mondrian、Kettle、Weka基本都使用了。特別適合大型復雜項目的開發。

                Pentaho在中國使用的比較多,文檔什么的也多一點。尤其值得一提的是網絡上對他的中文支持做的相當好,很多志愿者翻譯了它的文檔。這給我們開發帶來很大便利。

           

                Pentaho的模塊工作流引擎、中心資源庫、審計組件、報表設計工具、ETL工具、OLAP Server、多維展示、數據挖掘組件各種組建都有。

          而且Pentaho得到了很大的投資,開發后勁很大,而且會有付費的官方發售版本。 

          http://blog.csdn.net/dust_bug/archive/2006/09/18/1240753.aspx

          這個是Pentaho源代碼閱讀報告》,介紹Pentaho構架相當的全面。 

          Pentaho的中文論壇在http://www.bipub.org/ 

          Pentaho相對spagoBi來說功能較強,尤其是工作流一塊做的相當不錯。

          官方站的demos在http://www.pentaho.com/products/demos/

           spagoBi功能也很強,尤其是最近發布的1。9版本,在http://spagobi.eng.it:8080/sbiportal/faces/public/exo(或http://spagobi.eng.it:8080/sbiportal

          的demos里展現了spagoBi很多功能。

           后記
          這幾款BI框架因為都是開源的前端框架,所以核心部分使用的還是一些開源項目,

          Mondrian,Jpivot,JfreeReport,所以在使用的時候搭建合適的框架會占用項目很大一部分時間,但是一旦框架搭建好了,基本就可以象流水線一樣出報表了。

          但是期望在原始功能上添加性能功能是比較麻煩的,為了一個新加的功能可能需要相當長的時間來實現。

          另外這些開源框架的權限管理都不怎么強,可能需要改造。

          另外,全球話的問題也是問題。象OpenI完全不支持中文,必須改造。

          posted @ 2008-02-23 23:38 edsonjava 閱讀(961) | 評論 (0)編輯 收藏
           

          我們都知道“瞎子摸象”的故事。不同的瞎子對大象的認識不同,因為他們只認識了自己摸到的地方。而企業如果要避免重犯這樣的錯誤,那就離不開商務智能(BI)。專家認為,BI對于企業的重要性就像聰明才智對于個人的重要性。歐美企業的經驗也證明,企業避免無知和一知半解危險的有效手段就是商務智能。商務智能旨在充分利用企業在日常經營過程中收集的大量數據和資料,并將它們轉化為信息和知識來免除各種無知狀態和瞎猜行為。   

          支持BI的開源工具數量眾多,但是大多數的工具都是偏重某方面的。例如,CloverETL偏重ETL,JPivot偏重多維分析展現,Mondrian是OLAP服務器。而Bee、Pentaho和SpagoBI等項目則針對商務智能問題提供了完整的解決方案。

          ETL 工具

          ETL開源工具主要包括CloverETL和Octupus等。

          (1)CloverETL是一個Java的ETL框架,用來轉換結構化的數據,支持多種字符集之間的轉換(如ASCII、UTF-8和ISO-8859-1等);支持JDBC,同時支持dBase和FoxPro數據文件;支持基于XML的轉換描述。

          (2)Octupus是一個基于Java的ETL工具,它也支持JDBC數據源和基于XML的轉換定義。Octupus提供通用的方法進行數據轉換,用戶可以通過實現轉換接口或者使用Jscript代碼來定義轉換流程。

          OLAP服務器

          (1)Lemur主要面向HOLAP,雖然采用C++編寫,但是可以被其他語言的程序所調用。Lemur支持基本的操作,如切片、切塊和旋轉等基本操作。

          (2)Mondrian面向ROLAP包含4層:表示層、計算層、聚集層、存儲層。

          ● 表示層:指最終呈現在用戶顯示器上的以及與用戶之間的交互,有許多方法來展現多維數據,包括數據透視表、餅、柱、線狀圖。

          ● 計算層:分析、驗證、執行MDX查詢。

          ● 聚集層:一個聚集指內存中一組計算值(cell),這些值通過維列來限制。計算層發送單元請求,如果請求不在緩存中,或者不能通過旋轉聚集導出的話,那么聚集層向存儲層發送請求。聚合層是一個數據緩沖層,從數據庫來的單元數據,聚合后提供給計算層。聚合層的主要作用是提高系統的性能。

          ● 存儲層:提供聚集單元數據和維表的成員。包括三種需要存儲的數據,分別是事實數據、聚集和維。

          OLAP客戶端

          JPivot是JSP風格的標簽庫,用來支持OLAP表,使用戶可以執行典型的OLAP操作,如切片、切塊、上鉆、下鉆等。JPivot使用Mondrian服務器,分析結果可以導出為Excel或PDF文件格式。

          數據庫管理系統

          主要的開源工具包括MonetDB、MySQL、MaxDB和PostgreSQL等。這些數據庫都被設計用來支持BI環境。MySQL、MaxDB和PostgreSQL均支持單向的數據復制。BizGres項目的目的在于使PostgreSQL成為數據倉庫和 BI的開源標準。BizGres為BI環境構建專用的完整數據庫平臺。

          完整的BI開源解決方案

          1.Pentaho 公司的Pentaho BI 平臺

          它是一個以流程為中心的、面向解決方案的框架,具有商務智能組件。BI 平臺是以流程為中心的,其中樞控制器是一個工作流引擎。工作流引擎使用流程定義來定義在 BI 平臺上執行的商務智能流程。流程可以很容易被定制,也可以添加新的流程。BI 平臺包含組件和報表,用以分析這些流程的性能。BI 平臺是面向解決方案的,平臺的操作是定義在流程定義和指定每個活動的 action 文檔里。這些流程和操作共同定義了一個商務智能問題的解決方案。這個 BI 解決方案可以很容易地集成到平臺外部的商業流程。一個解決方案的定義可以包含任意數量的流程和操作。

          BI平臺包括一個 BI 框架、BI 組件、一個 BI 工作臺和桌面收件箱。BI 工作臺是一套設計和管理工具,集成到Eclipse環境。這些工具允許商業分析人員或開發人員創建報表、儀表盤、分析模型、商業規則和 BI 流程。Pentaho BI 平臺構建于服務器、引擎和組件的基礎之上,包括J2EE 服務器、安全與權限控制、portal、工作流、規則引擎、圖表、協作、內容管理、數據集成、多維分析和系統建模等功能。這些組件的大部分是基于標準的,可使用其他產品替換之。

          2.ObjectWeb

          該項目近日發布了SpagoBi 1.8版本。SpagoBi 是一款基于Mondrain+JProvit的BI方案,能夠通過OpenLaszlo產生實時報表,為商務智能項目提供了一個完整開源的解決方案,它涵蓋了一個BI系統所有方面的功能,包括:數據挖掘、查詢、分析、報告、Dashboard儀表板等等。SpagoBI使用核心系統與功能模塊集成的架構,這樣在確保平臺穩定性與協調性的基礎上又保證了系統具有很強的擴展能力。用戶無需使用SpagoBI的所有模塊,而是可以只利用其中的一些模塊。

          SpagoBI使用了許多已有的開源軟件,如Spago和Spagosi等。因此,SpagoBI集成了 Spago的特征和技術特點,使用它們管理商務智能對象,如報表、OLAP分析、儀表盤、記分卡以及數據挖掘模型等。SpagoBI支持BI系統的監控管理,包括商務智能對象的控制、校驗、認證和分配流程。SpagoBI采用Portalet技術將所有的BI對象發布到終端用戶,因此BI對象就可以集成到為特定的企業需求而已經選擇好的Portal系統中去。

          3.Bee項目

          該項目是一套支持商務智能項目實施的工具套件,包括ETL工具和OLAP 服務器。Bee的ETL工具使用基于Perl的BEI,通過界面描述流程,以XML形式進行存儲。用戶必須對轉換過程進行編碼。Bee的ROLAP 服務器保證多通SQL 生成和強有力的高速緩存管理(使用MySQL數據庫管理系統)。ROLAP服務器通過SOAP應用接口提供豐富的客戶應用。Web Portal作為主要的用戶接口,通過Web瀏覽器進行報表設計、展示和管理控制,分析結果可以以Excel、PDF、PNG、PowerPoint、 text和XML等多種形式導出。

          Bee項目的特點在于:

          ● 簡單快捷的數據訪問;

          ● 支持預先定義報表和實時查詢;

          ● 通過拖拽方式輕松實現報表定制;

          ● 完整報表的輕松控制;

          ● 以表和圖進行高質量的數據展示。

          posted @ 2008-02-23 23:29 edsonjava 閱讀(533) | 評論 (0)編輯 收藏
           
          java /zongfeng 
          mondrian是一個olap工具,jpviot是一個顯示它處理結果的taglib,使用這2個工具可以做復雜的統計匯總并顯示

          OLAP:Mondrian&JPviot


          olap:online analytical processing(聯機分析處理),實時的分析大量數據,其操作通常是 只讀的.online意味著即使是大量的數據,系統對查詢的響應也要足夠快.

          olap使用一種技術叫做multimensional analysis(多維分析),關系數據庫將數據存成行和列的形式,多維數據表包含軸和單元.

          mondrian包含4層:表示層,計算層,聚集層,存儲層.

          表示層:指最終呈現在用戶顯示器上的,以及與用戶之間的交互,有許多方法來展現多維數據,包括數據透視表,餅,柱,線狀圖.

          計算層:分析,驗證,執行MDX查詢.

          聚集層:一個聚集指內存中一組計算值(cell),這些值通過維列來限制.計算層發送單元請求,如果請求不在緩存中,或者不能通過旋轉聚集導出的話,聚集層向存儲層發送請求.

          聚合層是一個數據緩沖層,從數據庫來的單元數據,聚合后提供給計算層。聚合層的主要作用是提高系統的性能。

          存儲層:提供聚集單元數據和維表的成員,這些層可以不在同一機子上,但是計算和聚集層必須在同一臺機子上.

          三種需要存儲的數據:1:事實數據2:聚集3:維

          配置文件中的特定含義:
          1:cube(立方體):是維和量的集合

          2:measure(量):一個具體的測量量

          3:dimension(維):一個屬性或者一系列屬性,通過維可以將量分類

          下面是我關于jpviot的修改:jpviot是顯示mondrian的一個taglib

          問題1:讓行和列的標題顯示為中文,此問題非常簡單,只需要在你的schema中設置一下編碼即可,例如在FoodMart中設置如下

          <?xml version="1.0" encoding="gb2312"?>

          然后可以這樣描述Measure:

          <Measure name="庫存消耗" column="store_cost" aggregator="sum" formatString="#,###.00"/>

          所有帶name屬性的都可以替換成中文,jpviot會自動顯示這些中文.

          問題2:關于去掉Measure標題的問題:

          默認生成的報表中會有這么一行
          <tr>
          <th rowspan="1" colspan="2" class="corner-heading" nowrap="nowrap">&nbsp;</th><th rowspan="1" colspan="3" class="heading-heading" nowrap="nowrap"><img height="9" width="9" border="0" src="/jpivot/jpivot/table/drill-position-other.gif">Measures</th>
          </tr>

          這一行有個默認的標題是Measure,如果你不想刪除這一行,而僅僅想修改這個標題的話,可以修改
          WEB-INFclassescomtonbellerjpivotmondrianresources.properties.但是注意這個文件中內容寫成英文沒問題,如寫成中文的話應該寫成unicode,例如023這樣的形式.

          如果你要去掉這一行的話,修改配置文件和xsl恐怕做不到,我分析了其代碼,最終在代碼層次上做了修改:
          修改的代碼為com.tonbeller.jpivot.table.ColumnAxisBuilderImpl:

          將其構造函數中的setHierarchyHeader的參數修改為setHierarchyHeader(NO_HEADER);這個函數支持3個參數,我們修改后就不會顯示那個標題行了.

          問題3:生成圖表后自動生成chart表的問題:

          我測試生成圖表中的中文問題都解決了,但是每次生成chart圖時會報UTF編碼錯誤,從錯誤判斷應該是某個文件的編碼錯誤,起初根據錯誤判斷是filter的問題,可是filter那點代碼中根本不涉及編碼的問題.我將很多配置文件的編碼都改了也不行.因為那個英文例子沒問題,我查看了JFreechart的一個servlet(org.jfree.chart.servlet.DisplayChart),因為jpviot就是調用這個servlet實現繪圖的,分析這個servlet我知道它會在一個臨時目錄生成png文件,然后交給servlet寫到瀏覽器的響應中去,我找到那個臨時目錄(tomcattemp),發現里面已經生成了正確的中文圖形.從而判斷圖形生成正確,但是寫到瀏覽器中時出了問題.最后我查看能生成英文圖表的那個例子,發覺不僅僅在html中生成圖形,而且生成map.而這個map的生成全是在程序中做的,程序生成一個xml文件,通過chart.xsl解析生成map的最終html代碼.但是在程序中生成時并沒有加入編碼設置,因此問題出在生成map這兒.

          最終修改代碼如下:

          com.tonbeller.jpivot.chart.ChartComponent:

          在render函數中修改如下:

          String desc="<?xml version="1.0" encoding="gb2312"?>";
          String xchart =desc+"n"+ "<xchart>" + writeImageMap(filename, info, false) + "</xchart>";
          這樣就為xchart設置了編碼.

          問題4:修改jfreechart中的默認字體:

          com.tonbeller.jpivot.chart.ChartComponent中定義了幾種字體,但是這幾種字體都是英文字體,我將其修改為宋體:
          把所有的字體定義都改為"SimSun"
          注意到這兒并沒有玩,如果你僅僅修改程序,仍舊會出現問題,報錯說沒有適合"SimSun"的item
          同時要修改一個配置文件:WEB-INFjpivotchartchartpropertiesform.xml
          在這個配置文件中將SimSun加入其中,形式如下:

          <listBox1 type="string" modelReference="fontName" label="Title font">
          <listItem value="SansSerif" label="SansSerif"/>
          <listItem value="Serif" label="Serif"/>
          <listItem value="SimSun" label="SimSun"/>
          <listItem value="Monospaced" label="Monospaced"/>
          </listBox1>

          以上為我最近的一點心得,我會完善這篇文檔,將包含mondrian中schema的書寫方法和MDX查詢語言,歡迎大家交流
          link1:微軟的MDX中文文檔

          posted @ 2008-02-23 23:20 edsonjava 閱讀(884) | 評論 (0)編輯 收藏
           

          在xml應用中,經常將一些URL信息作為xml數據存儲,其中URL參數有可能包含有中文字符。
          當使用dom對xml數據進行解析時,可以對中文字符進行編碼。
          但如果只使用xslt來顯示xml數據時(data.xml+data.xsl),發現此時的URL會出現編碼錯誤.
          即使指定編碼類型(encoding="gb2312"),依然會出現同樣的問題.
          測試發現:是IE的緩存機制問題,IE仍會把新的頁面(所鏈接的URL)的MIME內容類型默認為text/xml

          解決方法:
          1.指定輸出文檔類型為xml文檔  (example:data.xsl)
           <xsl:output method="xml"  encoding="gb2312" media-type="text/xml" />
          2.在新的窗口打開,給聯接增加屬性,指明目標窗口為其他窗口  (example:data2.xsl)
           <xsl:attribute name="target">_blank</xsl:attribute>


          examples:


          /*** data.xml ***/

          <?xml version="1.0" encoding="gb2312"?>
          <?xml-stylesheet type="text/xsl" href="data.xsl"?>
          <root>
           <search>
            <url>http://www.google.com/search?q=</url>
            <word>xml數據</word>
           </search>
           <search>
            <url>http://www1.baidu.com/baidu?word=</url>
            <word>xml數據</word>
           </search>
           <search>
            <url>http://www.google.com/search?q=</url>
            <word>極限編程(xp)</word>
           </search>
           <search>
            <url>http://www1.baidu.com/baidu?word=</url>
            <word>極限編程(xp)</word>
           </search>
          </root>


          /*** data.xsl ***/

          <?xml version="1.0" encoding="gb2312"?>
          <xsl:stylesheet version="1.0" xmlns:xsl=" <!-- 去掉下面一句,將出現錯誤 -->
          <xsl:output method="xml"  encoding="gb2312" media-type="text/xml" />

          <xsl:template match="/">
           <xsl:apply-templates /> 
          </xsl:template>

          <xsl:template match="search">
           <xsl:element name="a">
            <xsl:attribute name="href"><xsl:value-of select="url" /><xsl:value-of select="word" /></xsl:attribute>
            <xsl:value-of select="word" />
           </xsl:element>
           <br />
          </xsl:template>

          </xsl:stylesheet>


          /*** data2.xsl ***/

          <?xml version="1.0" encoding="gb2312"?>
          <xsl:stylesheet version="1.0" xmlns:xsl="

          <xsl:template match="/">
           <xsl:apply-templates /> 
          </xsl:template>

          <xsl:template match="search">
           <xsl:element name="a">
            <xsl:attribute name="href"><xsl:value-of select="url" /><xsl:value-of select="word" /></xsl:attribute>
            <!-- 去掉下面一句,將出現錯誤 -->
            <xsl:attribute name="target">_blank</xsl:attribute>
            <xsl:value-of select="word" />
           </xsl:element>
           <br />
          </xsl:template>

          </xsl:stylesheet>

          posted @ 2008-02-23 23:08 edsonjava 閱讀(531) | 評論 (0)編輯 收藏
           
          軟件包:javax.servlet.http 
                所包含的接口:HttpServletRequest;HttpServletResponse;HttpSession;HttpSessionBindingListener;HttpSessionContext。
                所包含的類:Cookie;HttpServlet;HttpSessionBindingEvent;HttpUtils。

                一、HttpServletRequest接口
                定義\
                public interface HttpServletRequest extends ServletRequest;
                用來處理一個對Servlet的HTTP格式的請求信息。
                方法
                1、getAuthType
                public String getAuthType();
                返回這個請求的身份驗證模式。
                2、getCookies
                public Cookie[] getCookies();
                返回一個數組,該數組包含這個請求中當前的所有cookie。如果這個請求中沒有cookie,返回一個空數組。
                3、getDateHeader
                public long getDateHeader(String name);
                返回指定的請求頭域的值,這個值被轉換成一個反映自1970-1-1日(GMT)以來的精確到毫秒的長整數。
                如果頭域不能轉換,拋出一個IllegalArgumentException。如果這個請求頭域不存在,這個方法返回-1。
                4、getHeader
                public String getHeader(String name);
                返回一個請求頭域的值。(譯者注:與上一個方法不同的是,該方法返回一個字符串)
                如果這個請求頭域不存在,這個方法返回-1。
                5、getHeaderNames
                public Enumeration getHeaderNames();
                該方法返回一個String對象的列表,該列表反映請求的所有頭域名。
                有的引擎可能不允許通過這種方法訪問頭域,在這種情況下,這個方法返回一個空的列表。
                6、getIntHeader
                public int getIntHeader(String name);
                返回指定的請求頭域的值,這個值被轉換成一個整數。
                如果頭域不能轉換,拋出一個IllegalArgumentException。如果這個請求頭域不存在,這個方法返回-1。
                7、getMethod
                public String getMethod();
                返回這個請求使用的HTTP方法(例如:GET、POST、PUT)
                8、getPathInfo
                public String getPathInfo();
                這個方法返回在這個請求的URL的Servlet路徑之后的請求URL的額外的路徑信息。如果這個請求URL包括一個查詢字符串,在返回值內將不包括這個查詢字符串。這個路徑在返回之前必須經過URL解碼。如果在這個請求的URL的Servlet路徑之后沒有路徑信息。這個方法返回空值。
                9、getPathTranslated
                public String getPathTranslated();
                這個方法獲得這個請求的URL的Servlet路徑之后的額外的路徑信息,并將它轉換成一個真實的路徑。在進行轉換前,這個請求的URL必須經過URL解碼。如果在這個URL的Servlet路徑之后沒有附加路徑信息。這個方法返回空值。
                10、getQueryString
                public String getQueryString();
                返回這個請求URL所包含的查詢字符串。一個查詢字串符在一個URL中由一個“?”引出。如果沒有查詢字符串,這個方法返回空值。
                11、getRemoteUser
                public String getRemoteUser
                返回作了請求的用戶名,這個信息用來作HTTP用戶論證。
                如果在請求中沒有用戶名信息,這個方法返回空值。
                12、getRequestedSessionId
                public String getRequestedSessionId();
                返回這個請求相應的session id。如果由于某種原因客戶端提供的session id是無效的,這個session id將與在當前session中的session id不同,與此同時,將建立一個新的session。
                如果這個請求沒與一個session關聯,這個方法返回空值。
                13、getRequestURI
                public String getRequestURI();
                從HTTP請求的第一行返回請求的URL中定義被請求的資源的部分。如果有一個查詢字符串存在,這個查詢字符串將不包括在返回值當中。例如,一個請求通過/catalog/books?id=1這樣的URL路徑訪問,這個方法將返回/catalog/books。這個方法的返回值包括了Servlet路徑和路徑信息。
                如果這個URL路徑中的的一部分經過了URL編碼,這個方法的返回值在返回之前必須經過解碼。
                14、getServletPath
                public String getServletPath();
                這個方法返回請求URL反映調用Servlet的部分。例如,一個Servlet被映射到/catalog/summer這個URL路徑,而一個請求使用了/catalog/summer/casual這樣的路徑。所謂的反映調用Servlet的部分就是指/catalog/summer。
                如果這個Servlet不是通過路徑匹配來調用。這個方法將返回一個空值。
                15、getSession
                public HttpSession getSession();
                public HttpSession getSession(boolean create);
                返回與這個請求關聯的當前的有效的session。如果調用這個方法時沒帶參數,那么在沒有session與這個請求關聯的情況下,將會新建一個session。如果調用這個方法時帶入了一個布爾型的參數,只有當這個參數為真時,session才會被建立。
                為了確保session能夠被完全維持。Servlet開發者必須在響應被提交之前調用該方法。
                如果帶入的參數為假,而且沒有session與這個請求關聯。這個方法會返回空值。
                16、isRequestedSessionIdValid
                public boolean isRequestedSessionIdValid();
                這個方法檢查與此請求關聯的session當前是不是有效。如果當前請求中使用的session無效,它將不能通過getSession方法返回。
                17、isRequestedSessionIdFromCookie
                public boolean isRequestedSessionIdFromCookie();
                如果這個請求的session id是通過客戶端的一個cookie提供的,該方法返回真,否則返回假。
                18、isRequestedSessionIdFromURL
                public boolean isRequestedSessionIdFromURL();
                如果這個請求的session id是通過客戶端的URL的一部分提供的,該方法返回真,否則返回假。請注意此方法與isRequestedSessionIdFromUrl在URL的拼寫上不同。
                以下方法將被取消\

                19、isRequestedSessionIdFromUrl
                public boolean isRequestedSessionIdFromUrl();
                該方法被isRequestedSessionIdFromURL代替。

                二、HttpServletResponse接口
                定義\

                public interface HttpServletResponse extends ServletResponse
                描述一個返回到客戶端的HTTP回應。這個接口允許Servlet程序員利用HTTP協議規定的頭信息。
                成員變量
                public static final int SC_CONTINUE = 100;
                public static final int SC_SWITCHING_PROTOCOLS = 101;
                public static final int SC_OK = 200;
                public static final int SC_CREATED = 201;
                public static final int SC_ACCEPTED = 202;
                public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;
                public static final int SC_NO_CONTENT = 204;
                public static final int SC_RESET_CONTENT = 205;
                public static final int SC_PARTIAL_CONTENT = 206;
                public static final int SC_MULTIPLE_CHOICES = 300;
                public static final int SC_MOVED_PERMANENTLY = 301;
                public static final int SC_MOVED_TEMPORARILY = 302;
                public static final int SC_SEE_OTHER = 303;
                public static final int SC_NOT_MODIFIED = 304;
                public static final int SC_USE_PROXY = 305;
                public static final int SC_BAD_REQUEST = 400;
                public static final int SC_UNAUTHORIZED = 401;
                public static final int SC_PAYMENT_REQUIRED = 402;
                public static final int SC_FORBIDDEN = 403;
                public static final int SC_NOT_FOUND = 404;
                public static final int SC_METHOD_NOT_ALLOWED = 405;
                public static final int SC_NOT_ACCEPTABLE = 406;
                public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
                public static final int SC_REQUEST_TIMEOUT = 408;
                public static final int SC_CONFLICT = 409;
                public static final int SC_GONE = 410;
                public static final int SC_LENGTH_REQUIRED = 411;
                public static final int SC_PRECONDITION_FAILED = 412;
                public static final int SC_REQUEST_ENTITY_TOO_LARGE = 413;
                public static final int SC_REQUEST_URI_TOO_LONG = 414;
                public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;
                public static final int SC_INTERNAL_SERVER_ERROR = 500;
                public static final int SC_NOT_IMPLEMENTED = 501;
                public static final int SC_BAD_GATEWAY = 502;
                public static final int SC_SERVICE_UNAVAILABLE = 503;
                public static final int SC_GATEWAY_TIMEOUT = 504;
                public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
                以上HTTP產狀態碼是由HTTP/1.1定義的。
                方法
                1、addCookie
                public void addCookie(Cookie cookie);
                在響應中增加一個指定的cookie。可多次調用該方法以定義多個cookie。為了設置適當的頭域,該方法應該在響應被提交之前調用。
                2、containsHeader
                public boolean containsHeader(String name);
                檢查是否設置了指定的響應頭。
                3、encodeRedirectURL
                public String encodeRedirectURL(String url);
                對sendRedirect方法使用的指定URL進行編碼。如果不需要編碼,就直接返回這個URL。之所以提供這個附加的編碼方法,是因為在redirect的情況下,決定是否對URL進行編碼的規則和一般情況有所不同。所給的URL必須是一個絕對URL。相對URL不能被接收,會拋出一個IllegalArgumentException。
                所有提供給sendRedirect方法的URL都應通過這個方法運行,這樣才能確保會話跟蹤能夠在所有瀏覽器中正常運行。
                4、encodeURL
                public String encodeURL(String url);
                對包含session ID的URL進行編碼。如果不需要編碼,就直接返回這個URL。Servlet引擎必須提供URL編碼方法,因為在有些情況下,我們將不得不重寫URL,例如,在響應對應的請求中包含一個有效的session,但是這個session不能被非URL的(例如cookie)的手段來維持。
                所有提供給Servlet的URL都應通過這個方法運行,這樣才能確保會話跟蹤能夠在所有瀏覽器中正常運行。
                5、sendError
                public void sendError(int statusCode) throws IOException;
                public void sendError(int statusCode, String message) throws
                   IOException;
                用給定的狀態碼發給客戶端一個錯誤響應。如果提供了一個message參數,這將作為響應體的一部分被發出,否則,服務器會返回錯誤代碼所對應的標準信息。
                調用這個方法后,響應立即被提交。在調用這個方法后,Servlet不會再有更多的輸出。
                6、sendRedirect
                public void sendRedirect(String location) throws IOException;
                使用給定的路徑,給客戶端發出一個臨時轉向的響應(SC_MOVED_TEMPORARILY)。給定的路徑必須是絕對URL。相對URL將不能被接收,會拋出一個IllegalArgumentException。
                這個方法必須在響應被提交之前調用。調用這個方法后,響應立即被提交。在調用這個方法后,Servlet不會再有更多的輸出。
                7、setDateHeader
                public void setDateHeader(String name, long date);
                用一個給定的名稱和日期值設置響應頭,這里的日期值應該是反映自1970-1-1日(GMT)以來的精確到毫秒的長整數。如果響應頭已經被設置,新的值將覆蓋當前的值。
                8、setHeader
                public void setHeader(String name, String value);
                用一個給定的名稱和域設置響應頭。如果響應頭已經被設置,新的值將覆蓋當前的值。
                9、setIntHeader
                public void setIntHeader(String name, int value);
                用一個給定的名稱和整形值設置響應頭。如果響應頭已經被設置,新的值將覆蓋當前的值。
                10、setStatus
                public void setStatus(int statusCode);
                這個方法設置了響應的狀態碼,如果狀態碼已經被設置,新的值將覆蓋當前的值。
                以下的幾個方法將被取消\
                11、encodeRedirectUrl
                public String encodeRedirectUrl(String url);
                該方法被encodeRedirectURL取代。 
                12、encodeUrl
                public String encodeUrl(String url);
                該方法被encodeURL取代。 
                13、setStatus
                public void setStatus(int statusCode, String message);
                這個方法設置了響應的狀態碼,如果狀態碼已經被設置,新的值將覆蓋當前的值。如果提供了一個message,它也將會被作為響應體的一部分被發送。

                三、HttpSession接口
                定義\
                public interface HttpSession
                這個接口被Servlet引擎用來實現在HTTP客戶端和HTTP會話兩者的關聯。這種關聯可能在多外連接和請求中持續一段給定的時間。session用來在無狀態的HTTP協議下越過多個請求頁面來維持狀態和識別用戶。
                一個session可以通過cookie或重寫URL來維持。
                方法
                1、getCreationTime
                public long getCreationTime();
                返回建立session的時間,這個時間表示為自1970-1-1日(GMT)以來的毫秒數。 
                2、getId
                public String getId();
                返回分配給這個session的標識符。一個HTTP session的標識符是一個由服務器來建立和維持的唯一的字符串。
                3、getLastAccessedTime
                public long getLastAccessedTime();
                返回客戶端最后一次發出與這個session有關的請求的時間,如果這個session是新建立的,返回-1。這個時間表示為自1970-1-1日(GMT)以來的毫秒數。 
                4、getMaxInactiveInterval
                public int getMaxInactiveInterval();
                返加一個秒數,這個秒數表示客戶端在不發出請求時,session被Servlet引擎維持的最長時間。在這個時間之后,Servlet引擎可能被Servlet引擎終止。如果這個session不會被終止,這個方法返回-1。
                當session無效后再調用這個方法會拋出一個IllegalStateException。
                5、getValue
                public Object getValue(String name);
                返回一個以給定的名字綁定到session上的對象。如果不存在這樣的綁定,返回空值。
                當session無效后再調用這個方法會拋出一個IllegalStateException。
                6、getValueNames
                public String[] getValueNames();
                以一個數組返回綁定到session上的所有數據的名稱。
                當session無效后再調用這個方法會拋出一個IllegalStateException。
                7、invalidate
                public void invalidate();
                這個方法會終止這個session。所有綁定在這個session上的數據都會被清除。并通過HttpSessionBindingListener接口的valueUnbound方法發出通告。
                8、isNew
                public boolean isNew();
                返回一個布爾值以判斷這個session是不是新的。如果一個session已經被服務器建立但是還沒有收到相應的客戶端的請求,這個session將被認為是新的。這意味著,這個客戶端還沒有加入會話或沒有被會話公認。在他發出下一個請求時還不能返回適當的session認證信息。
                當session無效后再調用這個方法會拋出一個IllegalStateException。
                9、putValue
                public void putValue(String name, Object value);
                以給定的名字,綁定給定的對象到session中。已存在的同名的綁定會被重置。這時會調用HttpSessionBindingListener接口的valueBound方法。
                當session無效后再調用這個方法會拋出一個IllegalStateException。
                10、removeValue
                public void removeValue(String name);
                取消給定名字的對象在session上的綁定。如果未找到給定名字的綁定的對象,這個方法什么出不做。 這時會調用HttpSessionBindingListener接口的valueUnbound方法。
                當session無效后再調用這個方法會拋出一個IllegalStateException。
                11、setMaxInactiveInterval
                public int setMaxInactiveInterval(int interval);
                設置一個秒數,這個秒數表示客戶端在不發出請求時,session被Servlet引擎維持的最長時間。
                以下這個方法將被取消\
                12、getSessionContext
                public HttpSessionContext getSessionContext();
                返回session在其中得以保持的環境變量。這個方法和其他所有HttpSessionContext的方法一樣被取消了。

                四、HttpSessionBindingListener接口
                定義\
                public interface HttpSessionBindingListener
                這個對象被加入到HTTP的session中,執行這個接口會通告有沒有什么對象被綁定到這個HTTP session中或被從這個HTTP session中取消綁定。
                方法
                1、valueBound
                public void valueBound(HttpSessionBindingEvent event);
                當一個對象被綁定到session中,調用此方法。HttpSession.putValue方法被調用時,Servlet引擎應該調用此方法。
                2、valueUnbound
                public void valueUnbound(HttpSessionBindingEvent event);
                當一個對象被從session中取消綁定,調用此方法。HttpSession.removeValue方法被調用時,Servlet引擎應該調用此方法。

                五、HttpSessionContext接口
                定義\
                此接口將被取消\
                public interface HttpSessionContext
                這個對象是與一組HTTP session關聯的單一的實體。
                這個接口由于安全的原因被取消,它出現在目前的版本中僅僅是為了兼容性的原因。這個接口的方法將模擬以前的版本的定義返回相應的值。
                方法
                1、getSession
                public HttpSession getSession(String sessionId);
                當初用來返回與這個session id相關的session。現在返回空值。
                2、getIds
                public Enumeration getIds();
                當初用來返回這個環境下所有session id的列表。現在返回空的列表。

                六、Cookie類\
                定義\
                public class Cookie implements Cloneable
                這個類描述了一個cookie,有關cookie的定義你可以參照Netscape Communications Corporation的說明,也可以參照RFC 2109。
                構造函數
                public Cookie(String name, String value);
                用一個name-value對定義一個cookie。這個name必須能被HTTP/1.1所接受。
                以字符$開頭的name被RFC 2109保留。
                給定的name如果不能被HTTP/1.1所接受,該方法拋出一個IllegalArgumentException。
                方法
                1、getComment
                public String getComment();
                返回描述這個cookie目的的說明,如果未定義這個說明,返回空值。
                2、getDomain
                public String getDomain();
                返回這個cookie可以出現的區域,如果未定義區域,返回空值。
                3、getMaxAge
                public int getMaxAge();
                這個方法返回這個cookie指定的最長存活時期。如果未定義這個最長存活時期,該方法返回-1。
                4、getName
                public String getName();
                該方法返回cookie名。
                5、getPath
                public String getPath();
                返回這個cookie有效的所有URL路徑的前綴,如果未定義,返回空值。
                6、getSecure
                public boolean getSecure();
                如果這個cookie只通過安全通道傳輸返回真,否則返回假。
                7、getValue
                public String getValue();
                該方法返回cookie的值。
                8、getVersion
                public int getVersion();
                返回cookie的版本。版本1由RFC 2109解釋。版本0由Netscape Communications Corporation的說明解釋。新構造的cookie默認使用版本0。
                9、setComment
                public void setComment(String purpose);
                如果一個用戶將這個cookie提交給另一個用戶,必須通過這個說明描述這個cookie的目的。版本0不支持這個屬性。
                10、setDomain
                public void setDomain(String pattern);
                這個方法設置cookie的有效域的屬性。這個屬性指定了cookie可以出現的區域。一個有效域以一個點開頭(.foo.com),這意味著在指定的域名解析系統的區域中(可能是www.foo.com但不是a.b.foo.com)的主機可以看到這個cookie。默認情況是,cookie只能返回保存它的主機。
                11、setMaxAge
                public void setMaxAge(int expiry);
                這個方法設定這個cookie的最長存活時期。在該存活時期之后,cookie會被終目。負數表示這個cookie不會生效,0將從客戶端刪除這個cookie。
                   12、setPath
                public void setPath(String uri);
                這個方法設置cookie的路徑屬性。客戶端只能向以這個給定的路徑String開頭的路徑返回cookie。
                13、setSecure
                public void setSecure(boolean flag);
                指出這個cookie只能通過安全通道(例如HTTPS)發送。只有當產生這個cookie的服務器使用安全協議發送這個cookie值時才能這樣設置。
                14、setValue
                public void setValue(String newValue);
                設置這個cookie的值,對于二進制數據采用BASE64編碼。
                版本0不能使用空格、{}、()、=、,、“”、/、?、@、:以及;。
                15、setVersion
                public void setVersion(int v);
                設置cookie的版本號

                七、HttpServlet類\
                定義\
                public class HttpServlet extends GenericServlet implements 
                   Serializable
                這是一個抽象類,用來簡化HTTP Servlet寫作的過程。它是GenericServlet類的擴充,提供了一個處理HTTP協議的框架。
                在這個類中的service方法支持例如GET、POST這樣的標準的HTTP方法。這一支持過程是通過分配他們到適當的方法(例如doGet、doPost)來實現的。
                方法
                1、doDelete
                protected void doDelete(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException,
                      IOException;
                被這個類的service方法調用,用來處理一個HTTP DELETE操作。這個操作允許客戶端請求從服務器上刪除URL。這一操作可能有負面影響,對此用戶就負起責任。
                這一方法的默認執行結果是返回一個HTTP BAD_REQUEST錯誤。當你要處理DELETE請求時,你必須重載這一方法。
                2、doGet
                protected void doGet(HttpServletRequest request, 
                      HttpServletResponse response) throws ServletException,
                      IOException;
                被這個類的service方法調用,用來處理一個HTTP GET操作。這個操作允許客戶端簡單地從一個HTTP服務器“獲得”資源。對這個方法的重載將自動地支持HEAD方法。
                GET操作應該是安全而且沒有負面影響的。這個操作也應該可以安全地重復。
                這一方法的默認執行結果是返回一個HTTP BAD_REQUEST錯誤。
                3、doHead
                protected void doHead(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException,
                      IOException;
                被這個類的service方法調用,用來處理一個HTTP HEAD操作。默認的情況是,這個操作會按照一個無條件的GET方法來執行,該操作不向客戶端返回任何數據,而僅僅是返回包含內容長度的頭信息。
                與GET操作一樣,這個操作應該是安全而且沒有負面影響的。這個操作也應該可以安全地重復。
                這個方法的默認執行結果是自動處理HTTP HEAD操作,這個方法不需要被一個子類執行。 
                4、doOptions
                protected void doOptions(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException,
                      IOException;
                被這個類的service方法調用,用來處理一個HTTP OPTION操作。這個操作自動地決定支持哪一種HTTP方法。例如,一個Servlet寫了一個HttpServlet的子類并重載了doGet方法,doOption會返回下面的頭:
                Allow: GET,HEAD,TRACE,OPTIONS
                你一般不需要重載這個方法。
                5、doPost
                protected void doPost(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException,
                      IOException;
                被這個類的service方法調用,用來處理一個HTTP POST操作。這個操作包含請求體的數據,Servlet應該按照他行事。
                這個操作可能有負面影響。例如更新存儲的數據或在線購物。
                這一方法的默認執行結果是返回一個HTTP BAD_REQUEST錯誤。當你要處理POST操作時,你必須在HttpServlet的子類中重載這一方法。
                6、doPut
                protected void doPut(HttpServletRequest request, 
                      HttpServletResponse response) throws ServletException,
                      IOException;
                被這個類的service方法調用,用來處理一個HTTP PUT操作。這個操作類似于通過FTP發送文件。
                這個操作可能有負面影響。例如更新存儲的數據或在線購物。
                這一方法的默認執行結果是返回一個HTTP BAD_REQUEST錯誤。當你要處理PUT操作時,你必須在HttpServlet的子類中重載這一方法。
                7、doTrace
                protected void doTrace(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException,
                      IOException;
                被這個類的service方法調用,用來處理一個HTTP TRACE操作。這個操作的默認執行結果是產生一個響應,這個響應包含一個反映trace請求中發送的所有頭域的信息。
                當你開發Servlet時,在多數情況下你需要重載這個方法。
                8、getLastModified
                protected long getLastModified(HttpServletRequest request);
                返回這個請求實體的最后修改時間。為了支持GET操作,你必須重載這一方法,以精確地反映最后修改的時間。這將有助于瀏覽器和代理服務器減少裝載服務器和網絡資源,從而更加有效地工作。返回的數值是自1970-1-1日(GMT)以來的毫秒數。 
          默認的執行結果是返回一個負數,這標志著最后修改時間未知,它也不能被一個有條件的GET操作使用。
                9、service
                protected void service(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException,
                      IOException;
                public void service(ServletRequest request, ServletResponse response)
                      throws ServletException, IOException;
                這是一個Servlet的HTTP-specific方案,它分配請求到這個類的支持這個請求的其他方法。
                當你開發Servlet時,在多數情況下你不必重載這個方法。

                八、HttpSessionBindingEvent類\
                定義\
                public class HttpSessionBindingEvent extends EventObject
                這個事件是在監聽到HttpSession發生綁定和取消綁定的情況時連通HttpSessionBindingListener的。這可能是一個session被終止或被認定無效的結果。
                事件源是HttpSession.putValue或HttpSession.removeValue。
                構造函數
                public HttpSessionBindingEvent(HttpSession session, String name);
                通過引起這個事件的Session和發生綁定或取消綁定的對象名構造一個新的HttpSessionBindingEvent。
                方法
                1、getName
                public String getName();
                返回發生綁定和取消綁定的對象的名字。
                2、getSession
                public HttpSession getSession();
                返回發生綁定和取消綁定的session的名字。

                   九、HttpUtils類\
                定義\
                public class HttpUtils
                收集HTTP Servlet使用的靜態的有效的方法。
                方法
                1、getRequestURL
                public static StringBuffer getRequestURL(HttpServletRequest
                      request);
                在服務器上重建客戶端用來建立請求的URL。這個方法反映了不同的協議(例如http和https)和端口,但不包含查詢字符串。
                這個方法返回一個StringBuffer而不是一個String,這樣URL可以被Servlet開發者有效地修改。
                2、parsePostData
                public static Hashtable parsePostData(int len, 
                      ServletInputstream in);
                解析一個包含MIME類型application/x-www-form-urlencoded的數據的流,并創建一個具有關鍵值-數據對的hash table。這里的關鍵值是字符串,數據是該字符串所對應的值的列表。一個關鍵值可以在POST的數據中出現一次或多次。這個關鍵值每出現一次,它的相應的值就被加入到hash table中的字符串所對應的值的列表中。
                從POST數據讀出的數據將經過URL解碼,+將被轉換為空格以十六進制傳送的數據(例如%xx)將被轉換成字符。
                當POST數據無效時,該方法拋出一個IllegalArgumentException。
                3、parseQueryString
                public static Hashtable parseQueryString(String s);
                解析一個查詢字符串,并創建一個具有關鍵值-數據對的hash table。這里的數據是該字符串所對應的值的列表。一個關鍵值可以出現一次或多次。這個關鍵值每出現一次,它的相應的值就被加入到hash table中的字符串所對應的值的列表中。
                從查詢字符串讀出的數據將經過URL解碼,+將被轉換為空格以十六進制傳送的數據(例如%xx)將被轉換成字符。
                當查詢字符串無效時,該方法拋出一個IllegalArgumentException。
          posted @ 2007-07-26 16:34 edsonjava 閱讀(458) | 評論 (0)編輯 收藏
           
          主站蜘蛛池模板: 隆尧县| 安庆市| 吉木乃县| 专栏| 沽源县| 明光市| 威宁| 韶山市| 鄂州市| 义马市| 西贡区| 襄城县| 弋阳县| 洪雅县| 宁明县| 唐海县| 磐安县| 东平县| 齐河县| 依兰县| 宁安市| 怀来县| 金塔县| 叙永县| 华容县| 二连浩特市| 台中市| 资源县| 长海县| 福泉市| 昌都县| 增城市| 深泽县| 扎囊县| 伊金霍洛旗| 开平市| 康平县| 白城市| 泰和县| 荣昌县| 财经|