用JSP/Servlet开发简单的用户注册系统

  作者:板桥banq

上页

2.5.2  快速配置开发环境

JBuilder是一个很强大的Java开发工具。因为其包含内容太多,有时用来作为小型项目的JSP/Javabeas开发显得过于“笨重”,而且学习JBuilder配置使用还需要一定的时间和精力。下面介绍一套简单快速轻便的开发和调试环境。

·          Jcreatorhttp://www.jcreator.com/)用来编辑调试JavaBean

·          Dreamweaver (editplus)用来编辑JSPHTML文件。

·          Tomcat作为Serlvet/JSP容器服务器。

·          MySQL作为数据库服务器。

这套组合可以直接通过IE浏览器调试JSPJavaBean,与JBuilder这样庞大的IDE工具软件相比,最大优点是资源消耗少,可以发挥各自工具的特点。例如DreamWeaver强大的可视化图形开发界面非常方便HTML/JSP的开发。

开发环境配置:

1)在自己的PC Windows上安装JDK。目前最新版本是JDK 1.4,可以从http://java.sun.com下载安装。

2)建立自己项目的目录,如D:/javasource/SimpleRegister/放置的都是项目JSPJavaBean文件的目录,在myweb下可以建立4个目录:

·          defaultroot根目录:放置JSP源程序。

·          defaultroot/ WEB-INF/classes:编译后的javabean运行程序。

·          defaultroot/ WEB-INF/lib:驱动程序包。

·          src目录:JavaBeans的源程序。

3)下载3JDK中没有携带的驱动包:Servlet包(servlet.jar JavaMail包(mail.jar)和MySQL JDBC驱动程序包(mysql-connector-xxx.jar)。前两者可以从Sun网站下载。如果已经安装了Tomcat,可以使用Tomcat/common/lib目录下的servlet.jarmail.jar包,后者从MySQL网站下载。将这两个文件都复制到lib目录下。注意,lib下这几个支持包是本系统必备库文件,如果缺少,将可能无法编译或运行本系统。

4)安装Jcreator,让Jcreator安装时能自动搜索到JDK目录。配置jcreator Java环境时稍微有点麻烦。在Config菜单下选择Options,进入JDK profiles。如果Jcreator搜索到JDK目录,会看到一个item,选择“edit/add/add Jar”,将lib目录所有的Jar都逐个加入。

这样Jcreator编译Java相关技术时就不会出错。

5)安装MySQLMySQL可以从MySQL.com下载最新版本。从MySQL 4.0以后版本已经整合了原来MySQL 3 MAX版本的功能,变得非常强大而有效,下载后运行bin\winmysqladmin.exe就可以启动MySQL了。

MySQL的管理工具下载使用MySQL Control CenterPhpMyAdmin。前者可以从MySQL下载直接运行,在其中使用SQL脚本实现管理,基本是英文版本;而后者有中文版,提供了方便的数据库操作菜单,省去输入SQL脚本的麻烦,但是缺点是需要PHP。其实安装步骤也是很简单,首先下载Apache Windows版本,修改\Program Files\Apache Group\Apache\conf\http.conf:如下:

DocumentRoot "D:/javaserver/ApacheWebRoot"; 设置Apache文档根目录

下载PHP Windows版本,直接运行安装,例如安装到D:/javaserver/php-4.3.1-Win32/目录下。

再从sf.net上下载PhpMyAdmin,安装到上述指定Apache文档根目录下,例如D:\javaserver\ApacheWebRoot\phpMyAdmin-2.5.1,修改该目录下的config.inc.php文件如下:

$cfg['PmaAbsoluteUri'] = 'http://localhost/phpMyAdmin-2.5.1/'; //后者根据自己目录添加

$cfg['Servers'][$i]['controluser']   = 'Mysql访问用户名';

$cfg['Servers'][$i]['controlpass']   = 'Mysql访问密码';

修改Apachehttpd.conf,增加下列语句:

ScriptAlias /php/ "D:/javaserver/php-4.3.1-Win32/"  //PHP安装目录

AddType application/x-httpd-php .php

Action application/x-httpd-php "/php/php.exe"

重新启动Apache,在浏览器输入http://localhost/phpMyAdmin-2.5.1/就可以启用PhpMyAdmin访问管理MySQL数据库了。

2.5.3  Tomcat配置和调试

JSP/ServletJ2EE的一种技术规范,它的运行需要特定的支持容器。容器在运行时将JSP编译后作为Servlet运行,容器使用线程池来实现Servlet的运行。J2EE容器虽然确保使用者不用担心线程以及同步等问题,但是要真正用好Web系统,还需要掌握一定的Java线程基础知识,必须遵循一定的线程使用规则。如果超过规则使用JSP/Servlet,那么会给系统带来隐含的运行风险。

目前支持JSP/Servlet的应用服务器软件很多,如TomcatWeblogic等。Tomcathttp://jakarta.apache.org/tomcat/)是著名Apache雅加达组织推出的开放源代码软件。它们曾经推出著名HTTP服务器ApacheApache随着Linux的发展,已经占据整个互联网服务器软件大半壁江山,相信Tomcat也会像Apache那样有着广阔的发展前景。

Tomcat网站下载最新的Tomcat软件,Tomcat 4.0以后又取名为Catalina,整个架构设计和以前版本有很大不同。研究Tomcat源码会发现,其中也是主要基于TCP Socket连接上集合了线程池技术的一个Java应用系统。当然,在这里并不是研究如何开发Tomcat,而是讨论JSP/Servlet程序如何部署在Tomcat下运行。

将本项目部署到Tomcat下有两种方法:

1)将本项目根目录复制到Tomcatwebapps目录下,Tomcat在启动后就能使用根目录名访问本项目。例如项目的根目录名为SimpleRegister,那么这样部署后,通过浏览器http://localhost:8080/SimpleRegister就能访问到本项目。本方法需要复制目录,在反复调试时非常不方便,推荐使用第二种方法。

2)修改Tomcatconf目录下的server.xml配置文件,在下列代码处加入自己的项目的配置:

<!-- Tomcat Root Context -->

 <!--

    <Context path="" docBase="ROOT" debug="0"/>

  -->

 <!—本行是本项目的配置  -->

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

                 reloadable="true" crossContext="true" />

在配置中,指定了Context的路径path/register,那么就可以通过网址http://localhost:8080/register访问本项目;docbase是指本项目实际所在位置是根目录SimpleRegister下的defaultroot

启动Tomcat,如果发生一些错误,首先确认defaultroot目录下Web基本结构元素是否存在,如WEB-INF目录以及WEB-INF下的web.xml文件。因为本项目使用了数据库功能,那么在WEB-INFlib下就需要支持Java JDBC的库文件*.jarMySQL数据库的库文件是mysql-connector-java-XXX-stable-bin.jar

如果Tomcat正常启动,没有任何错误发生,表明本项目部署成功了,可以输入网址http://localhost:8080/register访问。

调试项目的复杂程度取决于项目的设计和编码情况,J2EE项目的整合调试有很多办法,其中有两种比较方便使用的方法:Log记录跟踪和IDE工具调试。

使用System.out.println记录程序的执行过程,并输出程序中相关状态,System.out.println是最初级的Log记录调试办法,在中大型项目中的调试中就很难胜任。这时使用Log4jhttp:// jakarta.apache.org/log4j/)将非常方便,在以后章节中将讨论Log4J的使用方法。

Log记录输出对于模块或组件之间集成运行调试很有好处,但是在一些细部的调试上,特别是细部的语句运行顺序,使用Log记录输出就比较繁琐。这时使用JBuilder这样的IDE调试工具的断点调试就比较方便,而且能够迅速发现问题。

JBuilderJBuilder 7以上版本)为例,在JavaBeans中设定断点后,在Project属性的RUN中新增一个Run TypeServer,这时整合在JBuilder中的Tomcat将自动作为Web服务器。使用Debug命令运行Tomcat Server,在浏览器中输入网址访问本项目,在JBuilderServer控制台中将显示在设置断点处的停留,使用step over逐步运行每个断点,这样可以了解程序运行的顺序以及详细情况。

2.5.4  Tomcat连接池使用

前面已经讨论过,使用数据库连接池可以提高数据库的访问性能。Tomcat的数据库连接池是使用Jakarta-Commons项目中Database Connection Pool,包含下列组件:Jakarta-Commons DBCP Jakarta-Commons CollectionsJakarta-Commons Pool。这些库文件包必须和JDBC驱动程序一起安装在$CATALINA_HOME/common/lib这个目录下。如果检查发现没有,请到http://jakarta.apache.org/中下载相应的库文件包。

$CATALINA_HOME/common/lib必须有下列包:

·          commons-collections.jar

·          commons-dbcp.jar

·          commons-pool.jar

·          mysql-connector-java-3.0.7-stable-bin.jar  //MySQL的驱动程序。

确定这些库文件包确实无误后,进行Tomcat的配置。

上个章节介绍了在Tomcat中部署应用的方法,其中第2种方法是修改server.xml,加入新的Context,只有一行就直接结束了,现在需要在这个Context中再增加内容,如下:

<Context path="/register"

docBase="D:/javasource/train/SimpleRegister/defaultroot" debug="1"

                 reloadable="true" crossContext="true" >

<!--注意这里jdbc/userDBJDNI Name,可以自己取名,这类似一个通用令牌

 将在程序系统中也使用到 -->

 <Resource name="jdbc/userDB"   auth="Container"  type="javax.sql.DataSource"/>

  <ResourceParams name="jdbc/userDB">

    <parameter>

      <name>factory</name>

      <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>

    </parameter>

    <parameter>

      <name>maxActive</name> <!--最大连接数目 -->

      <value>100</value>

    </parameter>

    <parameter>

      <name>maxIdle</name> <!--最大空闲数,即最小连接数目 -->

      <value>30</value>

    </parameter>

    <parameter>

      <name>maxWait</name> <!--等待连接时间 -->

      <value>10000</value>

    </parameter>

    <parameter>

     <name>username</name>

     <value>banq</value> <!--数据库访问用户名 -->

    </parameter>

    <parameter>

     <name>password</name>

     <value>9999</value> <!--数据库访问用户名 -->

    </parameter>

    <parameter>

       <name>driverClassName</name>

       <value>com.mysql.jdbc.Driver</value><!-- 数据库驱动名 -->

    </parameter>

    <parameter>

      <name>url</name> <!-- 数据库URL -->

      <value>jdbc:mysql://localhost/user?autoReconnect=true</value>

    </parameter>

  </ResourceParams>

</Context>

 

后面几个参数配置就是JDBC的通用配置了,一旦Tomcat容器配置完成后,就可以在应用系统通过JNDI访问到这个数据库连接池。

本系统更改web.xml如下:

<web-app>

  <description> Simple Register</description>

  <resource-ref>

      <description>DB Connection</description>

      <res-ref-name>jdbc/userDB</res-ref-name>

      <res-type>javax.sql.DataSource</res-type>

      <res-auth>Container</res-auth>

  </resource-ref>

</web-app>

这样在Web容器中,通过java:comp/env/jdbc/userDB就可以寻找到jdbc/userDB的连接池。注意,在Java代码中写JNDI Name时,要加上java:comp/env/,这也是通用规定。

由于本系统的数据库驱动都是集中在MySQL一个JavaBeans中实现,这样修改数据库驱动代码就非常方便。如果分散在各个程序中,那么现在要使用连接池作为数据库连接了,就必须逐个程序修改,是非常麻烦的。

修改MySQL类的代码如下,未显示部分表示不变:

public Mysql() {

    try {

      getDataSource();   //使用容器的数据库连接池

      stmt = conn.createStatement();

    } catch (Exception e) {

      System.err.println("Mysql init error: " + e);

    }

  }

  //使用连接池获得Connection

  private void getDataSource() {

    try {//以下是通过JNDI定位寻找到DataSource

      Context ctx = new InitialContext();

      if (ctx == null)  throw new Exception("Boom - No Context");

      DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/userDB");

      if (ds != null) conn = ds.getConnection();

    } catch (Exception e) {

      System.err.println("getDataSource() error: " + e);

    }

  }

  //老的 直接获得连接的方法

  private void getDirectConn(){

    try {

      Class.forName(Constants.dbdriver).newInstance();

      conn = DriverManager.getConnection(Constants.dburl);

    } catch (Exception e) {

      System.err.println("getDataSource() error: " + e);

    }

  }

  public Mysql(String sql) {

    try {

      getDataSource();  //使用容器的数据库连接池

      prepareStatement(sql);

    } catch (Exception e) {

      System.err.println("Mysql init error: " + e);

    }

  }

至此,所有步骤均已经完成,重新编译本系统,在Tomcat运行测试,也许会发现响应速度提高不少。

为了更进一步提高性能,上例中通过JNDI获得DataSource的方法可以形成缓冲,这样节省JNDI搜寻时间,代码如下:

public class ServiceLocator {

private InitialContext ic;

    private Map cache;

    private static ServiceLocator me;

    static {

      try {

        me = new ServiceLocator();

      } catch(ServiceLocatorException se) {

        System.err.println(se);

        se.printStackTrace(System.err);

      }

    }

 

    private ServiceLocator() throws ServiceLocatorException  {

      try {

        ic = new InitialContext();

        cache = Collections.synchronizedMap(new HashMap());

      } catch (NamingException ne) {

            throw new ServiceLocatorException(ne);

      } catch (Exception e) {

            throw new ServiceLocatorException(e);

       }

    }

    static public ServiceLocator getInstance() {

      return me;  //单态模式 保证全局只有一个ServiceLocator

    }

 

public DataSource getDataSource(String dataSourceName)

throws ServiceLocatorException {

    DataSource dataSource = null;

      try {

        if (cache.containsKey(dataSourceName)) { //如果缓冲中存在DataSource

           dataSource = (DataSource) cache.get(dataSourceName);

        } else {

            //不存在就通过JNDI获取 然后放入缓存 下次使用

            dataSource = (DataSource)ic.lookup(dataSourceName);

            cache.put(dataSourceName, dataSource );

        }

      } catch (NamingException ne) {

         throw new ServiceLocatorException(ne);

      } catch (Exception e) {

            throw new ServiceLocatorException(e);

      }

      return dataSource;

}

这个类是以单态Singleton模式实现,这样在一个JVM中只有一个实例,从而保证缓冲的惟一性,当然,关于JNDI其他参数获取都可以采取这种方式,具体可见Sun公司Petstore中的ServiceLocator

 

下页