<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 10, 文章 - 0, 評論 - 7, 引用 - 0
    數據加載中……

    2007年6月7日

    關于appfuse的探討

          項目在緊張的生活中很快就要結束了,一直以來,都是由于工作的繁忙,沒有時間去寫自己的blog.這段時間終于可以稍微閑下來了,覺得應該把這一階段的工作總結一下了,但是拿起鍵盤,思緒卻有些散亂,想寫的很多,卻也不知道怎么來寫,還是慢慢來吧.
       首先說一下整體框架appfuse,它是集成了當今最流行的web應用框架的更高層次的web開發框架.也可以說是一個web開發的基本平臺,它將當前最流行的一些技術,比如hibernate,spring,struts,DBUnit,ant,log4j,xdoclet,sitemesh,velocity,jstl,webwork,等等都集成了進來,在國內能夠將這些都應用進來的并不多見.

    待續....

    posted @ 2007-06-07 23:56 LiuTing 閱讀(247) | 評論 (0)編輯 收藏

    2007年5月29日

    JS常見函數

    1.常規函數  
      javascript常規函數包括以下9個函數:  
      (1)alert函數:顯示一個警告對話框,包括一個OK按鈕。  
      (2)confirm函數:顯示一個確認對話框,包括OK、Cancel按鈕。  
      (3)escape函數:將字符轉換成Unicode碼。  
      (4)eval函數:計算表達式的結果。  
      (5)isNaN函數:測試是(true)否(false)不是一個數字。  
      (6)parseFloat函數:將字符串轉換成符點數字形式。  
      (7)parseInt函數:將符串轉換成整數數字形式(可指定幾進制)。  
      (8)prompt函數:顯示一個輸入對話框,提示等待用戶輸入。例如:  
      (9)unescape函數:解碼由escape函數編碼的字符。  
      2.數組函數  
      javascript數組函數包括以下4個函數:  
      (1)join函數:轉換并連接數組中的所有元素為一個字符串。例:  
     
     程序代碼  
        function JoinDemo()  
        {  
         var a, b;  
         a = new Array(0,1,2,3,4);  
         b = a.join("-");//分隔符  
         return(b);//返回的b=="0-1-2-3-4"  
        }   
       
     (2)langth函數:返回數組的長度。例:  
           
     程序代碼  
    function LengthDemo()  
        {  
         var a, l;  
         a = new Array(0,1,2,3,4);  
         l = a.length;  
         return(l);//l==5  
        }   
     
      (3)reverse函數:將數組元素順序顛倒。例:  
          
     程序代碼  
    function ReverseDemo()  
       {  
        var a, l;  
        a = new Array(0,1,2,3,4);  
        l = a.reverse();  
        return(l);  
       }   
      (4)sort函數:將數組元素重新排序。例:  
           
     程序代碼  
    function SortDemo()  
        {  
         var a, l;  
         a = new Array("X" ,"y" ,"d", "Z", "v","m","r");  
         l = a.sort();  
         return(l);  
        }   
      3.日期函數  
      javascript日期函數包括以下20個函數:  
      (1)getDate函數:返回日期的“日”部分,值為1~31。例:  
          
     程序代碼  
    function DateDemo()  
       {  
        var d, s = "Today's date is: ";  
        d = new Date();  
        s += (d.getMonth() + 1) + "/";  
        s += d.getDate() + "/";  
        s += d.getYear();  
        return(s);  
       }   
      (2)getDay函數:返回星期幾,值為0~6,其中0表示星期日,1表示星期一,...,6表示星期六。例:  
          
     程序代碼  
    function DateDemo()  
       {  
        var d, day, x, s = "Today is: ";  
        var x = new Array("Sunday", "Monday", "Tuesday");  
        var x = x.concat("Wednesday","Thursday", "Friday");  
        var x = x.concat("Saturday");  
        d = new Date();  
        day = d.getDay();  
        return(s += x[day]);  
       }   
      (3)getHouse函數:返回日期的“小時”部分,值為0~23。例。  
          
     程序代碼  
    function TimeDemo()  
       {  
        var d, s = "The current local time is: ";  
        var c = ":";  
        d = new Date();  
        s += d.getHours() + c;  
        s += d.getMinutes() + c;  
        s += d.getSeconds() + c;  
        s += d.getMilliseconds();  
        return(s);  
       }   
      (4)getMinutes函數:返回日期的“分鐘”部分,值為0~59。見上例。  
      (5)getMonth函數:返回日期的“月”部分,值為0~11。其中0表示1月,2表示3月,...,11表示12月。見前面的例子。  
      (6)getSeconds函數:返回日期的“秒”部分,值為0~59。見前面的例子。  
      (7)getTime函數:返回系統時間。  
          
     程序代碼  
    function GetTimeTest()  
       {  
        var d, s, t;  
        var MinMilli = 1000 * 60;  
        var HrMilli = MinMilli * 60;  
        var DyMilli = HrMilli * 24;  
        d = new Date();  
        t = d.getTime();  
        s = "It's been " 
        s += Math.round(t / DyMilli) + " days since 1/1/70";  
        return(s);  
       }   
      (8)getTimezoneOffset函數:返回此地區的時差(當地時間與GMT格林威治標準時間的地區時差),單位為分鐘。  
          
     程序代碼  
    function TZDemo()  
       {  
        var d, tz, s = "The current local time is ";  
        d = new Date();  
        tz = d.getTimezoneOffset();  
     
        if (tz 的鏈接點的名稱,另一個函數link設定的URL地址。  
      (2)big函數:將字體加到一號,與...標簽結果相同。  
      (3)blink函數:使字符串閃爍,與...標簽結果相同。  
      (4)bold函數:使字體加粗,與...標簽結果相同。  
      (5)charAt函數:返回字符串中指定的某個字符。  
      (6)fixed函數:將字體設定為固定寬度字體,與...標簽結果相同。  
      (7)fontcolor函數:設定字體顏色,與標簽結果相同。  
      (8)fontsize函數:設定字體大小,與標簽結果相同。  
      (9)indexOf函數:返回字符串中第一個查找到的下標index,從左邊開始查找。  
      (10)italics函數:使字體成為斜體字,與...標簽結果相同。  
      (11)lastIndexOf函數:返回字符串中第一個查找到的下標index,從右邊開始查找。  
      (12)length函數:返回字符串的長度。(不用帶括號)  
      (13)link函數:產生一個超級鏈接,相當于設定的URL地址。  
      (14)small函數:將字體減小一號,與...標簽結果相同。  
      (15)strike函數:在文本的中間加一條橫線,與...標簽結果相同。  
      (16)sub函數:顯示字符串為下標字(subscript)。  
      (17)substring函數:返回字符串中指定的幾個字符。  
      (18)sup函數:顯示字符串為上標字(superscript)。  
      (19)toLowerCase函數:將字符串轉換為小寫。  
      (20)toUpperCase函數:將字符串轉換為大寫。  
     
    //校驗是否全由數字組成  
     
     程序代碼  
    function isDigit(s)  
    {  
    var patrn=/^[0-9]{1,20}$/;  
    if (!patrn.exec(s)) return false 
    return true 
    }  
     
    //校驗登錄名:只能輸入5-20個以字母開頭、可帶數字、“_”、“.”的字串  
     
     程序代碼  
    function isRegisterUserName(s)  
    {  
    var patrn=/^[a-zA-Z]{1}([a-zA-Z0-9]|[._]){4,19}$/;  
    if (!patrn.exec(s)) return false 
    return true 
    }  
     
    //校驗用戶姓名:只能輸入1-30個以字母開頭的字串  
     
     程序代碼  
    function isTrueName(s)  
    {  
    var patrn=/^[a-zA-Z]{1,30}$/;  
    if (!patrn.exec(s)) return false 
    return true 
    }  
     
    //校驗密碼:只能輸入6-20個字母、數字、下劃線  
     
     程序代碼  
    function isPasswd(s)  
    {  
    var patrn=/^(\w){6,20}$/;  
    if (!patrn.exec(s)) return false 
    return true 
    }  
     
    //校驗普通電話、傳真號碼:可以“+”開頭,除數字外,可含有“-”  
     
     程序代碼  
    function isTel(s)  
    {  
    //var patrn=/^[+]{0,1}(\d){1,3}[ ]?([-]?(\d){1,12})+$/;  
    var patrn=/^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,12})+$/;  
    if (!patrn.exec(s)) return false 
    return true 
    }  
     
    //校驗手機號碼:必須以數字開頭,除數字外,可含有“-”  
     
     程序代碼  
    function isMobil(s)  
    {  
    var patrn=/^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,12})+$/;  
    if (!patrn.exec(s)) return false 
    return true 
    }  
     
    //校驗郵政編碼  
     
     程序代碼  
    function isPostalCode(s)  
    {  
    //var patrn=/^[a-zA-Z0-9]{3,12}$/;  
    var patrn=/^[a-zA-Z0-9 ]{3,12}$/;  
    if (!patrn.exec(s)) return false 
    return true 
    }  
     
    //校驗搜索關鍵字  
     
     程序代碼  
    function isSearch(s)  
    {  
    var patrn=/^[^`~!@#$%^&*()+=|\\\][\]\{\}:;\'\,.<>/?]{1}[^`~!@$%^&()+=|\\\][\]\{\}:;\'\,.<>?]{0,19}$/;  
    if (!patrn.exec(s)) return false 
    return true 
    }  
     
     程序代碼  
    function isIP(s) //by zergling  
    {  
    var patrn=/^[0-9.]{1,20}$/;  
    if (!patrn.exec(s)) return false 
    return true 
    }  

    posted @ 2007-05-29 18:03 LiuTing 閱讀(297) | 評論 (0)編輯 收藏

    2007年5月25日

    DISPALYTAG的用法

    1) Caption指標題
    2) name:數據源
    3) defaultsort:排序列,一般不需要
    4) defaultorder:排序方式
    5) class:表格顯示的樣式
    6) varTotals:需要統計(總計)
    7) decorator="totals":表示使用指定的decorator?,F在僅在同時使用小計、合計時用到,自己也可以定制。
    8) <display:column 部分:
      property指數據中的列名
      title指顯示的標題
      format指數據的格式化樣式,
      total表示該字段是否需要作統計。
      style="width:20%"可以設置寬度。
      也可以用
      <display:column title="請假時間">
      <fmt:formatDate value="${currentRowObject.QJSJ}" pattern="yyyy-MM-dd"/>
      </display:column>表現。
      group="1"表示進行group的字段。
    9) 在表格中建立一個連接:
      <display:column title="部別">
      <a href="<c:out value="${pageContext.request.contextPath}"/>
      /holidayDefaultSearchStatView.do?type=
      <c:out value="${currentRowObject.CJDM}"/>&SYD=
      <c:out value="${currentRowObject.DWDM}"/>" target="_blank">
      <c:out value="${currentRowObject.DWMC}"/>
      </a>
      </display:column>
    10) 由于該tag只有合計時,沒有合計那一列,所以實現的時候以<display:footer>實現。
      可以通過totalMap對象獲取合計的數據,如totalMap.colomn1獲取合計的第一列數值。
    11) 標題頭不顯示<display:setProperty name="basic.show.header" value="false" />
    12) 自己定制表頭:<display:caption>
       使用decorator:
       <jsp:scriptlet>
       org.displaytag.decorator.TotalTableDecorator totals =
       new org.displaytag.decorator.TotalTableDecorator();
           totals.setTotalLabel("合計");
           totals.setSubtotalLabel("小計");
           pageContext.setAttribute("totals", totals);
       </jsp:scriptlet>
    實例:
    <display:caption>這是表標題</display:caption>
     <display:table
      name="${model.rowToColumnStatResult}" defaultsort="1"
      class="simple" defaultorder="ascending" varTotals="totalMap">
      <display:column property="GCWZ" title="部門"/>
       <c:forEach items="${model.YList.YList}" var="yColumn">
       <c:forEach items="${model.rowToColumnStatResult[0]}"
          var="mapEntry">
        <c:if test="${mapEntry.key == yColumn}">
         <th>
           <display:column property="${mapEntry.key}"
           title="${mapEntry.key}"
           format="{0,number,####.##}" total="true"/>
         </th>
        </c:if>
       </c:forEach>
       </c:forEach>
      <display:column property="小計"
          title="小計"
          format="{0,number,####.##}" total="true"/>
     <display:footer>
     <tr>
      <td>總計</td>
      <c:forEach items="${model.YList.YColumn}" var="yColumn">
      <td><fmt:formatNumber value="${totalMap[yColumn]}"
            pattern="####.##"/>
      </td>
      </c:forEach>
     </tr>
     </display:footer>
    </display:table>
     

    另外一個例子:
    <display:table name="${model.statResult}" class="simple"
     varTotals="totalMap">
     <display:column property="XMMC" title="項目名稱" />
     <display:column property="KSRQ" title="開始日期" />
     <display:column property="FZRXM" title="負責人姓名" />
     <display:column property="GKDW" title="掛靠單位" />
     <display:column property="JFLY" title="經費來源" />
     <display:column property="XMZJF" title="項目總經費" total="true" />
     <display:column property="DNDKJF" title="當年到款經費" total="true"/>
     <display:footer>
      <tr><td colspan="5">總計</td>
       <td>
        <fmt:formatNumber value="${totalMap.column6}"
         pattern="####.####" />
       </td>
       <td>
        <fmt:formatNumber value="${totalMap.column7}"
         pattern="####.####" />
       </td>
      </tr>
     </display:footer>
    </display:table>
    總計某一列的方法:
    ${totalMap.column?}    ?為該列號
    colspan="5":表示這個單元格占5個單元格
    項目名稱 開始日期  負責人姓名 掛靠單位 經費來源 項目總經費 當年到款經費
                                                       531      400
                                                       151       10
    -------------------------------------
    總計                              682     500 

    posted @ 2007-05-25 10:42 LiuTing 閱讀(756) | 評論 (0)編輯 收藏

    2007年5月20日

    DWRUtils API 使用方法

    $("precloneNode1suf") 取得該對象;

    DWRUtil.selectRange("selectRangeBasic", 5, 15) 選中selectRangeBasic文本框里面從第五個字符到第15個字符之間的字符.

    DWRUtil._getSelection("selectRangeBasic") 得到selectRangeBasic文本框里選中的字符.

    var arrayFive = [ 'One', 'Two', 'Three', 'Four', 'Five' ];
    DWRUtil.addOptions('addOptionsBasic', arrayFive); 將數組添加到下拉菜單里面去;

    DWRUtil.getValue('addOptionsBasic') 得到 addOptionsBasic 對象的值;
    DWRUtil.getValue("precloneNode1Inner1suf", { textContent:true }); 后面加個參數,在 precloneNode1Inner1suf元素為"UL" 時,它返回了元素里面得值,也就是說去掉了HTML標簽部分.

    DWRUtil.getText('addOptionsBasic') 得到下拉框 addOptionsBasic 顯示的文本;

    var arrayObject = [
    { name:'One', value:'1' },
    { name:'Two', value:'2' },
    { name:'Three', value:'3' },
    { name:'Four', value:'4' },
    { name:'Five', value:'5' }
    ];
    DWRUtil.addOptions('addOptionsObject1', arrayObject, "name"); 將數組添加到下拉菜單里面去;后面的參數是確定那個是給用戶顯示的文本,同時也是值;

    DWRUtil.addOptions('addOptionsObject1', arrayObject, "name","value"); 同上,不過后面參數是: 3=文本;4=值;

    var map = { one:1, two:2, three:3, four:4, five:5 };
    DWRUtil.addOptions('addOptionsMap1', map); 同上, one 是值;1 是文本;
    DWRUtil.addOptions('addOptionsMap1', map,true); 同上, 1 是值;one 是文本;

    -------------------------------------------------------------------------------------
    <ul id="removeItems">
    <li>One</li><li>Two</li><li>Three</li><li>Four</li><li>Five</li>
    </ul>

    如果是列表顯示,如上;則上面所有方法和select 下拉框使用一樣;
    -------------------------------------------------------------------------------------
    DWRUtil.cloneNode('cloneNode1', { idPrefix:'pre', idSuffix:'suf' });克隆一個節點,參數一為要克隆的節點的id,第二個參數是在克隆的節點id前面加pre,后面加suf.(注意:如果該節點有子節點的話,子節點的名字也一樣加)

    DWRUtil.addRows(id, array, cellfuncs, [options]);
    原理:

    for each member in array
    for each function in cellfuncs
    create cell from cellfunc(array[i])
    循環數組,循環函數,建立單元調用函數;(順序決定)

    例如:
    DWRUtil.addRows('addRowsBasic', arrayFive, [
    function(data) { return data; },
    function(data) { return data.toUpperCase(); },
    function(data) {
    var input = document.createElement("input");
    input.setAttribute("type", "button");
    input.setAttribute("value", "DOM Test");
    input.setAttribute("onclick", "alert('" + data + "');");
    return input;
    },
    function(data) { return "<input type='button' value='innerHTML Test' onclick='alert(\"" + data + "\");'>"; }
    ]);

    高級部分:
    第四個參數為對單元的高級操作,主要下面的兩個方法;
    function defaultRowCreator(options) {
    return document.createElement("tr");
    };

    function defaultCellCreator(options) {
    return document.createElement("td");
    };

    例子:
    DWRUtil.addRows( "demo2",[ 'Africa', 'America', 'Asia', 'Australasia', 'Europe' ] , cellFuncs, {
    rowCreator:function(options) {
    var row = document.createElement("tr");
    var index = options.rowIndex * 50;
    row.style.color = "rgb(" + index + ",0,0)";
    return row;
    },
    cellCreator:function(options) {
    var td = document.createElement("td");
    var index = 255 - (options.rowIndex * 50);
    td.style.backgroundColor = "rgb(" + index + ",255,255)";
    td.style.fontWeight = "bold";
    return td;
    }
    });

    其中 options 參數的屬性可用的為:(沒試過,自己試試吧)

    rowData: the element value from the array (the same for all cells in a row)
    rowIndex: the key (if map) or index (if array) from the collection
    rowNum: The row number counting from 0 in this section (so if you are using tbody, it counts rows in the tbody and not the whole table)
    data: The 'computed' data value for the cell (cellCreators only)
    cellNum: The cell number that we are altering counting from 0 (cellCreators only)


    DWRUtil.setValues(); 批量設置值;
    var settings = {
    setValuesDiv:"setValuesDiv",
    setValuesSpan:"setValuesSpan",
    setValuesSelect:"two",
    setValuesText:"setValuesText",
    setValuesPassword:"AB",
    setValuesTextarea:"setValuesTextarea",
    setValuesButton1:"B1-Two",
    setValuesButton2:"B2-Two",
    setValuesRadio1:true,
    setValuesRadio2:false,
    setValuesRadio3:"one",
    setValuesRadio4:"two",
    setValuesCheckbox1:true,
    setValuesCheckbox2:false
    };
    DWRUtil.setValues(settings);

    DWRUtil.getValues(empty);批量獲取值;
    var empty = {
    setValuesDiv:null,
    setValuesSpan:null,
    setValuesSelect:null,
    setValuesText:null,
    setValuesPassword:null,
    setValuesTextarea:null,
    setValuesButton1:null,
    setValuesButton2:null,
    setValuesRadio1:null,
    setValuesRadio2:null,
    setValuesRadio3:null,
    setValuesRadio4:null,
    setValuesCheckbox1:null,
    setValuesCheckbox2:null
    };
    DWRUtil.getValues(empty);

    DWRUtil.useLoadingMessage("Ping");//類似gmail那個樣子,在右上角顯示加載"ping";可用自定樣式,具體查詢;
    http://getahead.ltd.uk/dwr/browser/util/useloadingmessage

    DWRUtil.toDescriptiveString("id",數字);彈出調試信息,數字為0,1,2.一級比一級高.

    DWRUtil.onReturn(event, submitFunction);一般在form表單里面,防止在文本框上按回車就提交表單.
    例如:
    <input type="text"
    onkeypress="DWRUtil.onReturn(event, submitFunction)"/>
    <input type="button" onclick="submitFunction()"/>

    posted @ 2007-05-20 12:46 LiuTing 閱讀(613) | 評論 (1)編輯 收藏

    DWR框架實現Ajax

          Ajax是時下比較流行的一種web界面設計新思路,其核心思想是從瀏覽器獲取XMLHttp對象與服務器端進行交互. DWR(Direct Web Remoting)就是實現了這種Ajax技術的一種web框架. 最近做的項目中我也將它用上了,感覺很是方便,比如動態生成javascript代碼,隱藏的http協議,java代碼和javascript交互的是javascript的對象(或字符串).  下面是我整理的文檔.
      DWR主要由兩部門組成。javascript與web服務器通信并更新web頁;運行在web服務器的Servlet處理請求并把響應發回瀏覽器。

       1  .  配置web.xml
    <servlet>
      <servlet-name>dwr-invoker</servlet-name>
      <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
    </servlet>
    <servlet-mapping>
      <servlet-name>dwr-invoker</servlet-name>
      <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>

      2    當我們想看dwr自動生成的測試頁時,可在java代碼
    servlet中加
    <init-param>
      <param-name>debug</param-name>
      <param-value>true</param-value>
    </init-param>

    這個參數DWR默認是false.如果選擇true.我們可以通過url http://localhost:port/app/dwr ,你就可以看到你部署的每個DWR class。并且可以測試java代碼的每個方法是否運行正常。為了安全考慮,在正式環境下你一定把這個參數設為false.

    3  log信息配置

    我喜歡用log4j輸出日志,那么在log4j.properties下加,log4j.logger.uk.ltd.getahead.dwr = debug。這樣可以看DWR的調試日志。

    4  配置dwr.xml (和web.xml同目錄)
     
    <create creator="new" javascript="JDate">
    <param name="class" value="java.util.Date"/>
    </create>

    這里的多數元素都是可選的 - 你真正必須知道的是指定一個creator和一個javascript名字。

    creator屬性 是必須的 - 它用來指定使用那種創造器。

    默認情況下DWR1.1有8種創造器。它們是:

    • new: 用Java的new關鍵字創造對象。
    • none: 它不創建對象,看下面的原因。 (v1.1+)
    • scripted: 通過BSF使用腳本語言創建對象,例如BeanShell或Groovy。
    • spring: 通過Spring框架訪問Bean。
    • jsf: 使用JSF的Bean。 (v1.1+)
    • struts: 使用Struts的FormBean。 (v1.1+)
    • pageflow: 訪問Beehive或Weblogic的PageFlow。 (v1.1+)

    javascript屬性 用于指定瀏覽器中這個被創造出來的對象的名字。你不能使用Javascript的關鍵字。

    scope屬性 非常類似servlet規范中的scope。 它允許你指定這個bean在什么生命范圍。選項有"application", "session", "request" 和"page"。這些值對于Servlet和JSP開發者來說應該相當熟悉了。

    scope屬性是可選的。默認是"page"。如果要使用"session"需要cookies。當前的DWR不支持ULR重寫。

    param元素 被用來指定創造器的其他參數,每種構造器各有不同。例如,"new"創造器需要知道要創建的對象類型是什么。每一個創造器的參數在各自的文檔中能找到。請查看上面的鏈接。

    include和exclude元素 允許創造器來限制類中方法的訪問。一個創造器必須指定include列表或exclude列表之一。如果是include列表則暗示默認的訪問策略是"拒絕";如果是exclude列表則暗示默認的訪問策略是"允許"。


    5 dwr.jar下載后放lib下

    源碼淺析

    dwr的設計很象webwork2的設計,隱藏http協議,擴展性,兼容性及強。

    通過研究uk.ltd.getahead.dwr.DWRServlet這個servlet來研究下dwr到底是如何工作的。

    <servlet>
      <servlet-name>dwr-invoker</servlet-name>
      <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
    </servlet>
    <servlet-mapping>
      <servlet-name>dwr-invoker</servlet-name>
      <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>

    這樣/dwr/*下的所有的請求都是由這個servlet來處理,到底生理了什么呢,我們還是以例子來說明吧.

    1 web服務器啟動,DWRServlet init()方法調用,init主要做了以下工作。
    設置日志級別、實例化DWR用到的單例類(這些類在jvm中只有一個實例對象)、讀去配置文件(包括dwr.jar包中的dwr.xml,WEB-INF/dwr.xml. config*.xml)。
    2 請求處理
    DWRServlet.doGet, doPost方法都調用processor.handle(req, resp)方法處理。Processor對象在init()方法中已經初始化了。 

    代碼
    public void handle(HttpServletRequest req, HttpServletResponse resp)  
            throws IOException  
        {  
            String pathinfo = req.getPathInfo();  
            if(pathinfo == null || pathinfo.length() == 0 || pathinfo.equals("/"))  
            {  
                resp.sendRedirect(req.getContextPath() + req.getServletPath() + '/' + "index.html");  
            } else 
            if(pathinfo != null && pathinfo.equalsIgnoreCase("/index.html"))  
            {  
                doIndex(req, resp);  
            } else 
            if(pathinfo != null && pathinfo.startsWith("/test/"))  
            {  
                doTest(req, resp);  
            } else 
            if(pathinfo != null && pathinfo.equalsIgnoreCase("/engine.js"))  
            {  
                doFile(resp, "engine.js", "text/javascript");  
            } else 
            if(pathinfo != null && pathinfo.equalsIgnoreCase("/util.js"))  
            {  
                doFile(resp, "util.js", "text/javascript");  
            } else 
            if(pathinfo != null && pathinfo.equalsIgnoreCase("/deprecated.js"))  
            {  
                doFile(resp, "deprecated.js", "text/javascript");  
            } else 
            if(pathinfo != null && pathinfo.startsWith("/interface/"))  
            {  
                doInterface(req, resp);  
            } else 
            if(pathinfo != null && pathinfo.startsWith("/exec"))  
            {  
                doExec(req, resp);  
            } else 
            {  
                log.warn("Page not found. In debug/test mode try viewing /[WEB-APP]/dwr/");  
                resp.sendError(404);  
            }  
        } 

    dwr/*處理的請求也就這幾種。

    (1)dwr/index.html,dwr/test/這種只能在debug模式下使用,調試用。
    dwr/engine.js,dwr/util.js,dwr/deprecated.js當這個請求到達,從dwr.jar包中讀取文件流,響應回去。(重復請求有緩存)
    (2)當dwr/interface/這種請求到來,(例如我們在index.html中的 <script type='text/javascript' src='dwr/interface/JDate.js'></script>)DWR做一件偉大的事。把我們在WEB-INF/dwr.xml中的
    <create creator="new" javascript="JDate">
    <param name="class" value="java.util.Date"/>
    </create>
    java.util.Date轉化為javascript函數。
    http://localhost:port/simpledwr/dwr/interface/JDate.js看看吧。
    細節也比較簡單,通過java反射,把方法都寫成javascript特定的方法。(我覺得這些轉換可以放到緩存里,下次調用沒必要再生成一遍,不知道作者為什么沒這樣做)。
    (3)dwr/exec
    javascript調用方法時發送這種請求,可能是XMLHttpRequest或IFrame發送。
    當然,javascript調用的方法簽名與java代碼一致,包括參數,還有javascript的回調方法也傳到了服務器端,在服務器端很容易實現。回調方法的java的執行結果 返回類似 <script>callMethod(結果)<script>的javascript字符串,在瀏覽器執行。哈,一切就這么簡單,巧妙。

    我這里還有DWR中文文檔. http://www.tkk7.com/Files/LiuTing/DWR中文文檔.rar





    posted @ 2007-05-20 12:45 LiuTing 閱讀(4335) | 評論 (4)編輯 收藏

    Acegi工作流程

    任何一個安全系統都包括authentication和authorization兩部分,Acegi相同。

    第一部分:authentication

    1、acegi通過AuthenticationProcessingFilter攔截login請求獲取Principal和Credential信息(通俗一點就是用戶名和密碼);

    2、驗證用戶名密碼,由這個Filter調用認證管理器AuthenticatiomManager進行驗證。

    AuthenticatiomManager本身并不具備驗證的功能,它相當與是一個驗證控制器,由它來管理驗證的過程及方式。AuthenticatiomManager是通過調用provider來進行驗證的,一個manager中可以具有多個provider,但只要有一個provider驗證通過,manager就認為驗證成功。

    這部分要明白三點:一,provider是可以配置進去的,因為acegi是基于spring的;二是AuthenticatiomManager是可以被重寫的,你可以將manager改成你自己希望的控制器;三,好好利用event,這是標準的observer模式。acegi中的設計模式研究將在以后的貼子中討論。

    3、provider進行驗證。

    provider是真正的驗證模塊,并且決定了驗證的模式。provider目前acegi提供了dao、jaas,cas,x509,ldap等幾種驗證方式,這些驗證方式的具體內容可以查閱acegi的文檔。provider驗證通過后將Authentication對象返回。

    4、AuthenticationProcessingFilter將對象保存到ContextHolder中。Authentication部分結束。

    第二部分:authorization

    1、用戶提交請求,攔截器FilterSecurityInterceptor攔截請求,攔截器是一個Filter.

    2 、鑒權,攔截器調用AccessDecisionManager進行鑒權。

    AccessDecisionManager是通過投票的方式來決定是否有權限訪問資源。所謂投票就要包括投票的參與者和投票的策略。

    投票的參與者decisionVoters,這是AccessDecisionManager的一個屬性。decisionVoter能從某一個角度決定用戶是否能訪問資源,例如RoleVoter來判斷用戶的角色是否有權限訪問資源,MaxuserVoter來決定某個資源的訪問用戶數是否已經達到了最大值等。

    投票策略。投票的策略是通過不同的AccessDecisionManager來實現的,例如acegi提供的AffirmativeBased對象,這個對象的策略就是只要有一個投票通過就全體通過。UnanimousBased對象的策略是必須全體投票通過才能通過。但在大多數情況下acegi提供的AccessDecisionManager不能滿足我們的要求,這就需要我們去實現AccessDecisionManager接口,去定制適合自己項目的策略。

    3、投票。投票對象必須實現AccessDecisionVoter接口。投票對象關注的是某一方面的決定權,如果投票通過則Vote方法來完成的。vote方法必須返回一個int型的數據代表投票結果,它們是AccessDecisionVoter的三個靜態成員屬性:ACCESS_ABSTAIN,,ACCESS_DENIED和ACCESS_GRANTED,它們分別是棄權,否決和贊成。
     

    安全攔截器

      攔截器如何工作
      MethodInvocation攔截器
      FilterInvocation攔截器

    認證

      認證請求
      認證管理器
      Authentication Provider

    授權

      Access Decision Manager
      Voting Decision Manager
      授權管理推薦

    ContextHolder的用戶接口

      用戶接口目標
      HTTP會話認證
      HTTP Basic認證

    posted @ 2007-05-20 12:44 LiuTing 閱讀(647) | 評論 (1)編輯 收藏

    使用Acegi時獲取用戶信息的幾個函數

    1 /**
     2    * 取得當前用戶名
     3    *  @return
     4     */

     5    public   static  String getUsername() {
     6     Context context = ContextHolder.getContext();
     7      if (context != null ) {
     8        if (context  instanceof  SecureContext) {
     9         SecureContext sc = (SecureContext)context;
    10         Authentication auth = sc.getAuthentication();
    11          if (auth != null ) {
    12           Object principal = auth.getPrincipal();
    13            if (principal  instanceof  UserDetails)  {
    14              return  ((UserDetails)principal).getUsername();
    15           }
    else {
    16              return  principal.toString();
    17           }

    18         }

    19       }

    20     }

    21      return   null ;
    22   }

    23    /**
    24    * 取得當前用戶密碼
    25    *  @return
    26     */

    27    public   static  String getPassword() {
    28     Context context = ContextHolder.getContext();
    29      if (context != null ) {
    30        if (context  instanceof  SecureContext) {
    31         SecureContext sc = (SecureContext)context;
    32         Authentication auth = sc.getAuthentication();
    33          if (auth != null ) {
    34           Object principal = auth.getPrincipal();
    35            if (principal  instanceof  UserDetails)  {
    36              return  ((UserDetails)principal).getPassword();
    37           }
    else {
    38              return   null ;
    39           }

    40         }

    41       }

    42     }

    43      return   null ;
    44   }

    45    /**   */ /**
    46    * 取得當前用戶session?。椋?br>47    *  @return  sessionid or null
    48     */

    49    public   static  String getSessionID() {
    50     Context context = ContextHolder.getContext();
    51      if (context != null ) {
    52        if (context  instanceof  SecureContext) {
    53         SecureContext sc = (SecureContext)context;
    54         Authentication auth = sc.getAuthentication();
    55          if (auth != null ) {
    56           Object details = auth.getDetails();
    57            if (details  instanceof  WebAuthenticationDetails)  {
    58              return  ((WebAuthenticationDetails)details).getSessionId();
    59           }
    else {
    60              return   null ;
    61           }

    62         }

    63       }

    64     }

    65      return   null ;
    66   }

    posted @ 2007-05-20 12:43 LiuTing 閱讀(365) | 評論 (0)編輯 收藏

    Acegi使用2

    流程說完了,接下對上面提到的問題解釋一下:

    引用

    先使用URL攔截的方式去對付大多數的情況,然后少數URL搞不定的再加一個接口,讓Action自己去判別。這樣用兩個攔截器對Action進行攔截,如果Action實現了hasPermission接口,那么就交給Action自己判斷,如果Action沒有該接口,就查找內部的URL和權限的對照表來判斷。

     

    這個情況比較復雜,因為是要對Action進行調用,所以要看使用的web框架來定奪。是用不同Web框架要是用不同的Web框架攔截器。所以恐怕acegi力不從心,挺多在filter里面配置一下是否要是用Action自身校驗。但是想法很好,贊。

     

    引用

    你怎么把信息有效的傳遞給Web層和其他的Facade層進行用戶友好性的提示處理?

     

    acegi校驗失敗的時候會拋出AuthenticationException異常,然后放在session里面,
    在錯誤轉向頁面可以這樣是用

    代碼
    <%= ((AuthenticationException) session.getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %>    
    <%= session.getAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_USERNAME_KEY) %>    
    <%= session.getAttribute(SecurityEnforcementFilter.ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY) %> 

    不過這么用實在太難看了,暈了??梢宰约河胻ag來搞定

     

     

    引用

    很多系統需要根據權限不同,生成不同的UI組件(例如管理員的菜單和普通用戶菜單就肯定不一樣),這也需要在Web層的View進行控制。

    acegi對View的處理就是使用tag,原來的acegi好像沒有什么tag,簡直是爛,現在有了tag,說一下是用的方法,但是說實話他的tag實在是不夠強。

     

    老版的web.xml

    代碼
    1<taglib>   
    2  <taglib-uri>http://acegisecurity.sf.net/authz</taglib-uri>   
    3  <taglib-location>/WEB-INF/authz.tld</taglib-location>   
    4</taglib>  

    在頁面中使用
    代碼
    1<authz:authorize ifAllGranted="ROLE_SUPERVISOR">   
    2<td>   
    3<HREF="del.htm?id=<c:out value="/${contact.id}"/>">Del</A>   
    4</td>   
    5</authz:authorize>  

    ifAllGranted是說所有的權限都有,用','分割權限
    可以替換成ifAnyGranted: ifNotGranted:

     

     

    代碼
    1<authz:authentication operation="username"/>   

     

    這個是用來顯示你的權限信息的。

     

    代碼
    1<authz:acl domainObject="${contact}" hasPermission="16,1">   
    2<td><HREF="<c:url value="del.htm"><c:param name="contactId"   
    3value="${contact.id}"/></c:url>">Del</A></td>   
    4</authz:acl>  

    posted @ 2007-05-20 12:42 LiuTing 閱讀(493) | 評論 (0)編輯 收藏

    Acegi使用1

    首先要配置一個filter,這個filter用一個代理bean寫在了spring里面,其實根正常的filter沒有任何區別。

    代碼
    1<bean id="securityEnforcementFilter"   
    2    class="org.acegisecurity.intercept.web.SecurityEnforcementFilter">   
    3    <property name="filterSecurityInterceptor">   
    4        <ref local="filterInvocationInterceptor" />   
    5    </property>   
    6    <property name="authenticationEntryPoint">   
    7        <ref local="authenticationProcessingFilterEntryPoint" />   
    8    </property>   
    9</bean>  

     

    "filterInvocationInterceptor" 是一個攔截器,說是攔截器,其實就是在filter里面執行一下他的攔截方法,這里可沒有什么aop.
    authenticationEntryPoint 交驗失敗的時候轉到的地方,為什么說是地方,因為通過配置可以轉到其它的url甚至其它的協議下(http 轉到 https等等)
     
    代碼
     1<bean id="authenticationProcessingFilterEntryPoint"   
     2    class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">   
     3    <property name="loginFormUrl">   
     4        <value>/error.security</value>   
     5    </property>   
     6    <property name="forceHttps">   
     7        <value>false</value>   
     8    </property>   
     9</bean>  
    10

     

    這個就是失敗的時候轉到的地方,我們可以配置url和是否使用https

     

    代碼
     1<bean id="filterInvocationInterceptor"   
     2    class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">   
     3    <property name="authenticationManager">   
     4        <ref bean="authenticationManager" />   
     5    </property>   
     6    <property name="accessDecisionManager">   
     7        <ref local="httpRequestAccessDecisionManager" />   
     8    </property>   
     9    <property name="objectDefinitionSource">   
    10        <value>   
    11            CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON    
    12            PATTERN_TYPE_APACHE_ANT    
    13            /index.jsp=ROLE_ANONYMOUS,ROLE_USER    
    14            /j_acegi_switch_user=ROLE_SUPERVISOR   
    15            /login.security=ROLE_ANONYMOUS,ROLE_USER                /test.do=ROLE_CODER   
    16            /**.do*=ROLE_USER    
    17        </value>   
    18    </property>   
    19</bean>  

     

    這個就是前面提到的攔截器。簡單解釋一下:
    authenticationManager 在acegi里面的主要作用就是管理維護用戶的權限角色等信息,比方說想要用戶的ROLE就要在這里面拿了。里面配置了多種全縣的來源,可以從DAO里面來(就是數據庫里面),可以是cookies里面的,也可以是匿名的權限,每種權限都以一種Provider的形式提供:

    代碼
     1<bean id="authenticationManager"   
     2    class="org.acegisecurity.providers.ProviderManager">   
     3    <property name="providers">   
     4        <list>   
     5            <ref local="daoAuthenticationProvider" />   
     6            <ref local="anonymousAuthenticationProvider" />   
     7            <ref local="rememberMeAuthenticationProvider" />   
     8        </list>   
     9    </property>   
    10</bean>

     

    objectDefinitionSource在acegi里面就是配置權限信息,說明哪一個url需要什么權限才能訪問,acegi默認用<value>來表示,其實這正是acegi的不足之處,還好能夠補救。我來說明一下:
    我們知道在spring里面<value>標簽比較特殊,spring首先找到這個屬性的類型,然后把value里面的內容以String的類型取出來(Spring做了一下包裝,為TypedString)。然后根據這個屬性的類型找他的Editer,然后用Editer來處理String為需要的類型。但是我們不希望用String來表達url,很明顯url里面有=就不會玩了。我們可以把這個信息寫到數據庫里面,然后讀取,這里面不說了以前有一位高手已經解釋過了。

    接下來就是httpRequestAccessDecisionManager了,AccessDecisionManager在acegi里面是決策者,就是根據你所擁有的權限和訪問URL需要的權限來決定你到底能不能訪問。

     

    代碼
     1<bean id="httpRequestAccessDecisionManager"   
     2    class="org.acegisecurity.vote.AffirmativeBased">   
     3    <property name="allowIfAllAbstainDecisions">   
     4        <value>false</value>   
     5    </property>   
     6    <property name="decisionVoters">   
     7        <list>   
     8            <ref bean="roleVoter" />   
     9        </list>   
    10    </property>   
    11</bean>  

     

    決策者里面是投票者,這個上面已經解釋過了,一個投票者校驗一種權限。整個流程已經說完了。

    posted @ 2007-05-20 12:41 LiuTing 閱讀(405) | 評論 (0)編輯 收藏

    Eclipse報表插件birt

     

    1. BIRT 概述

    BIRT是一個Eclipse-based開放源代碼報表系統。它主要是用在基于JavaJ2EEWeb應用程序上。BIRT主要由兩部分組成:一個是基于Eclipse的報表設計和一個可以加到你應用服務的運行期組件。BIRT同時也提供一個圖形報表制作引擎。

        使用BIRT,能制作出多樣化的報表到你的應用中。比如:列表 lists ,圖表 charts,混合報表 Compound Reports,交叉表(二維表)Crosstabs(二維報表目前在BIRT 2.1.1 還未實現,但在以后的版本中將會實現此功能)。

    2. BIRT的安裝

    2.1>birt的安裝

    Eclipse 3.1
    支持 BIRT 2.0

    Eclipse 3.2 支持 BIRT 2.1

     

    目前我使用的版本是BIRT 2.1.1BIRT的安裝有很多的方法。

    方法一:

    Eclipse的官方網站http://download.eclipse.org/birt/downloads去下載 BIRT 插件(birt-report-designer-all-in-one-2_1_1),解壓后,它就是一個擁有 BIRT插件的Eclipse。如果你已經安裝了Eclipse,那么把下載的文件夾的內容拷到所對應的 Eclipse 的文件夾里(pluginsfeatures兩個目錄),之后的第一次啟動是通過DOS進入到Eclipse目錄,啟動 Eclipse -clean 命令,此命令是清除 Eclipse 緩存里的記錄并啟動Eclipse。這也是最簡單的安裝BIRT方法。

     

    方法二:

        BIRT 2.1開始,可以在 Eclipse 里直接下載。[幫助]à[軟件更新]à[查找并安裝]

     

    方法三:

        如果你的 Eclipse 已經安裝或者不想使用方法一安裝,可以進行分別安裝的方法。EMF, GEF BIRT 都是需要通過 Eclipse download page下載的。請注意以下的配置要求:

    • BIRT 2.0.2
    • Eclipse 3.1
    • GEF 3.1.
    • EMF 2.1.
    • JRE 1.4.2/JRE 1.5.
    • BIRT 2.1/2.1.1
    • Eclipse 3.2.
    • GEF 3.2.
    • EMF 2.2.
    • JRE 1.4.2/JRE 1.5.
    • BIRT 2.2M4 and higher
    • Eclipse 3.3.
    • GEF 3.3.
    • EMF 2.3.
    • JRE 1.5.

    GEF:圖形編輯框架,是一個通過 BIRT UI 使用的Eclipse 插件

    EMF:用來制作圖表的框架

    具體的安裝和配置請參考 Eclipse官方網站 這里我還推薦一個BIRT 2.0.1的安裝視頻 希望對大家有所幫助。

    注意:iTextAsian.jar 是為了支持用PDF輸出時亞洲人的字體。prototype.js 是安裝 BIRT 2.0.2 或者更早的版本使用的,目前版本不需要了。

    提示:我個人使用的是方法一,首先安裝比較方便,其次如果使用方法二,在Eclipse [幫助]à[幫助內容] 里沒有關于 BIRT 的幫助文檔,這樣對學習不是很方便。

     2.2    birt版本升級

    1.刪除在 plugins 目錄下的所有以 org.eclipse.birt 開頭的文件。

    2.
    按照上面的方法一進行安裝。

    3.重新啟動 Eclipse -clean

     2.3  語言包安裝

        目前 BIRT2.1.1 已經有中文語言包。下載完畢以后把對應的目錄 copy 到對應的 Eclipse 目錄下,然后 Eclipse -clean 啟動。

      

    3. BIRT應用

        在這里我提供了一個 “BIRT中文教程”,在Eclipse官方網站也有它的演示視頻,Customers.rptdesign 是做好的報表。

     

    JDBC Drivers

        以上例子介紹的是使用“示例數據庫”的數據源,在大多數情況下我們使用的是自己的JDBC driver,下面介紹連接 Oracle 數據庫。

        打開 Eclipse 后進入 [窗口]à[打開透視圖]à[報表設計],新建項目 [文件]à[新建]à[項目],選擇“業務智能和報表工具”à“報表項目”,起項目名。新建的項目上,右鍵 新建報表,給報表起名字,報表的后綴名是 .rptdesign

        [數據源]à[新建數據源],選擇“JDBC數據源”(別忘了給數據源起名字),“管理驅動程序”à“添加”,把所需要的數據庫 jar 包添加進來。選擇oracle.jdbc.driver.OracleDriver ( v1.0),寫上正確的數據庫 URL,用戶名,密碼,點擊“測試連接”,顯示 連接成功。

     

    報表的種類有很多,具體的制作過程參考[幫助]à[幫助內容]

     

    提示:交叉表即二維報表在目前BIRT 2.1.1 還未實現,但在以后的版本中正在計劃實現此功能。

     

    4. BIRT部署

    BIRT 2.1.1所對應使用的部署工具是birt-runtime-2_1_1,可以到 Eclipse 官方網站下載。

     
    4.1. tomcat 部署

    我使用的版本是 tomcat 5.5,步驟如下:

    1)      mail.jar activation.jar拷到Tomcat 5.5\common\lib

    2)      iTextAsian.jar itext-1.3.jar拷到

    WebViewerExample\WEB-INF\platform\plugins\com.lowagie.itext\lib

    3)      連接數據庫的包拷到

    WebViewerExample\WEB-INF\platform\plugins\org.eclipse.birt.report.data.oda.jdbc_2.1.1.v20060922-1058\drivers

    4)      WebViewerExample整個目錄copy Tomcat 5.5\webapps,可以更改文件夾名。

    5)      完成的報表可以直接復制到根目錄下,也可以新建文件夾目錄。

     

    現在BIRT支持兩種瀏覽報表模式,frameset是支持顯示分頁的,采用Ajax技術。run暫不支持顯示分頁,直接輸出HTML流。比較一下它們的區別,如下:

    http://localhost:8080/WebViewerExample/frameset?__report=Customers.rptdesign

    http://localhost:8080/WebViewerExample/run?__report=Customers.rptdesign

    注意:

    a)      問號后面的是雙下劃線

    b)      以上報表是放在根目錄下,如果是放在自己新建的目錄比如 myreport URL應是:

    http://localhost:8080/WebViewerExample/run?__report=myreport/Customers.rptdesign

     
    4.2. Weblogic Server 部署

    我使用的版本是 Weblogic Server 9.2,它是 BEA WebLogic 產品的一部分。BEA WebLogic Server 是一個功能豐富、基于標準的現成的企業 J2EE應用服務器。

    Weblogic Server 有很多的域組成,medrec wl_server 是其中自帶的域,也可以自己創建新的域。域中可以包含許多服務器,在服務器中可以部署許多的應用程序。域有一個默認的服務器,它是管理服務器。每個域中的管理服務器是唯一的,其他創建的服務器叫受管服務器。

    Weblogic Server 的安裝就不多做介紹了,主要介紹它的配置和部署。下面介紹一下新建域和部署的步驟:

    1)      運行開始 -> 程序 -> BEA Products -> Tools -> Configuration Wizard

    2)      選擇 Create a new WebLogic domainNext。

    3)      Select Domain Source 界面保持默認,Next。

    4)      User name 處輸入用戶名,如 user,password 輸入密碼,如12345678(密碼要求 8 位),Next

    5)      Configure Server Start Mode and JDK 界面中保持默認,即 JDK 選擇的是“Sun SDK 1.5.0_04 @ C:\BEA\jdk150_04,注意這里若選擇“Other JDK”配置比 SDK 1.5.0_04 更高的版本,服務器啟動時將會出現異常,所以最好保持默認,然后 Next

    6)      Customize Environment and Services Settings 界面中默認為 No,Next。

    7)      Domain name 處輸入 mydomain,點擊 Create。

    8)      完成后點擊 Done 關閉 Configuration Wizard 對話框。

    9)      運行開始 -> 程序 -> BEA Products -> User Projects -> mydomain -> Start Admin Server for Weblogic Server Domain,啟動創建域的服務器。如果最后顯示 <Server started in RUNNING mode> 則說明服務器啟動成功。

    10) 在地址欄輸入 http://localhost:7001/console 進入管理控制臺,輸入剛才的用戶名和密碼。點擊 更改中心 的[鎖定并編輯],域結構 中的[部署],點擊[安裝]。找到你要部署的應用程序,之后都為默認,最后點完成。在更改頁面上點擊[保存]完成所需的更改后,單擊 更改中心 中的[激活更改]。注意:只有點擊了[激活更改]后才真正保存了更改。某些在管理控制臺中所做的更改在激活后立即生效。有些更改需要重新啟動此更改影響到的服務器或模塊。后面的這些更改稱為非動態更改。非動態更改在管理控制臺中由此警告圖標表示: 如果對非動態配置設置進行了編輯,則只有在重新啟動服務器之后,所有對動態配置設置所進行的編輯才會生效。

    11) 點擊 域結構 中的[部署],啟動剛才部署的應用程序。

    12) 在地址欄中輸入 http://localhost:7001/部署程序名在web中顯示應用程序。

     

        BIRT的部署方法基本和上面步驟相同,注意一點,在部署前將

    commons-logging.jar 拷入 WebViewerExample 中的 lib 包中,否則最后顯示會報錯。

     

        Weblogic Server 的部署方法有很多,weblogic.Deployer、管理控制臺、WLST 等等。剛才介紹的管理控制臺的部署,它是一個可視化的界面,用起來比較方便。

     

    推薦:在這里推薦使用一種應用程序的目錄管理方法,新建目錄結構如下:

    C:myApplication

    app

    plan

    將你的應用程序放入此目錄

    部署完后將會再此目錄下自動產生plan.xml文件

    用此目錄有利于很好的管理配置文件。

     

    關于 Weblogic 的更多詳細資料,我這里推薦幾個比較好的官方學習網站:

    www.bea.com.cn          bea的產品網站

    edocs.bea.com.cn       bea的比較系統的學習網站

    dev2dev.bea.com.cn      一般介紹bea的最新技術,動態等的網站
     
    4.3. web外觀顯示

        部署好的報表頁面顯示樣式是固定的,在多數情況下我們都希望修改外觀,下面將對此做簡單介紹。

    Webcontent是主要文件夾:

    1)      Webcontent中的ajax目錄,完成了在web上顯示的報表分頁的功能。

    2)      Styles目錄中的style.css是整個報表在web上顯示的外觀,包括工具條顏色,字體。文件注釋很清楚,具體修改可以參見注釋。

    3)      pages目錄pages/control/ NavigationbarFragment.jsp 分頁那一條工具欄的 JSP pages/control/ ToolbarFragment.jsp 工具按紐JSP,可以修改以保留自己想要使用的功能按紐。pages/control/ ProgressBarFragment.jsp 它是顯示剛開始讀取報表時,顯示條的樣式。

    4)      Layout目錄 FramesetFragment.jsp 可以修改報表標題。

     

    WEB-INF/web.xml文件中,BIRT_VIEW_REPORT_ROOT 是配置報表路徑的屬性,如果沒有配置則是默認路徑:$tomcat$\webapps\birt

        目前在web上顯示的所有的都是英文。項目有一個資源文件,打包在lib/viewservlets.jar中,…/…/resource/messages.properties文件中。顯示中文的解決方法是,用unicode轉換器把要顯示的中文事先轉換好,然后替換資源文件中的英文。

     

    5. BIRT總結

    BIRT是目前比較常用也是比較方便,效率較高的報表制作工具。當然其發展時間不長,所以還有很多的缺陷和未完善的地方,之后的版本也在不斷改進,因此我也將會一直跟蹤它的技術發展,不斷更新我的文檔。

    posted @ 2007-05-20 12:40 LiuTing 閱讀(4583) | 評論 (1)編輯 收藏

    主站蜘蛛池模板: 日韩激情淫片免费看| 亚洲欧美第一成人网站7777| 亚洲日韩乱码中文字幕| 亚洲女初尝黑人巨高清| 国产一区视频在线免费观看| 91精品免费在线观看| 中文精品人人永久免费| 男人免费视频一区二区在线观看| 久久精品国产亚洲av麻豆图片| 亚洲av日韩av不卡在线观看| 久久亚洲高清综合| 亚洲第一视频在线观看免费| 卡一卡二卡三在线入口免费| 91在线品视觉盛宴免费| 2021精品国产品免费观看| 久久免费高清视频| 一个人免费视频观看在线www| 免费人人潮人人爽一区二区 | 免费播放在线日本感人片| 黄色网址免费在线| 老司机亚洲精品影院在线观看| 亚洲一区AV无码少妇电影| 亚洲一区在线观看视频| 亚洲成AV人综合在线观看| 91亚洲国产在人线播放午夜| 亚洲尹人香蕉网在线视颅| 日产亚洲一区二区三区| 亚洲欧洲日产韩国在线| 亚洲成人福利在线| 久久精品国产亚洲αv忘忧草| 亚洲卡一卡二卡乱码新区| 亚洲精品123区在线观看| 亚洲熟妇无码AV| 国产精品亚洲专区无码唯爱网| 国产精品亚洲va在线观看| 国产精品久久久久久亚洲小说| 日韩在线视频免费| 你是我的城池营垒免费观看完整版| a级毛片毛片免费观看永久| 久久精品中文字幕免费| 91频在线观看免费大全|