当前位置:Linux教程 - RedHat - RedHat Linux 网络服务器构架实务(三)

RedHat Linux 网络服务器构架实务(三)



         几点说明:
    1、应大家的要求,现在使用简体中文发布,并添加了几个非常有用的例子,也增加了许多注释,具体修改内容详见附录中的Revision Log。
    2、同时,我声明上次发布的《最新RedHat 7.2 WEB开发服务器配置文档》一文用现在的三篇代替。
    3、本版本也已经做成PDF文档,较WEB页面可读性很强,如果你需要,请Email到yesgo.gledecity.com告知。
    4、本文档较长,分为三篇,不便之处,敬请谅解。
    5、最后,感谢您阅读本文档,谢谢!


    这是第三篇,接第二篇,正文如下:




    Step 17 Server Test
    ## 为什么不使用 1+1=<%=1+1%>或者<%out.print(“Hello World!”);%>这样的例子呢? 因为这样的例子只能测试Apache和Resin是否能够协同工作,而不能测试数据库连接、JDBC2.0是否支持,中文问题是否存在等等。下面给出四个例子,第一个例子可以测试上述的所有问题;第二个例子告诉你如何使用Resin的连接池;第三个例子告诉你如何调用组件,如何实现数据层和处理层的分离;第四个例子用来测试PHP。

    例一:使用连接串连接数据库

    1 创建数据库
    ## 数据库脚本如下,可存储为.sql文件,然后利用phpMyAdmin生成数据库
    ## 注意,后面的例子也将沿用该数据库。
    create database yesgo
    use yesgo;

    create table prov
    (
    prov_id tinyint(2) not null primary key,
    prov_name char(6) not null
    );

    insert into prov values (,安徽);
    insert into prov values (,北京);
    insert into prov values (,重庆);
    insert into prov values (,福建);
    insert into prov values (,甘肃);
    insert into prov values (,广东);
    insert into prov values (,广西);
    insert into prov values (8,贵州);
    insert into prov values (9,海南);
    insert into prov values (10,河北);
    insert into prov values (11,黑龙江);
    insert into prov values (12,河南);
    insert into prov values (13,湖北);
    insert into prov values (14,湖南);
    insert into prov values (15,内蒙古);
    insert into prov values (16,江苏);
    insert into prov values (17,江西);
    insert into prov values (18,吉林);
    insert into prov values (19,辽宁);
    insert into prov values (20,宁夏);
    insert into prov values (21,青海);
    insert into prov values (22,山西);
    insert into prov values (23,陕西);
    insert into prov values (24,山东);
    insert into prov values (25,上海);
    insert into prov values (26,四川);
    insert into prov values (27,天津);
    insert into prov values (28,西藏);
    insert into prov values (29,新疆);
    insert into prov values (30,云南);
    insert into prov values (31,浙江);
    insert into prov values (32,香港);
    insert into prov values (33,澳门);
    insert into prov values (34,台湾);

    2 为数据库添加帐号
    ##按如下方式添加的帐户只对yesgo数据库具有权限,而且对它拥有全部权限,为什么要添加四次呢?主要是host的不同,需要注意的是,MySQL验证是一个连接是否正确,不仅取决于帐号和密码,还要看主机名和数据库名。
    mysql –p
    mysql> grant all privileges on yesgo.* to your_user_name@localhost identified by ‘your_password’ with grant option;
    mysql> grant all privileges on yesgo.* to your_user_name@’ns.yesgo.loc’ identified by ‘your_password’ with grant option;
    mysql> grant all privileges on yesgo.* to your_user_name@’192.168.1.2’ identified by ‘your_password’ with grant option;
    mysql> grant all privileges on yesgo.* to your_user_name@’%’ identified by ‘your_password’ with grant option;
    mysql>exit

    3 创建JSP源文件
    touch /home/www/cnmysql.jsp
    chown –R www /home/www/cnmysql.jsp
    chgrp –r root /home/www/cnmysql.jsp
    chmod 771 /home/www/cnmsql.jsp

    vi /home/www/cnmsql.jsp
    ## 源代码如下:

    <%@ page language="java" import="java.sql.*"%>
    <%
    Class.forName ("org.gjt.mm.mysql.Driver");
    Connection conn = DriverManager.getConnection("jdbc:mysql://host_name/db_name","user_name","password");
    Statement stmt = conn.createStatement();
    ResultSet rs=stmt.executeQuery("select * from prov");
    rs.next();
    out.print(rs.getString("prov_id")+" "+rs.getString("prov_name")+"<br>");
    rs.last();
    out.print(rs.getString("prov_id")+" "+rs.getString("prov_name")+"<br>");
    rs.close();
    stmt.close();
    conn.close();
    %>
    4 测试该程序
    lynx http://www.yesgo.loc/cnmysql
    ##正确的结果应该是:

    1 安徽
    34 台湾

    例二:用连接池连接数据库
    1 建立数据源
    vi /usr/local/resin/conf/resin.conf
    <java compiler="internal" compiler-args="" work-dir=work/>

    <dbpool.sql id="your_data_source_name">
    <driver>org.gjt.mm.mysql.Driver</driver>
    <url>jdbc:mysql://localhost/database_name</url>
    <!-- <url> jdbc:mysql://localhost/database_name </url> -->
    <user>user_name</user>
    <password>password</password>
    <max-connections>100</max-connections>
    </dbpool.sql>

    <!--
    - Sample database pool configuration
    - The JDBC name is java:comp/env/jdbc/test
    -->

    2 创建JSP源文件
    touch /home/www/testpool.jsp
    chown –R www /home/www/testpool.jsp
    chgrp –r root /home/www/testpool.jsp
    chmod 771 /home/www/testpool.jsp

    vi /home/www/testpool.jsp
    ## 源代码如下:

    <%@ page language="java" import="java.sql.*,com.caucho.sql.*;"%>
    <%
    DBPool pool=new DBPool();
    Connection conn = pool.getPool("data_source_name ").getConnection();
    Statement stmt = conn.createStatement();
    ResultSet rs=stmt.executeQuery("select * from prov");
    rs.next();
    out.print(rs.getString("prov_id")+rs.getString("prov_name")+"<br>");
    rs.last();
    out.print(rs.getString("prov_id")+" "+rs.getString("prov_name")+"<br>");
    rs.close();
    stmt.close();
    conn.close();
    %>

    3 调试该程序
    lynx http://www.yesgo.loc/testpool.jsp
    ##处理的结果跟例一是一样的:

    1 安徽
    34 台湾

    例三:用处理层连接数据库
    ##本例告诉你如何使用组件
    ##其实你完全可以写一个bean来处理数据库,而不用象例二那么罗索。只用四条语句就可以取出数据库中的所有数据并显示出来,这样做实现了处理层和逻辑层的彻底分离,逻辑层发出指令处理层去响应相关处理,记录集也不会返回到逻辑层的jsp页面,而由处理层的bean处理,使得代码非常精简,效率也更高。至于如何书写组件不是本文档的重点,下面仅给出一个组件的例子并说明逻辑层的调用方法,你会发现逻辑层其实是个官僚,二处理层是下属,呵呵。

    1 创建处理层组件
    下面的组件是我为公司写的数据库处理组件的简化版本,考虑到篇幅的问题和可读性,这里我简化了它的功能(象分页、批量更新、获取字段数和字段名称,用set和get提高其扩展性、对其他连库方法的支持等都没有出现在下面的代码中),使之包含所有常用的功能并使之更加清晰和易于理解;其二,我将连库动作加到了构造函数中,这是个优点也是个缺点,优点是简化了连库动作,缺点是降低了通用性,我没有添加设置数据源等方法,从而每当变换一次数据库就需要改写组件中的连接池名称,这在做一个固定项目的时候是可以的,如果你需要set数据源,可以自行添加;
    ##使用组件的方法:
    我这里说的是使用bean的通用方法,你建立自己的bean目录可以仿照该例子。在你的站点根目录下建立resin.conf中指定的存放bean的目录,我上面的举例是classes,那你就建立classes目录,那么classes就是你站点的class根目录。然后在下面依次建立com\gledecity\yesgo\sql,注意它们之间是父子关系,不是同级文件夹,然后将下面即将建立的DBBridge.java放到”站点根目录\classes\com\gledecity\yesgo\sql”目录下,然后将该文件上传到服务器端即可。上面的步骤在微软平台上使用UltraDev之类的开发工具即可完成,当然手工也可以。

    源文件如下:

    //------------------------------------------------------------------------------
    // File: DBBridge.java
    // Copyright (c) 2000-2001 Mr.Fengjun Zhao. All Rights Reserved.
    // Author: 赵凤君@06/18/01
    // Last Revision: 赵凤君@12/22/01
    // Description: 数据库接口类。一个统一的数据库接口,实现了逻辑层和数据层的彻底分离,封装了常用的数据库操作。主要功能是:连接数据库、执行SQL语句、数据库取值操作、数据分页、清除数据、关闭数据库等。
    // Version:简化版1.0
    //------------------------------------------------------------------------------

    //指定包目录
    package com.gledecity.yesgo.sql;

    //导入包
    import java.sql.* ;
    import com.caucho.sql.*;

    public class DBBridge {
    //声明属性
    private DBPool connPool ;
    private Connection conn ;
    private ResultSet rs ;
    private Statement stmt ;


    // -------------------------------------- 构造函数---------------------------------
    public DBBridge() {
    connPool=null ;
    conn=null ;
    rs=null ;
    stmt=null ;
    try{open();}
    catch(java.sql.SQLException ex){ex.toString();}
    }
    // ------------------------------------------------------------------------------------

    //连接数据库的方法
    public void open()
    throws SQLException {
    if( conn!=null && !conn.isClosed() )
    throw new SQLException( "The connection has been established already." ) ;
    clear () ;
    DBPool pool=new DBPool();
    conn = pool.getPool("your_data_source_name").getConnection();
    }

    //执行SQL语句的方法,将JDBC中的executeQuary()和executeUpdate()两个方法//合而为一,注意返回值为整形,
    public int execSQL( String sqlStmt )
    throws SQLException {
    if( conn==null || conn.isClosed() )
    throw new SQLException( "This connection has not been established yet." ) ;
    if( sqlStmt==null )
    throw new SQLException( "SQL-statement is null." ) ;
    clear () ;
    conn.setAutoCommit( true ) ;
    stmt=conn.createStatement() ;
    if( sqlStmt.toUpperCase().startsWith( "SELECT" ) ) {
    rs=stmt.executeQuery( sqlStmt ) ;
    return -1 ;
    }
    else {
    int numRow=stmt.executeUpdate( sqlStmt ) ;
    clear() ;
    return numRow ;
    }
    }

    //获取字段值,参数为整形——字段次序
    public String getString( int fieldNo )
    throws SQLException {
    return rs.getString(fieldNo) ;
    }

    //获取字段值,参数为字符串——字段名
    public String getString( String fieldName )
    throws SQLException {
    return rs.getString(fieldName) ;
    }

    //上移指针
    public boolean previous()
    throws SQLException {
    if( rs==null )
    throw new SQLException( "ResultSet is null." ) ;
    return rs.previous() ;
    }

    //下移指针
    public boolean next()
    throws SQLException {
    if( rs==null )
    throw new SQLException( "ResultSet is null." ) ;
    return rs.next() ;
    }

    //指针最上
    public boolean first()
    throws SQLException {
    if( rs==null )
    throw new SQLException( "ResultSet is null." ) ;
    return rs.first() ;
    }

    //指针最下
    public boolean last()
    throws SQLException {
    if( rs==null )
    throw new SQLException( "ResultSet is null." ) ;
    return rs.last() ;
    }

    //清除变量,当你仅需要清除变量而不关库时可调用此方法
    private void clear () throws SQLException {
    if( rs!=null ) rs.close() ;
    rs=null ;
    if( stmt!=null ) stmt.close() ;
    stmt=null ;
    }

    //清除变量并关库
    public void close() throws SQLException {
    clear () ;
    if( connPool!=null ) {
    connPool=null ;
    }
    else {
    if( conn==null )
    throw new SQLException( "This connection has been closed already." ) ;
    if( conn.isClosed() )
    throw new SQLException( "This connection has been closed." ) ;
    conn.close() ;
    }
    conn=null ;
    }

    }

    2 编写逻辑层代码
    ##在客户端创建dbbridge.jsp,然后上传到服务器端即可:

    ##上级要来视察某官僚的工作,只见该官僚指挥若定:
    ##逻辑层对处理层说:小子,去跟我的后台联络一下。 //连库并初始化
    <jsp:useBean id=”bridge” class=”com.gledecity.yesgo.sql.DBBridge” />
    ##逻辑层对处理层说:去帮我准备点书面材料,我只要结果。 //执行SQL语句
    <%bridge.execSQL(“select * from prov”);
    ##逻辑层对处理层说:材料准备好了?干得好!上级一来看到一片数据。//循环显示
    while(bridge.next())
    { out.print(bridge.getString("prov_id")+bridge.getString("prov_name")+"<br>");}
    ##逻辑层对处理层说:好了好了,政绩显示完毕,你们通通滚蛋吧。 //关闭所有变量
    bridge.close();
    %>
    ##上级看后非常满意,拍拍官僚的肩膀:“干得不错!”官僚一高兴,说:“哪里哪里,都是下属办事得力!”

    3 测试该程序
    lynx http://www.yesgo.loc/dbbridge.jsp
    ##当然你也可以在客户端浏览器测试,只是你需要将你服务器的IP添加到你网络设置中的DNS列表中。
    ##处理的结果是数据库中所有的数据:

    1安徽
    2北京
    3重庆
    4福建
    5甘肃
    6广东
    7广西
    8贵州
    9海南
    10河北
    11黑龙江
    12河南
    13湖北
    14湖南
    15内蒙古
    16江苏
    17江西
    18吉林
    19辽宁
    20宁夏
    21青海
    22山西
    23陕西
    24山东
    25上海
    26四川
    27天津
    28西藏
    29新疆
    30云南
    31浙江
    32香港
    33澳门
    34台湾

    例四:测试PHP
    1 创建源文件
    touch /home/www/test.php
    chmod 701 /home/www/test.php

    2 编辑源文件
    vi test.php
    ## 源代码如下:
    <?
    phpinfo();
    ?>

    3 测试该程序
    lynx http://www.yesgo.loc/test.php
    //结果是大家熟知的服务器端变量列表。
    --------------------------------------------------------------------------------------------
    Step 18 Configuration debug

    ##调试过程可能的错误如下:

    常见错误一:You don have permission
    Forbidden
    You don have permission to access / on this server.

    Apache/1.3.22 Server at www.yesgo.loc Port 80

    原因可能是:
    1、 你没有为该目录或者该文件设置guest组权限;
    2、 你没有将该文件名设置为默认页面,尤其是在仅用域名访问的情况下。
    解决办法:
    chmod 701 /home/www
    chmod 701 /home/www/*

    vi /usr/local/apache/conf/httpd.conf
    DirectoryIndex index.html index.jsp index.xtp index.php index.php3

    常见错误二:404 Not Found
    404 Not Found
    /index.jsp was not found on this server.

    Resin 2.0.4 (built Thu Nov 15 17:56:24 PST 2001)

    原因可能是:
    1、 你请求的文件名输入错误;
    2、 你没有在resin.conf和httpd.conf中都建立相应的主机。
    解决办法:
    1、 检查文件名,尤其注意大小写问题;
    2、 参照Resin install步骤中的配置支持JSP的虚拟主机部分。

    常见错误三:java.lang.ClassNotFoundException
    500 Servlet Exception
    java.lang.ClassNotFoundException: org.gjt.mm.mysql.Driver
    at com.caucho.util.DynamicClassLoader.loadClass(DynamicClassLoader.java:479)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:253)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:313)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:120)
    at _cnmysql__jsp._jspService(/cnmysql.jsp:4)
    at com.caucho.jsp.JavaPage.service(JavaPage.java:74)
    at com.caucho.jsp.Page.subservice(Page.java:485)
    at com.caucho.server.http.FilterChainPage.doFilter(FilterChainPage.java:176)
    at com.caucho.server.http.Invocation.service(Invocation.java:278)
    at com.caucho.server.http.CacheInvocation.service(CacheInvocation.java:129)
    at com.caucho.server.http.RunnerRequest.handleRequest(RunnerRequest.java:338)
    at com.caucho.server.http.RunnerRequest.handleConnection(RunnerRequest.java:270)
    at com.caucho.server.TcpConnection.run(TcpConnection.java:140)
    at java.lang.Thread.run(Thread.java:484)

    Resin 2.0.4 (built Thu Nov 15 17:56:24 PST 2001)

    原因可能是:
    1、你没有安装驱动程序;
    2、驱动程序没有设置到系统CLASSPATH中。
    解决办法:
    参见 Classes Install and edit /etc/profile两部分

    常见错误四:Invalid authorization specification
    500 Servlet Exception
    java.sql.SQLException: Invalid authorization specification: Access denied
    for user: [email protected] (Using password: YES)
    at org.gjt.mm.mysql.MysqlIO.init(MysqlIO.java:330)
    at org.gjt.mm.mysql.Connection.connectionInit(Connection.java:261)
    at org.gjt.mm.mysql.jdbc2.Connection.connectionInit(Connection.java:89)
    at org.gjt.mm.mysql.Driver.connect(Driver.java:167)
    at java.sql.DriverManager.getConnection(DriverManager.java:517)
    at java.sql.DriverManager.getConnection(DriverManager.java:177)
    at _cnmysql__jsp._jspService(/cnmysql.jsp:5)
    at com.caucho.jsp.JavaPage.service(JavaPage.java:74)
    at com.caucho.jsp.Page.subservice(Page.java:485)
    at com.caucho.server.http.FilterChainPage.doFilter(FilterChainPage.java:176)
    at com.caucho.server.http.Invocation.service(Invocation.java:278)
    at com.caucho.server.http.CacheInvocation.service(CacheInvocation.java:129)
    at com.caucho.server.http.RunnerRequest.handleRequest(RunnerRequest.java:338)
    at com.caucho.server.http.RunnerRequest.handleConnection(RunnerRequest.java:270)
    at com.caucho.server.TcpConnection.run(TcpConnection.java:140)
    at java.lang.Thread.run(Thread.java:484)

    Resin 2.0.4 (built Thu Nov 15 17:56:24 PST 2001)
    原因可能是:
    1、 源代码中的主机名、数据库名、帐号或者密码输入错误;
    2、 如果数据库名、帐号、密码均正确,那说明是主机名不匹配;
    3、 如果使用数据源连库,检查数据源的设置和源代码中名称是否输入正确。
    Solution:
    1、 参见Resin install和Server test两部分;
    2、 注意:数据库的连接不仅仅是帐号和密码决定的,而是由主机名、数据库名、用户名和密码四个参数决定的。

    常见错误五:Invalid authorization specification
    500 Servlet Exception
    java.lang.AbstractMethodError
    at _cnmysql__jsp._jspService(/cnmysql.jsp:11)
    at com.caucho.jsp.JavaPage.service(JavaPage.java:74)
    at com.caucho.jsp.Page.subservice(Page.java:485)
    at com.caucho.server.http.FilterChainPage.doFilter(FilterChainPage.java:176)
    at com.caucho.server.http.Invocation.service(Invocation.java:278)
    at com.caucho.server.http.CacheInvocation.service(CacheInvocation.java:129)
    at com.caucho.server.http.RunnerRequest.handleRequest(RunnerRequest.java:338)
    at com.caucho.server.http.RunnerRequest.handleConnection(RunnerRequest.java:270)
    at com.caucho.server.TcpConnection.run(TcpConnection.java:140)
    at java.lang.Thread.run(Thread.java:484)

    Resin 2.0.4 (built Thu Nov 15 17:56:24 PST 2001)

    原因可能是:
    1、你安装的JDK版本太低以至于JDBC版本并不是2.0的;
    3、 更大的可能性是你的驱动程序不支持JDBC2.0,JDBC只是提供了抽象类接口,它需要驱动程序作为其实体类来具体实现。
    解决办法:
    1、 升级JDK,我的建议是 is j2sdk-1_3_1_01-linux-i386.bin,参见Jvm install部分;
    2、 替换数据库驱动,你很有可能使用的是mysql_comp.jar ,使用 mm.mysql-2.0.4-bin.jar.zip替代它。

    常见错误六:中文乱码
    可能的原因:
    安装操作系统时候,你没有选择i18n的简体包也没有在源文件中加以处理
    解决办法:
    1、Html方式,添加如下一行到你的JSP源代码:
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    2、JSP方式一:
    <%@ page contentType = "text/html; charSet=gb2312" %>
    3、JSP方式二:
    一般说来使用Resin作为JSP引擎是不需要本方法的,我就从来都没用到,只有使用象Tomcat之类的东东才可能用到这个繁琐的方法,不过这个方法也有它的好处,就是提高了程序的可移植性,不至于换了系统或者引擎就乱码了。
    <%
    String chs=”这个方法肯定可以!”;
    byte[] bchs=chs.getBytes();
    out.print(new String(bchs,”8859_1”));
    %>




























    Appendix
    Appendix I : Thanks

    人物:
    我的很多知识来源于同事和朋友的指教,请允许我在这里占用一点篇幅向我的朋友表达我最真诚的感谢。
    Mr. Jim Zhao 是我原先的一位同事,一个富有突破性的人才,狂热的Linux爱好者,他是我在UNIX和Linux方面的启蒙者,是他引导我进入这块美妙的天地并在我初学的路上给予诸多帮助,谢谢你,Jim。
    很多未曾谋面的网友也对我教益量多,象Mr. Axman和Mr. popeye。Mr. Axman 是Linux和JAVA方面的高手,他出类拔萃的才能和侠肝义胆的古道热肠令我为之钦佩;Mr.popeye年龄很小却有优秀的技能,也曾指教我很多问题。像这样的朋友还有很多,恕不一一列出。

    站点:
    我也从很多站点和论坛上得到很多的知识和资源,向这些站点的所有者和参与者真诚感谢:
    中国JSP网络 http://www.cnjsp.net
    LinuxByte: http://www.linuxbyte.net
    LinuxAid: http://www.linuxaid.com.cn
    中国Linux论坛: http://www.linuxforum.net

    谢谢你们!
    Appendix II : Todo List
    计划添加的内容:
    1、 如何定制化安装操作系统;
    2、 添加Qmail的配置方法和webmail开发思路;
    3、 磁盘配额的实现;
    4、 增强系统安全性的方法;
    5、 负载均衡的实现办法;
    6、 添加FAQ列表;

    Appendix III: Revision log
    1、 12/20/2001 首次发布。
    语言:英文
    版本:0.0.1
    发布:
    http://www.linuxbyte.net
    标题:最新RedHat 7.2 WEB开发服务器配置文档
    http://www.iuirc.com/cnjspbbs/
    标题:最新的RedHat 7.2 WEB开发服务器配置文档(PDF格式)

    2、 12/22/2001 第二次发布。
    语言:简体中文;
    版本: 0.0.2
    发布:
    http://www.linuxbyte.net
    标题:RedHat Linux 网络服务器构架实务(chs_0.0.2_12-22-2001)
    http://www.iuirc.com/cnjspbbs/
    标题:RedHat Linux 网络服务器构架实务(chs_0.0.2_12-22-2001)
    修改:

    2 将语言换为简体中文;
    2 添加了许多注释;
    2 修改了几处文字错误;
    2 添加了连接池的使用方法;
    2 添加了组件的使用方法,并提供了一个数据库处理组件;
    2 更新了目录结构;
    2 修改了TODO列表;

    发布人:叶三耿 来自: