用JSP/Servlet开发简单的用户注册系统
作者:板桥banq
上页
2.5.2 快速配置开发环境
JBuilder是一个很强大的Java开发工具。因为其包含内容太多,有时用来作为小型项目的JSP/Javabeas开发显得过于“笨重”,而且学习JBuilder配置使用还需要一定的时间和精力。下面介绍一套简单快速轻便的开发和调试环境。
· Jcreator(http://www.jcreator.com/)用来编辑调试JavaBean。
· Dreamweaver (editplus)用来编辑JSP和HTML文件。
· Tomcat作为Serlvet/JSP容器服务器。
· MySQL作为数据库服务器。
这套组合可以直接通过IE浏览器调试JSP或JavaBean,与JBuilder这样庞大的IDE工具软件相比,最大优点是资源消耗少,可以发挥各自工具的特点。例如DreamWeaver强大的可视化图形开发界面非常方便HTML/JSP的开发。
开发环境配置:
(1)在自己的PC Windows上安装JDK。目前最新版本是JDK 1.4,可以从http://java.sun.com下载安装。
(2)建立自己项目的目录,如D:/javasource/SimpleRegister/放置的都是项目JSP或JavaBean文件的目录,在myweb下可以建立4个目录:
· defaultroot根目录:放置JSP源程序。
· defaultroot/ WEB-INF/classes:编译后的javabean运行程序。
· defaultroot/ WEB-INF/lib:驱动程序包。
· src目录:JavaBeans的源程序。
(3)下载3个JDK中没有携带的驱动包:Servlet包(servlet.jar) JavaMail包(mail.jar)和MySQL JDBC驱动程序包(mysql-connector-xxx.jar)。前两者可以从Sun网站下载。如果已经安装了Tomcat,可以使用Tomcat/common/lib目录下的servlet.jar和mail.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)安装MySQL。MySQL可以从MySQL.com下载最新版本。从MySQL 4.0以后版本已经整合了原来MySQL 3 MAX版本的功能,变得非常强大而有效,下载后运行bin\winmysqladmin.exe就可以启动MySQL了。
MySQL的管理工具下载使用MySQL Control Center或PhpMyAdmin。前者可以从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访问密码';
修改Apache的httpd.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/Servlet是J2EE的一种技术规范,它的运行需要特定的支持容器。容器在运行时将JSP编译后作为Servlet运行,容器使用线程池来实现Servlet的运行。J2EE容器虽然确保使用者不用担心线程以及同步等问题,但是要真正用好Web系统,还需要掌握一定的Java线程基础知识,必须遵循一定的线程使用规则。如果超过规则使用JSP/Servlet,那么会给系统带来隐含的运行风险。
目前支持JSP/Servlet的应用服务器软件很多,如Tomcat、Weblogic等。Tomcat(http://jakarta.apache.org/tomcat/)是著名Apache雅加达组织推出的开放源代码软件。它们曾经推出著名HTTP服务器Apache,Apache随着Linux的发展,已经占据整个互联网服务器软件大半壁江山,相信Tomcat也会像Apache那样有着广阔的发展前景。
从Tomcat网站下载最新的Tomcat软件,Tomcat 4.0以后又取名为Catalina,整个架构设计和以前版本有很大不同。研究Tomcat源码会发现,其中也是主要基于TCP Socket连接上集合了线程池技术的一个Java应用系统。当然,在这里并不是研究如何开发Tomcat,而是讨论JSP/Servlet程序如何部署在Tomcat下运行。
将本项目部署到Tomcat下有两种方法:
(1)将本项目根目录复制到Tomcat的webapps目录下,Tomcat在启动后就能使用根目录名访问本项目。例如项目的根目录名为SimpleRegister,那么这样部署后,通过浏览器http://localhost:8080/SimpleRegister就能访问到本项目。本方法需要复制目录,在反复调试时非常不方便,推荐使用第二种方法。
(2)修改Tomcat的conf目录下的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-INF的lib下就需要支持Java JDBC的库文件*.jar,MySQL数据库的库文件是mysql-connector-java-XXX-stable-bin.jar。
如果Tomcat正常启动,没有任何错误发生,表明本项目部署成功了,可以输入网址http://localhost:8080/register访问。
调试项目的复杂程度取决于项目的设计和编码情况,J2EE项目的整合调试有很多办法,其中有两种比较方便使用的方法:Log记录跟踪和IDE工具调试。
使用System.out.println记录程序的执行过程,并输出程序中相关状态,System.out.println是最初级的Log记录调试办法,在中大型项目中的调试中就很难胜任。这时使用Log4j(http:// jakarta.apache.org/log4j/)将非常方便,在以后章节中将讨论Log4J的使用方法。
Log记录输出对于模块或组件之间集成运行调试很有好处,但是在一些细部的调试上,特别是细部的语句运行顺序,使用Log记录输出就比较繁琐。这时使用JBuilder这样的IDE调试工具的断点调试就比较方便,而且能够迅速发现问题。
以JBuilder(JBuilder 7以上版本)为例,在JavaBeans中设定断点后,在Project属性的RUN中新增一个Run Type为Server,这时整合在JBuilder中的Tomcat将自动作为Web服务器。使用Debug命令运行Tomcat Server,在浏览器中输入网址访问本项目,在JBuilder的Server控制台中将显示在设置断点处的停留,使用step over逐步运行每个断点,这样可以了解程序运行的顺序以及详细情况。
2.5.4 Tomcat连接池使用
前面已经讨论过,使用数据库连接池可以提高数据库的访问性能。Tomcat的数据库连接池是使用Jakarta-Commons项目中Database Connection Pool,包含下列组件:Jakarta-Commons DBCP 、Jakarta-Commons Collections和Jakarta-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/userDB是JDNI 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。
下页