array's profilearray yaoBlogLists Tools Help

array yao

java is a simplehearted language, it seems to me

在Linux上使用msmtp和mutt发邮件

1, 软件介绍

msmtp是一个smtp client 用于把邮件发送到smtp server 所以前提是要有smtp server 它不能单独发送邮件。

mutt 是一个邮件编辑器,用于编写邮件,添加附件等,编写完成后使用msmtp 发送到 smtp server

 

 

2, 安装软件

mutt 默认已经安装在sles 10 中。

准备软件包msmtp-1.4.16.tar.bz2,使用如下命令安装。

# tar jxvf msmtp-1.4.16.tar.bz2

# ./configure --prefix=/usr/local/msmtp

# make

# make install

如果没有安装make,可以用 software management 安装,选择seach 输入make 即可发现该软件包。

3, 配置 msmtp

新建文件 msmtprc

# cd /usr/local/msmtp/etc

# vi msmtprc

 

编辑文件 msmtprc msmtp 能够连接到10.0.0.3 smtp 服务器

# Set default values for all following accounts.

defaults

# The SMTP server of the provider

account default

host 10.0.0.3

port 25

auth lonin

user yaohaogang@lonbi.cn

password ******

from yaohaogang@lonbi.cn

 

 

 

 

 

4, 配置 mutt

编辑文件 /etc/Muttrc mutt 使用 msmtp 发信

修改如下选项,有注释去掉

set sendmail=”/usr/local/msmtp/bin/msmtp”

set from=yaohaogang@lonbi.cn

 

 

5, 测试发信

 

# mutt

SLES10.1上安装oracle9i

1. 准备必须的安装包

gcc_old-2.95.3-175.2.i586.rpm

j2re-1_3_1_19-linux-i586.bin

ship_9204_linux_disk1.cpio.gz

ship_9204_linux_disk2.cpio.gz

ship_9204_linux_disk3.cpio.gz

 

2. 创建oracle用户oracle和组dba

 

3. 解压oracle安装包

# cd /home/oracle

# gunzip ship_9204_linux_disk1.cpio.gz

# gunzip ship_9204_linux_disk2.cpio.gz

# gunzip ship_9204_linux_disk3.cpio.gz

# cpio –idmv < ship_9204_linux_disk1.cpio

# cpio –idmv < ship_9204_linux_disk2.cpio

# cpio –idmv < ship_9204_linux_disk3.cpio

完成后将看到三个文件夹,Disk1,Disk2,Disk3

 

4. 安装jre1.3.1

# cd /home/oracle

# chmod 544 j2re-1_3_1_19-linux-i586.bin

# ./ j2re-1_3_1_19-linux-i586.bin

# mv jre1.3.1_19 /opt/

 

5. 配置java环境

/etc/profile.d/ 文件夹下新建文件java.sh输入如下内容

JRE_HOME=/opt/jre1.3.1_19

PATH=$PATH:$JRE_HOME/bin

export PATH JRE_HOME JAVA_FONTS

 

6. 安装其他软件包

检查如下软件包有没有安装

# rpm –q gcc glibc-devel libstdc++ libstdc++-devel cpp compat

没有安装的使用 install software 安装

 

7. 安装gcc_old

# cd /home/oracle

# rpm –ivh gcc_old-2.95.3-175.2.i586.rpm

# mv /usr/bin/gcc /usr/bin/gcc3

# mv /opt/gcc295/bin/gcc /usr/bin/gcc

 

8. 配置oracle的环境

  /home/oracle  文件夹下新建 .bash_profile  的文件,输入如下内容

ORACLE_BASE=/opt/oracle

ORACLE_HOME=$ORACLE_BASE/920

ORACLE_SID=lonbi

LD_LIBRARY_PATH=$ORACLE_HOME/lib

PATH=$PATH:$ORACLE_HOME/bin

export ORACLE_BASE ORACLE_HOME ORACLE_SID LD_LIBRARY_PATH PATH

 

9. 修改oracle安装文件oraparam.ini

# cd /home/oracle/Disk1/install/linux/

JRE_LOCATION=/opt/jre1.3.1_19

 

10. 重新启动linux系统, 启动后使用 oracle 用户登录

 

11. 开始安装

~> cd /home/oracle

~> Disk1/runInstaller

 

12. 选择 Custom 安装,有两个组件无法安装

去掉 Legato NetWorker Single Server 6.1.0.0.0 前面的勾

去掉 Oracle Enterprise Manager Products 9.2.0.1.0  前面的勾

 

13. 是否创建数据库,选择  No

 

14. 几个报错信息,忽略,单击 continue

 

15. Oracle Net Configration Assistant 安装错误,输入如下命令解决错误信息

~>su root

password : ***

# cd /opt/oracle/920

# rm JRE

# ln –s /opt/jre1.3.1_19 JRE

# cd /opt/oracle/920/JRE/bin

# ln –s java jre

# cd i386/native_threads

# ln –s java jre

 

选择 Oracle Net Configration Assistant 单击 Retry,其他两个组件未解决

 

16. 创建数据库

在命令行下输入命令

~> dbca

 

17. 配置网络服务和监听

~> netca

 

18 启动数据库的方法

~> sqlplus /nolog

Sql> connect / as sysdba

Sql> startup

 

将数据库表中数据导出为txt文件存储过程

CREATE OR REPLACE PROCEDURE P_EXPORT_TO_TXT(P_PATH IN VARCHAR2,       --目标文件夹,必须在数据库中创建
                                            P_TABLE_PATTERN IN VARCHAR2     --导出表的名称,可以是部分名称


    ) IS   


 
    L_CTX   DBMS_XMLGEN.CTXHANDLE;        --会话
    L_FILE  UTL_FILE.FILE_TYPE;             --输出文件
    L_XML   CLOB;       --获得表的xml
   
    L_AMOUNT BINARY_INTEGER;        --读取数量
    L_OFFSET INTEGER;                         --读取位置
    L_BUFFER VARCHAR2(20000);                --读取获得内容
   
   
   
    --获得数据库中的表名
    TYPE CURSOR_TYPE IS REF CURSOR;
    SQL_TABS VARCHAR2(200) := 'SELECT TABLE_NAME FROM USER_ALL_TABLES
            WHERE TABLE_NAME LIKE :1';
       
       
    CURSOR_TABS CURSOR_TYPE;   
    ITER_TABS USER_ALL_TABLES.TABLE_NAME%TYPE;
   
   
   
   
    L_PARSER XMLPARSER.PARSER;    --将clob转换为xml文档
   
    L_DOC XMLDOM.DOMDOCUMENT;     --xml文档
   
    L_NL_ROW XMLDOM.DOMNODELIST;      --节点列表
    L_NL_COL XMLDOM.DOMNODELIST;        --节点列表
   
   
    L_N XMLDOM.DOMNODE;         --节点
   
   
   
    I NUMBER(3);        --迭代变量
    J NUMBER(3);
   
    L_TXT CLOB;                   --xml中提取的文本
 
 

BEGIN

  OPEN CURSOR_TABS FOR SQL_TABS USING P_TABLE_PATTERN || '%';
 
    LOOP
          FETCH CURSOR_TABS INTO ITER_TABS;
          EXIT WHEN CURSOR_TABS%NOTFOUND;   

 
            -- CREATE XML CONTEXT.
            L_CTX := DBMS_XMLGEN.NEWCONTEXT('SELECT * FROM ' || ITER_TABS);
           
           
            -- SET PARAMETERS TO ALTER DEFAULT ROWSET AND ROW TAG NAMES AND DEFAULT CASE.
            DBMS_XMLGEN.SETROWSETTAG(L_CTX, ITER_TABS);
            DBMS_XMLGEN.SETROWTAG(L_CTX, 'ROW');

           
            -- CREATE THE XML DOCUMENT.
            L_XML := DBMS_XMLGEN.GETXML(L_CTX, 2);
            DBMS_XMLGEN.CLOSECONTEXT(L_CTX);
           
           
           
           
            --提取XML数据
           
            L_PARSER := XMLPARSER.NEWPARSER;
           
            XMLPARSER.PARSECLOB(L_PARSER, L_XML);
           
            --获得xml文档
            L_DOC := XMLPARSER.GETDOCUMENT(L_PARSER);
           
            -- FREE
            DBMS_LOB.FREETEMPORARY(L_XML);
            XMLPARSER.FREEPARSER(L_PARSER);
           
           

            --获得表数据节点
            L_N := XMLDOM.GETLASTCHILD(XMLDOM.MAKENODE(L_DOC));
           
           
            --DBMS_OUTPUT.PUT_LINE('TABLENAME:  ' || XMLDOM.GETNODENAME(L_N));
           
            --获得row节点类表
            L_NL_ROW := XMLDOM.GETCHILDNODES(L_N);
           
            SELECT TO_CLOB(CHR(10)) INTO L_TXT FROM DUAL;
           
            --从每个row中提取col的数据,append到l_txt后边
            I := 0;
            FOR I IN 0 .. XMLDOM.GETLENGTH(L_NL_ROW)-1 LOOP
                L_N := XMLDOM.ITEM(L_NL_ROW, I);
               
                L_NL_COL := XMLDOM.GETCHILDNODES(L_N);
               
                J := 0;
                FOR J IN 0 .. XMLDOM.GETLENGTH(L_NL_COL)-1 LOOP
                      L_N := XMLDOM.ITEM(L_NL_COL, J);
                     
                     
                      DBMS_LOB.APPEND(L_TXT, TO_CLOB(XSLPROCESSOR.VALUEOF(L_N,'text()')));
                     
                      DBMS_LOB.APPEND(L_TXT, CHR(9) );
                     
                      --DBMS_OUTPUT.PUT_LINE('NODENAME:  ' || XSLPROCESSOR.VALUEOF(L_N,'TEXT()'));
                     
               
                END LOOP;     
               
                DBMS_LOB.APPEND(L_TXT, CHR(10) );        
               
            END LOOP;
           
           
           
           
            --DBMS_OUTPUT.PUT_LINE('NL LENGTH:   ' || XMLDOM.GETLENGTH(L_NL_ROW));
           
           
            --将l_txt写入文件
            L_FILE := UTL_FILE.FOPEN(P_PATH, ITER_TABS || '.TXT', 'W');
           
           
             
             /* DBMS_OUTPUT.PUT_LINE('LENGTH:  ' || DBMS_LOB.GETLENGTH(L_XML));*/
             
            L_AMOUNT  := 10000;
            L_OFFSET := 1;


            LOOP
              EXIT WHEN L_AMOUNT <> 10000;
           
              DBMS_LOB.READ(L_TXT, L_AMOUNT, L_OFFSET, L_BUFFER); 
               
              UTL_FILE.PUT_LINE(L_FILE, L_BUFFER, TRUE);
              
                 
              /*DBMS_OUTPUT.PUT_LINE('L_OFFSET:  ' || L_OFFSET);
              DBMS_OUTPUT.PUT_LINE('L_AMOUNT:  ' || L_AMOUNT);*/    
          
              L_OFFSET := L_OFFSET + L_AMOUNT;  


            END LOOP; 
           
            UTL_FILE.FCLOSE(L_FILE); 
            DBMS_LOB.FREETEMPORARY(L_TXT);
 
 
      END LOOP;
  CLOSE CURSOR_TABS;
 
 
/*EXCEPTION
   WHEN NO_DATA_FOUND THEN
  
      DBMS_OUTPUT.PUT_LINE('END OF CHAPTER REACHED.');
      UTL_FILE.FCLOSE(L_FILE);*/



 
END P_EXPORT_TO_TXT;


将数据库表中数据导出为XML存储过程

-- Create directory
create or replace directory DIR_C
  as 'C:\test';
 
 
 CREATE OR REPLACE PROCEDURE P_EXPORT_TO_XML(P_PATH IN VARCHAR2,     --目标文件夹,必须在数据库中创建
                                            P_TABLE_PATTERN IN VARCHAR2   --导出表的名称,可以是部分名称


    ) IS    


 
    L_CTX   DBMS_XMLGEN.CTXHANDLE;    --会话
    L_FILE  UTL_FILE.FILE_TYPE;       --输出文件
    L_XML   CLOB;                         --获得表的xml
    
    L_AMOUNT BINARY_INTEGER;        --读取数量
    L_OFFSET INTEGER;             --读取位置
    L_BUFFER VARCHAR2(20000);         --读取获得内容
 
 
    --获得数据库中的表名
    TYPE CURSOR_TYPE IS REF CURSOR;
    SQL_TABS VARCHAR2(200) := 'SELECT TABLE_NAME FROM USER_ALL_TABLES
            WHERE TABLE_NAME LIKE :1';
        
        
    CURSOR_TABS CURSOR_TYPE;    
    ITER_TABS USER_ALL_TABLES.TABLE_NAME%TYPE;

BEGIN

  OPEN CURSOR_TABS FOR SQL_TABS USING P_TABLE_PATTERN || '%';
    LOOP
          FETCH CURSOR_TABS INTO ITER_TABS;
          EXIT WHEN CURSOR_TABS%NOTFOUND;    

 
            -- CREATE XML CONTEXT.
            L_CTX := DBMS_XMLGEN.NEWCONTEXT('SELECT * FROM ' || ITER_TABS);
            
            
            -- SET PARAMETERS TO ALTER DEFAULT ROWSET AND ROW TAG NAMES AND DEFAULT CASE.
            DBMS_XMLGEN.SETROWSETTAG(L_CTX, ITER_TABS);
            DBMS_XMLGEN.SETROWTAG(L_CTX, 'ROW');

            
            -- CREATE THE XML DOCUMENT.
            L_XML := DBMS_XMLGEN.GETXML(L_CTX);
            DBMS_XMLGEN.CLOSECONTEXT(L_CTX);

            
            L_FILE := UTL_FILE.FOPEN(P_PATH, ITER_TABS || '.XML', 'W');
            
            
              
             /* DBMS_OUTPUT.PUT_LINE('LENGTH:  ' || DBMS_LOB.GETLENGTH(L_XML));*/
              
            L_AMOUNT  := 10000;
            L_OFFSET := 1;
            
            
            

            --将xml写入文件
            LOOP
              EXIT WHEN L_AMOUNT <> 10000;
            
              DBMS_LOB.READ(L_XML, L_AMOUNT, L_OFFSET, L_BUFFER);  
                
              UTL_FILE.PUT_LINE(L_FILE, L_BUFFER, TRUE);
               
                  
              /*DBMS_OUTPUT.PUT_LINE('L_OFFSET:  ' || L_OFFSET);
              DBMS_OUTPUT.PUT_LINE('L_AMOUNT:  ' || L_AMOUNT);*/     
           
              L_OFFSET := L_OFFSET + L_AMOUNT;   


            END LOOP;  
            
            UTL_FILE.FCLOSE(L_FILE);  
 
 
      END LOOP;
  CLOSE CURSOR_TABS;
 
 
/*EXCEPTION
   WHEN NO_DATA_FOUND THEN
   
      DBMS_OUTPUT.PUT_LINE('END OF CHAPTER REACHED.');
      UTL_FILE.FCLOSE(L_FILE);*/



 
END P_EXPORT_TO_XML;


 

 
 
exec P_EXPORT_TO_TXT('DIR_C');

oracle 数字金额到中文大写金额转换函数

create or replace function f_to_yuan(p_number in number) return varchar2 is
  result varchar2(500);

  l_unit varchar2(50) := '分角零元拾佰仟万拾佰仟亿拾佰千万拾佰仟';
  l_value_cn varchar2(50) := '负零壹贰叁肆伍陆柒捌玖整';

  i number(2);
  j number(1);
  k number(1);
  cj varchar2(1);
 
  type t_atomic is record (
    value_d varchar2(2),
    value_cn varchar2(20),
    unit varchar2(20));
  type t_yuan_varray is varray(20) of t_atomic;
 
  l_atomic t_atomic;
  l_yuan_varray t_yuan_varray := new t_yuan_varray();
 
  l_number varchar2(20);
  l_length number(2);

begin
  l_number := to_char(p_number,'fm9999999999999999.00');
  l_length := length(l_number);
  l_yuan_varray.extend(l_length);
 
  i := l_length;

  while i >= 1 loop
    cj := substr(l_number,i,1);
   
    if cj = '-' then
      l_atomic.value_d := cj;
      l_atomic.value_cn := substr(l_value_cn,1,1);
      l_atomic.unit := null;
      l_yuan_varray(l_length-i+1) := l_atomic;
    elsif cj = '0' then
      l_atomic.value_d := cj;
      l_atomic.value_cn := substr(l_value_cn,2,1);
      l_atomic.unit := substr(l_unit,l_length-i+1,1);
      l_yuan_varray(l_length-i+1) := l_atomic;
    elsif cj = '1' then
      l_atomic.value_d := cj;
      l_atomic.value_cn := substr(l_value_cn,3,1);
      l_atomic.unit := substr(l_unit,l_length-i+1,1);
      l_yuan_varray(l_length-i+1) := l_atomic;
    elsif cj = '2' then
      l_atomic.value_d := cj;
      l_atomic.value_cn := substr(l_value_cn,4,1);
      l_atomic.unit := substr(l_unit,l_length-i+1,1);
      l_yuan_varray(l_length-i+1) := l_atomic;
    elsif cj = '3' then
      l_atomic.value_d := cj;
      l_atomic.value_cn := substr(l_value_cn,5,1);
      l_atomic.unit := substr(l_unit,l_length-i+1,1);
      l_yuan_varray(l_length-i+1) := l_atomic;
    elsif cj = '4' then
      l_atomic.value_d := cj;
      l_atomic.value_cn := substr(l_value_cn,6,1);
      l_atomic.unit := substr(l_unit,l_length-i+1,1);
      l_yuan_varray(l_length-i+1) := l_atomic;   
    elsif cj = '5' then
      l_atomic.value_d := cj;
      l_atomic.value_cn := substr(l_value_cn,7,1);
      l_atomic.unit := substr(l_unit,l_length-i+1,1);
      l_yuan_varray(l_length-i+1) := l_atomic;
    elsif cj = '6' then
      l_atomic.value_d := cj;
      l_atomic.value_cn := substr(l_value_cn,8,1);
      l_atomic.unit := substr(l_unit,l_length-i+1,1);
      l_yuan_varray(l_length-i+1) := l_atomic;
    elsif cj = '7' then
      l_atomic.value_d := cj;
      l_atomic.value_cn := substr(l_value_cn,9,1);
      l_atomic.unit := substr(l_unit,l_length-i+1,1);
      l_yuan_varray(l_length-i+1) := l_atomic;
    elsif cj = '8' then
      l_atomic.value_d := cj;
      l_atomic.value_cn := substr(l_value_cn,10,1);
      l_atomic.unit := substr(l_unit,l_length-i+1,1);
      l_yuan_varray(l_length-i+1) := l_atomic;
    elsif cj = '9' then
      l_atomic.value_d := cj;
      l_atomic.value_cn := substr(l_value_cn,11,1);
      l_atomic.unit := substr(l_unit,l_length-i+1,1);
      l_yuan_varray(l_length-i+1) := l_atomic;
    elsif cj = '.' then
      l_atomic.value_d := cj;
      l_atomic.value_cn := substr(l_value_cn,12,1);
      l_atomic.unit := substr(l_unit,l_length-i+1,1);
      l_yuan_varray(l_length-i+1) := l_atomic;
    end if;
    i := i - 1;
  end loop;
 
/*
  i :=1;
  while i <= l_length loop
    dbms_output.put_line('>> ' || l_yuan_varray(i).value_d
      || l_yuan_varray(i).value_cn || l_yuan_varray(i).unit);
     
    i := i + 1;
  end loop;*/
 
  i := 1;
  j := -1;
  k := 0;
 
  while i <= l_length loop
    if l_yuan_varray(i).value_d = '0' then
     
      if j = 0 then
        result := l_yuan_varray(i).value_cn || result;
        j := 1;
      end if;
       
      if l_yuan_varray(i).unit = substr(l_unit,12,1) then
        result := l_yuan_varray(i).unit || result;
      elsif l_yuan_varray(i).unit = substr(l_unit,8,1) then
        result := l_yuan_varray(i).unit || result;
      elsif l_yuan_varray(i).unit = substr(l_unit,4,1) then
        result := l_yuan_varray(i).unit || result;
      end if;   
   
    elsif l_yuan_varray(i).value_d = '.' then
     
      if k = 1 then
        result := l_yuan_varray(i).unit || result;
      elsif k = 0 then
        result := l_yuan_varray(i).value_cn || result;
      end if;
     
      j := 1;
   
    else
   
      result := l_yuan_varray(i).value_cn || l_yuan_varray(i).unit || result ;
      if j <> -1 then
        j := 0;
      elsif j = -1 then
        k := 1;
      end if;
    end if;
   
  i := i + 1;
  end loop;

  result := '人民币' || result;
 
  return(result);
end f_to_yuan;

加密存储过程时遇到一些问题的解决方法

在加密存储过程时发现如下问题:

 

1,在BETWEEN语句后面的AND必须和BETWEEN处在同一行中,并且AND前后只能有一个空格。

 

 

 

2,在如下代码中:

 

不支持将子查询放SELECT字句后,应该用连接查询来替代。

另外不支持INNER JOIN, LEFT OUTER JOIN等写法,应写成oracle特有的带(+)号的连接查询。

 

错误代码示例:

 

INSERT INTO PUB_DIM_ITEM
  (ITEM_ID,
   ITEM_SOURCE,
   ITEM_CK,
   ITEM_NAME,
   PARENT_ITEM_ID,
   ITEM_LEVEL_ID,
   EFF_DATE,
   EXP_DATE,
   EXTR1,
   SOURCE_COD)
  SELECT DISTINCT M.MU_ID,
         M.MU_ID,
         M.MU_ID,
         (SELECT T1.ITEM_NAME||M.MU_ID
            FROM PUB_DIM_ITEM T1
           WHERE T1.ITEM_ID IN SUBSTR(M.MU_ID, 1, 7)),

         SUBSTR(M.MU_ID, 1, 7),
         '4',
         SYSDATE,
         TO_DATE('2099-12-31', 'YYYY-MM-DD'),
         'MU_ID_ADD',
         M.MU_ID
    FROM MDT_FCT_RVN_003 M
   WHERE M.MU_ID IN (SELECT DISTINCT TO_CHAR(T.MU_ID)
                       FROM MDT_FCT_RVN_003 T
                     MINUS
                     SELECT TO_CHAR(V.MU_ID) FROM V_DIM_I4_MU V);

 

 

 修改后的代码:

 

INSERT INTO PUB_DIM_ITEM
    (ITEM_ID
    ,ITEM_SOURCE
    ,ITEM_CK
    ,ITEM_NAME
    ,PARENT_ITEM_ID
    ,ITEM_LEVEL_ID
    ,EFF_DATE
    ,EXP_DATE
    ,EXTR1
    ,SOURCE_COD)
    SELECT DISTINCT M.MU_ID
                   ,M.MU_ID
                   ,M.MU_ID
                   ,T1.ITEM_NAME || M.MU_ID
                   ,SUBSTR(M.MU_ID, 1, 7)
                   ,'4'
                   ,SYSDATE
                   ,TO_DATE('2099-12-31', 'YYYY-MM-DD')
                   ,'MU_ID_ADD'
                   ,M.MU_ID
      FROM MDT_FCT_RVN_003 M, PUB_DIM_ITEM T1
     WHERE T1.ITEM_ID IN (SUBSTR(M.MU_ID, 1, 7))
       AND M.MU_ID IN
           (SELECT DISTINCT TO_CHAR(T.MU_ID)
              FROM MDT_FCT_RVN_003 T
            MINUS
            SELECT TO_CHAR(V.MU_ID) FROM V_DIM_I4_MU V);    

 

 

3IN 子句后面要有()    

 

这样的写法是错误的:

 WHERE T1.ITEM_ID IN SUBSTR(M.MU_ID, 1, 7)

 

 

应写成这样的形式:

WHERE T1.ITEM_ID IN (SUBSTR(M.MU_ID, 1, 7))

Official Video for Terra Naomi's "Say It's Possible"

  

折叠的菜单

首先需要将菜单内容写在一个xml文件上,我将其命名为menu.xml;

代码清单menu.xml

<?xml version="1.0" encoding="UTF-8"?>

<menu-definition>

<menu name="hkVmi" label="HK VMI" href="hkVmiMenu.do">
  <sub-menu name="hkVmiInbound" label="HK VMI Inbound" href="sss"></sub-menu>
  <sub-menu name="hkVmiOutbound" label="HK VMI Outbound" href="sss"></sub-menu>
  <sub-menu name="hkVmiInboundQuery" label="HK VMI Inbound Query" href="sss"></sub-menu>
  <sub-menu name="hkVmiOutboundQuery" label="HK VMI Outbound Query" href="sss"></sub-menu>
  <sub-menu name="hkVmiStockQuery" label="HK VMI Stock Query" href="sss"></sub-menu>
  <sub-menu name="hkVmiParnoQuery" label="HK VMI Partno Query" href="sss"></sub-menu>
  <sub-menu name="hkVmiSkuTransfer" label="HK VMI Sku transfer" href="sss"></sub-menu>
</menu>

<menu name="hkWmsi" label="HK WMSI" href="hkWmsiMenu.do">
  <sub-menu name="inbound" label="Inbound" href="sss"></sub-menu>
  <sub-menu name="outbound" label="Outbound" href="sss"></sub-menu>
  <sub-menu name="stock" label="Stock" href="sss"></sub-menu>
</menu>
<menu name="baoBiao" label="报表" href="baoBiaoMenu.do">
  <sub-menu name="keHuDuiZhangDan" label="客户队帐单" href="homeBaobiaoKehuduizhangdanPage.do"></sub-menu>
</menu>
<menu name="dingDan" label="订单" href="dingDanMenu.do">
  <sub-menu name="dingDanGuanLi" label="订单管理" href="homeDingdanDingdanguanliPage.do"></sub-menu>
</menu>
</menu-definition>
 

然后创建一个继承自TagSupport的类,我将其命名为ParseMenuTag,并为这个类创建相应的tld文件:

代码清单zibet-zibet.tld

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<taglib>
    <tlibversion>1.2</tlibversion>
    <jspversion>1.1</jspversion>
    <shortname>zibet</shortname>
    <uri>http://jakarta.apache.org/struts/tags-bpgdc</uri>
    <tag>
        <name>menu</name>
        <tagclass>com.zibet.taglib.menu.ParseMenuTag</tagclass>
        <attribute>
            <name>url</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
</taglib>

在ParseMenuTag类中,首先使用Dom4j读取XML文件,然后应用Taglib将其打印在网页上,需要注意的是需要将当前菜单的label存储在session中。

代码清单ParseMenuTag.java:

package com.zibet.taglib.menu;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

import org.apache.struts.taglib.TagUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import com.zibet.util.Dom4jHelper;

public class ParseMenuTag extends TagSupport
{
private String url;
public String getUrl()
{
  return url;
}
public void setUrl(String url)
{
  this.url = url;
}
private boolean flag = true;
public int doStartTag() throws JspException
{
  HttpServletRequest req =
   (HttpServletRequest)pageContext.getRequest();
  String label;
  try
  {
   label = pageContext.getSession()
        .getAttribute("label").toString();
  }
  catch(RuntimeException e1)
  {
   label = "null";
  }

  try
  {
   URL httpurl = Dom4jHelper.instance.wrapperUrl(url,req);
   Document document = Dom4jHelper.instance.parse(httpurl);
   //document.setXMLEncoding("ISO-8859-1");
   List nodes;
   if(label == "null")
   {
    nodes = document.selectNodes("menu-definition/menu");
   }
   else
   {
    nodes = document.selectNodes(
       "menu-definition/menu[@label='"+ label +"']/preceding-sibling::* |" +
       "menu-definition/menu[@label='"+ label +"']/descendant-or-self::* |" +
       "menu-definition/menu[@label='"+ label +"']/following-sibling::*");
   }
   StringBuffer sb = new StringBuffer();
   sb.append("<ul>");
   for(int i=0; i<nodes.size(); i++)
   {
    Node node = (Node)nodes.get(i);
    if(node.getName().equals("menu"))
    {
     sb.append("<li><a class=\"main-menu\" href=\""
       + node.valueOf("@href").toString().trim()
       + "\">"
       + node.valueOf("@label").toString().trim()
       + "</a></li>");
    }
    else
    {
     sb.append("<li><a class=\"sub-menu\"href=\""
       + node.valueOf("@href").toString().trim()
       + "\">"
       + node.valueOf("@label").toString().trim()
       + "</a></li>");
    }
   }
   sb.append("</ul>");
   TagUtils.getInstance().write(pageContext,sb.toString());
  }
  catch(MalformedURLException e)
  {
   e.printStackTrace();
  }
  catch(DocumentException e)
  {
   e.printStackTrace();
  }
  return SKIP_BODY;
}

}

类ParseMenuTag用到了一个补助类:Dom4jHelper

代码清单Dom4jHelper.java

package com.zibet.util;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.PageContext;

import org.apache.struts.taglib.TagUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

public class Dom4jHelper
{
    public static Dom4jHelper instance = new Dom4jHelper();
    public Document parse(URL url)throws DocumentException
    {
        SAXReader reader = new SAXReader();
        Document document = reader.read(url);
        return document;
    }
    public Document parse(File file)throws DocumentException
    {
        SAXReader reader = new SAXReader();
        Document document = reader.read(file);
        return document;
    }
    public URL wrapperUrl(String url,HttpServletRequest req)
    throws MalformedURLException
    {
        return new URL(req.getScheme() + "://" + req.getServerName() + ":"
                + req.getServerPort() + "/" + req.getContextPath() + url);
    }
}

在jsp页面中可以这样调用菜单:

代码清单menu.jsp

<%@ page contentType="text/html; charset=UTF-8" language="java"%>

<%@ taglib uri="/tags/struts-htmlx" prefix="htmlx"%>

<htmlx:menu url="/xml/menu.xml"/>

程序运行效果如下:

menu

最后奉上css代码:

代码清单style.css

/* body start */
body {
    margin: 5px 5px 5px 5px;
    padding: 0;
    font-size: 12px;
    font-family: arial, "宋体";
    line-height: 1.6em;
    color: #000;
}
/* body end */

/* input start */
input[type="button"] {
    color: #000000;
    background-color: #fed;
    border: 1px solid;
    border-top-color: #69b;
    border-left-color: #696;
    border-right-color: #363;
    border-bottom-color: #363;
}

input[type="button"]:hover {
    border-top-color: #c63;
    border-left-color: #c63;
    border-right-color: #930;
    border-bottom-color: #930;
}

input[type="submit"] {
    color: #000000;
    background-color: #fed;
    border: 1px solid;
    border-top-color: #69b;
    border-left-color: #696;
    border-right-color: #363;
    border-bottom-color: #363;
}

input[type="submit"]:hover {
    border-top-color: #c63;
    border-left-color: #c63;
    border-right-color: #930;
    border-bottom-color: #930;
}
input[type="reset"] {
    color: #000000;
    background-color: #fed;
    border: 1px solid;
    border-top-color: #69b;
    border-left-color: #696;
    border-right-color: #363;
    border-bottom-color: #363;
}

input[type="reset"]:hover {
    border-top-color: #c63;
    border-left-color: #c63;
    border-right-color: #930;
    border-bottom-color: #930;
}

input[type="text"] {
    border-width: 1px;
    background-color: #FFFFFF;
}
input[type="password"] {
    border-width: 1px;
    background-color: #FFFFFF;
}
/* input end  */

/* layout start */
#container {
    width: 100%;
    margin: 0;
    padding: 0;
}

#header {
    margin: 0;
    padding: 0;
    clear: right;
}

#footer {
    margin: 0;
    padding: 0;
    clear: right;
}
#content {
    margin: 5px 0px;
    padding: 0;
    width: 100%;
}
#left {
    float: left;
    width: 13%;
    margin: 0px 1px 0px 0px;
    padding: 0;
}

#right {
    float: right;
    width: 86%;
    margin: 0px 0px 0px 1px;
    padding: 0;
}
/* layout end */

/* heaeder_nav start */
#header_nav {
    margin: 0;
    padding: 0;
    list-style-type: none;
    text-align: right
}

#header_nav li {
    border-color: #666;
    border-style: solid;
    border-width: 0 1px 0 0;
    padding: 0 2px 0 1px;
    margin: 0 3px 0 3px;
    list-style-type: none;
    display: inline;
}

#header_nav li a {
    margin: 0;
}

#header_nav li.last {
    border-width: 0;
    margin: 0;
}
/* header_nav end */

/* dabable start */
#datable table {
    table-layout: automatic;
    empty-cells: show;
    padding: 0;
    margin: 0;
    border-spacing: 1px;
    border-collapse: collapse;
    border-width: 1px 1px 1px 1px;
    border-color: #bbbbbb;
    border-style: solid solid solid solid;
    width: 100%;
}
#datable table caption {
    padding: 0 0 5px 0;
    font-style: italic;
    text-align: right;
}

#datable table th {
    padding: 1px 1px 1px 1px;
    -moz-border-radius: 0px 0px 0px 0px;
    padding: 1px 1px 1px 1px;
    letter-spacing: -0px;   
    border-width: 1px 1px 1px 1px;
    font-weight: normal;
    border-color: #bbbbbb;
    border-style: solid solid solid solid;
    background-color: #eeeeee;
    color: #000;
    text-align: left;
}
#datable table td {
    -moz-border-radius: 0px 0px 0px 0px;
    padding: 1px 1px 1px 1px;
    letter-spacing: 0px;
    border-width: 1px 1px 1px 1px;
    border-color: #bbbbbb;
    border-style: solid solid solid solid;
}
/* datable end */

/* contable start */
#contable table {
    table-layout: automatic;
    empty-cells: show;
    padding: 0;
    margin: 0;
    border-spacing: 1px;
    border-collapse: separate;
    border-width: 1px 1px 1px 1px;
    width: 100%;
    border-color: #dddddd;
    border-style: none;
}

#contable table td {
    -moz-border-radius: 0px 0px 0px 0px;
    padding: 1px 1px 1px 1px;
    letter-spacing: 0px;
    border-width: 1px 1px 1px 1px;
    border-color: #dddddd;
    border-style: none;
    background-color: #ffffff;
    padding-left: 5px;
}
#contable table th {
    text-align: right;
    padding: 1px 1px 1px 1px;
    -moz-border-radius: 0px 0px 0px 0px;
    padding: 1px 1px 1px 1px;
    letter-spacing: -0px;
    border-width: 1px 1px 1px 1px;
    background-color: #eeeeee;
    font-weight: normal;
    border-style: none;
    padding-left: 4px;
    border-color: #dddddd;
}
#contable table td input[type="text"] {
    border-width: 0px 0px 1px 0px;
    background-color: #ffffff;
    border-color: #000;
}

/* contable end*/

/* report_nav start */
#report_nav {
      position: relative;
     z-index: 1;
     margin: 0;
    padding: 0;
    list-style: none;
}
#report_nav ul {
    width: 100%;
    padding: 0;
    margin: 0;
    list-style-type: none;
}

#report_nav ul li {
    margin: 0 0 3px 0;
    padding: 1px 0 0 0;
}

#report_nav ul li a {
      display: block;
    text-decoration: none;
    outline: none;
    color: #000;
}

#report_nav ul li a.main-menu{
    display: block;
      position: relative;
    border-style: solid;
    border-color: #d7d7d7;
      border-width: 1px 1px 1px 1px;
    padding: 1px 1px 1px 6px;
    background-color: #e4e4e4;
}

#report_nav ul li a.sub-menu{
    display: block;
      position: relative;
    border-style: dotted;
    border-color: #d7d7d7;
      border-width: 0 0 1px 0;
    padding: 1px 1px 1px 12px;
    margin: 0 3px 0 6px;
}

#report_nav ul li a:hover {
      text-decoration: underline;
}
#report_nav ul li a:link {
      color: #000000;
}
#report_nav ul li a:visited {
      color: #000000;
}
/* report_nav end */