liupopo的专栏

原创 使用NetBeans5.0开发一个简单的网站程序

新一篇: 用NetBeans编写Filter,解决存入HsqlDb数据库中文问题。

使用NetBeans5.0开发一个简单的网站程序

敬告:
------------------------------------------------------------
    本文作者希望本文可以在网络及任何媒体进行任何形式的传播、复
制、引用、修改,在此过程中请保留此敬告内容。

                                 谢谢!
                                                    popo
------------------------------------------------------------

使用NetBeans5.0创建一个采用WebWork+Spring+Hibernate结构的简单网站,介绍NetBeans的部分功能。
程序的结构参照Appfuse(https://appfuse.dev.java.net/)及Equinox(https://equinox.dev.java.net/)实现。我写过一篇利用Appfuse进行开发的简单步骤(http://spaces.msn.com/liupopo/blog/cns!A1043CA66A0B4C53!126.entry?_c11_blogpart_blogpart=blogview&_c=blogpart#permalink)
该网站首先实现的主要功能是用户注册、登录、修改用户信息等简单操作,并不断的扩展完善,由简单到复杂,实现页面布局、安全验证、角色管理等功能(不断的集成进各种开源的工具)。
演示利用NetBeans5.0开发WebApplication应用。


一、需要用到的软件及Jar包:
JDK_5.0:Java开发工具包,不用介绍啦。http://java.sun.com/
NetBeans_5.0:Sun Microsystems公司与NetBeans社团推出的基于Java技术的开源集成开发环境(IDE)。http://www.netbeans.org/
HsqlDb_1.8:Hypersonic SQL是纯Java开发的关系型数据库,可以通过jdbc driver来存取。支持ANSI-92 标准 SQL语法。而且他占的空间很小,拥有快速的数据库引擎。http://www.hsqldb.org/
WebWork_2.1.7:WebWork是由OpenSymphony组织开发的,致力于组件化和代码重用的拉出式MVC模式J2EE Web框架。http://www.opensymphony.com/webwork/
Spring_1.2.6:Spring是一个解决了许多在J2EE开发中常见的问题的强大框架。 Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯。Spring的架构基础是基于使用JavaBean属性的 Inversion of Control容器。http://www.springframework.org/
Hibernate_3.1:Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。http://www.hibernate.org/
DisplayTag_1.1:JAVA的一个tagLib,主要是显示表格数据,很漂亮、完善。http://displaytag.sourceforge.net
SiteMesh_2.2.1:sitemesh应用Decorator模式,用filter截取request和response,把页面组件 head,content,banner结合为一个完整的视图。http://www.opensymphony.com/sitemesh/
Junit_3.8.1:单元测试工具。http://jakarta.apache.org/velocity/
Velocity_1.4:Velocity是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。http://jakarta.apache.org/velocity/
Jakarta-Commons:apache的一些公共包。http://jakarta.apache.org/
......

二、工作目录及设置
1.整个网站工程的名称:SimpleWebSite
2.创建开发目录,与项目相关的代码与文档工具等都放到这里:D:\ProjectNetBeans\SimpleWebSite
3.创建第三方JAR包目录,我是把所有的JAR包都解压到这一个目录里了:D:\ProjectNetBeans\SimpleWebSite\lib
4.创建参考资料、开发文档的目录:D:\ProjectNetBeans\SimpleWebSite\Documents
5.数据库存放目录:D:\ProjectNetBeans\SimpleWebSite\database\db
6.数据库Sql存放目录:D:\ProjectNetBeans\SimpleWebSite\database\sql
7.开发中用到的小工具存放目录:D:\ProjectNetBeans\SimpleWebSite\tools
8.用NetBeans创建三个项目,项目目录由NetBeans生成到SimpleWebSite目录下

三、准备数据库
利用HsqlDb做为数据库,方便携带。
1.将hsqldb.jar拷贝到D:\ProjectNetBeans\SimpleWebSite\database\db目录
2.在同一目录下新建一个文件:server.bat,用来启动数据库,采用HsqlDb Server模式,server.bat的内容如下:
java -cp hsqldb.jar org.hsqldb.Server -database.0 sws -dbname.0 sws
执行server.bat会创建sws数据库并启动。
3.在同一目录下新建一个文件:manager.bat,用来查看数据库的内容,执行SQL语句等,manager.bat的内容如下:
java -cp hsqldb.jar org.hsqldb.util.DatabaseManager

四、准备Web服务器
利用NetBeans自带的Tomcat做为Web服务器,如果以前用NetBeans做过Web项目的开发,需要在开始这个工程之前做一些准备工作,把C:\Documents and Settings\liupopo\.netbeans\5.0\jakarta-tomcat-5.5.9_base\conf\Catalina\localhost目录(这是我机器的目录,一般的是Administrator的用户目录)下曾做过Web项目的配置文件删除(只留admin.xml,manager.xml,ROOT.xml三个文件就可以),这样避免在调试时不受其他的项目的影响。

五、工程结构
整个工程由三个项目组成
1.SimpleWebSite_dao,数据访问层,包含Domain对象(POJO,实体对象,实体类)及数据库访问对象(DAO)。打包成SimpleWebSite_dao.jar。
2.SimpleWebSite_service,业务逻辑层,调用数据访问层进行业务逻辑的处理,实现与业务相关的方法等。打包成SimpleWebSite_service.jar。
3.SimpleWebSite_web,展示层,用户的操作在这里体现,包含JSP页面、动作类等,调用业务逻辑层的方法。打包成sws.war。

六、开发数据访问层
目标:创建一个User对象,并存入到数据库中。

启动数据库server.bat
使用数据库管理工具manager.bat建一个user表,用到的SQL语句保存在D:\ProjectNetBeans\SimpleWebSite\database\sql目录下的CreateTables.txt文件中。

drop table IF EXISTS User;
Create table User (
    id Bigint NOT NULL,
    name Char(20) NOT NULL,
    password Char(20) NOT NULL,
 Primary Key (id));

启动NetBeans5.0,选择“New Project...”-》“General”-》“Java Application”
“下一步”
Project Name为:SimpleWebSite_Dao
Project Location为:D:\liupopo\ProjectNetBeans\SimpleWebSite
不选择“Create Main Class”
“Finish”

我是把Lib目录下的所有JAR包都引用了,呵呵,其中很多用不到,NetBeans要扫描包引用路径,所以会浪费些时间,但可以保证类引用的完整和正确。


“New Java Class”
Class Name:BaseObject
Package:org.liupopo.simplewebsite.model
“Finish”

BaseObject :我准备把所有POJO对象都继承这个类
package org.liupopo.simplewebsite.model;

import java.io.Serializable;

/**
 *
 * @author liupopo
 */
public abstract class BaseObject implements Serializable {
   
    /** Creates a new instance of BaseObject */
    public BaseObject() {
    }
   
    public abstract String toString();
    public abstract boolean equals(Object o);
    public abstract int hashCode();
   
}


“New Java Class”
Class Name:User
Package:org.liupopo.simplewebsite.model
“Finish”

User :用户对象
package org.liupopo.simplewebsite.model;

/**
 *
 * @author liupopo
 */
public class User extends BaseObject {
   
    /** Creates a new instance of User */
    public User() {
    }
   
    public String toString() {
        return this.getName();
    }
   
    public boolean equals(Object o) {
        return true;
    }
   
    public int hashCode() {
        return 0;
    }
   
    private Long id;
    private String name;
    private String passWord;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
   
}

 
“New XML Document”
File Name:User.hbm
“Finish”

User.hbm.xml :用户对象与数据库表的映射文件(ORM),这个文件放在与User同一个目录(包)下。
 <?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="org.liupopo.simplewebsite.model.User"
           table="user"
           dynamic-update="false"
           dynamic-insert="false" >

        <id name="id"
            column="id"
            type="java.lang.Long"
            unsaved-value="null">
            <generator class="increment" >
            </generator>
        </id>

        <property
            name="name"
            type="java.lang.String"
            update="true"
            insert="true"
            column="name"
        />
       
        <property
            name="passWord"
            type="java.lang.String"
            update="true"
            insert="true"
            column="password"
        />

    </class>

</hibernate-mapping>


“New Properties File”
File Name:database
“Finish”

database.properties:数据库连接的配置文件,该文件放在DAO项目的根目录下
# Sample ResourceBundle properties file
hibernate.connection.username=sa
dao.type=hibernate
hibernate.connection.password=
hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.connection.url=jdbc:hsqldb:hsql://localhost/sws
hibernate.connection.show_sql=true
hibernate.connection.driver_class=org.hsqldb.jdbcDriver


“New XML Document”
File Name:applicationContext-resources
“Finish”

applicationContext-resources.xml:Spring用到的资源的配置文件,如数据库参数,JMail参数等
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:database.properties</value>
            </list>
        </property>
    </bean>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${hibernate.connection.driver_class}"/>
        <property name="url" value="${hibernate.connection.url}"/>
        <property name="username" value="${hibernate.connection.username}"/>
        <property name="password" value="${hibernate.connection.password}"/>
    </bean>
</beans>


“New XML Document”
File Name:applicationContext-hibernate
“Finish”

applicationContext-hibernate.xml:Spring用到的Hibernate相关配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
    <!-- Hibernate SessionFactory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mappingResources">
            <list>
                <value>org/liupopo/simplewebsite/model/User.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            </props>
        </property>
    </bean>

    <bean id="userDao" class="org.liupopo.simplewebsite.dao.hibernate.UserDaoImpl">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

</beans>


“New Java Interface”
Class Name:UserDao
Package:org.liupopo.simplewebsite.dao
“Finish”

UserDao:用户对象的数据库访问接口,现在暂时这样写,以后实体对象多了,需要重构,都继承一个公共的DAO接口。
package org.liupopo.simplewebsite.dao;

import java.util.List;
import org.liupopo.simplewebsite.model.User;

/**
 *
 * @author liupopo
 */
public interface UserDao {
   
    public Long saveUser(User user);
    public boolean deleteUser(User user);
    public boolean deleteAllUser();
    public User findUserById(Long id);
    public User findUserByName(String name);
    public List findAllUsers();
   
}


“New Java Class”
Class Name:UserDaoImpl
Package:org.liupopo.simplewebsite.dao.hibernate
“Finish”

UserDaoImpl:用户对象的数据库访问接口的具体实现。
package org.liupopo.simplewebsite.dao.hibernate;

import java.util.List;
import org.liupopo.simplewebsite.dao.UserDao;
import org.liupopo.simplewebsite.model.User;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

/**
 *
 * @author liupopo
 */
public class UserDaoImpl  extends HibernateDaoSupport implements UserDao {
   
    /** Creates a new instance of UserDaoImpl */
    public UserDaoImpl() {
    }
   
    public Long saveUser(User user) {
        Long id = 0L;
        getHibernateTemplate().saveOrUpdate(user);
        id = user.getId();
        return id;
    }
    public boolean deleteUser(User user) {
        boolean result = false;
        getHibernateTemplate().delete(user);
        result = true;
        return result;
    }
   
    public boolean deleteAllUser(){
        boolean result = false;
        getHibernateTemplate().deleteAll(findAllUsers());
        result = true;
        return result;
    }
    public User findUserById(Long id){
        User user = null;
        user = (User)getHibernateTemplate().get(User.class,id);
        return user;
    }
    public User findUserByName(String name){
        User user = null;
        String sqlString = "from User as user where user.name = ?";
        user = (User)getHibernateTemplate().find(sqlString,name);
        return user;
    }
   
    public List findAllUsers(){
        List userList = null;
        userList = getHibernateTemplate().find("from User");
        if (userList.size() < 1) {
            userList = null;
        }
        return userList;
    }
   
}


“New Java Class”
Class Name:UserDaoTest
Package:org.liupopo.simplewebsite.dao
“Finish”

UserDaoTest:用户对象的数据库访问接口的单元测试,这个文件是放在test的源文件夹下的。
package org.liupopo.simplewebsite.dao;

import org.liupopo.simplewebsite.model.*;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;

/**
 *
 * @author liupopo
 */
public class UserDaoTest extends AbstractDependencyInjectionSpringContextTests {
   
    public UserDaoTest() {
    }

    protected String[] getConfigLocations() {
        return new String [] {"classpath*:/**/applicationContext-*.xml"};
    }
    private User user = null;
    private UserDao dao = null;
   
    public void setUserDao(UserDao dao) {
        this.dao = dao;
    }
   
    public void testSaveUserToDatabase() throws Exception {
        user = new User();
        user.setName("liupopo");
        user.setPassWord("liupopo");

        dao.saveUser(user);
        assertNotNull(user.getId());
    }
    public void testDeleteAllUsers() throws Exception {
        user = new User();
        user.setName("liupopo");
        user.setPassWord("liupopo");

        dao.saveUser(user);
        assertNotNull(user.getId());
       
        dao.deleteAllUser();
       
        assertNull(dao.findAllUsers());
    }
   
    public void testDeleteUserFromDatabase() throws Exception {
        user = new User();
        user.setName("aaa");
        user.setPassWord("aaa");

        dao.saveUser(user);
        assertNotNull(user.getId());
       
        dao.deleteUser(user);
        assertNull(dao.findUserById(user.getId()));
    }
}


All tests passed.. 
要保证Lib引用完整,Clean And Build Project,NetBeans会帮我们打Jar包。
:)数据访问层的开发工作告一段落。


七、开发业务逻辑层
这一部分主要实现业务逻辑组件,用来接收层示层的业务请求,调用Dao层取得数据库的数据,进行逻辑处理与运算,将结果返回给展示层。

“New Project...”-》“General”-》“Java Application”
“下一步”
Project Name为:SimpleWebSite_Service
Project Location为:D:\liupopo\ProjectNetBeans\SimpleWebSite
不选择“Create Main Class”
“Finish”

为了省事儿,我仍是把Lib目录下的所有JAR包都引用了,并且还引用SimpleWebSite_Dao项目,这样,每次编译的时候会先编译SimpleWebSite_Dao项目,并打成Jar包,这是NetBeans给我提供的便利。


先把Dao项目中的Spring配置文件(两个Xml和一个Properties)拷贝到src目录下,我当时认为引用了Dao的Jar包,而这个配置文件已经打包进Jar里并在根目录下,应该直接用Jar包里的文件的,那样的话我只关心本层的资源及配置文件多爽啊,但事实上好象不行,:( 所以我又拷贝一份。

“New Java Interface”
Name:UserManager
Package:org.liupopo.simplewebsite.service
“Finish”

UwerManager :用户管理接口,这里需要重构,应该管理类接口都继承自一个总的接口
package org.liupopo.simplewebsite.service;

import java.util.List;
import org.liupopo.simplewebsite.dao.UserDao;
import org.liupopo.simplewebsite.model.User;

/**
 * 用户管理
 * @author liupopo
 */
public interface UserManager {
   
    /**
     * 保存一个用户至数据库
     * @param user 用户对象
     * @return Long 用户对象的ID
     */
    public Long saveUser(User user);
    public List findAllUsers();

    void setUserDao(UserDao userDao);
}


“New Java Class”
Class Name:UserManagerImpl
Package:org.liupopo.simplewebsite.service.impl
“Finish”

UserManagerImpl :UserManager接口的实现类
package org.liupopo.simplewebsite.service.impl;

import java.util.List;
import org.liupopo.simplewebsite.dao.UserDao;
import org.liupopo.simplewebsite.model.User;
import org.liupopo.simplewebsite.service.UserManager;

/**
 *
 * @author liupopo
 */
public class UserManagerImpl implements UserManager{
   
    /** Creates a new instance of UserManagerImpl */
    public UserManagerImpl() {
    }
    private UserDao dao = null;
    public void setUserDao(UserDao dao) {
        this.dao = dao;
    }

    public Long saveUser(User user) {
        return dao.saveUser(user);
    }
   
    public List findAllUsers(){
        return dao.findAllUsers();
    }
}

“New XML Document”
File Name:applicationContext-service
“Finish”

applicationContext-service :Spring用到的Bean配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
   
    <!-- Transaction template for Managers, from:
         http://blog.exis.com/colin/archives/2004/07/31/concise-transaction-definitions-spring-11/ -->
    <bean id="txProxyTemplate" abstract="true"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager" ref="transactionManager"/>
        <property name="transactionAttributes">
            <props>
                <prop key="find*">PROPAGATION_REQUIRED</prop>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="delete*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
    <!-- Transaction declarations for business services.  To apply a generic transaction proxy to
         all managers, you might look into using the BeanNameAutoProxyCreator -->
    <bean id="userManager" parent="txProxyTemplate">
        <property name="target">
            <bean class="org.liupopo.simplewebsite.service.impl.UserManagerImpl">
                <property name="userDao" ref="userDao"/>
            </bean>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    <!-- Add new Managers here -->
</beans>


“New Java Class”
Class Name:UserManagerTest
Package:org.liupopo.simplewebsite.service
“Finish”

UserManagerTest :UserManager接口的单元测试
package org.liupopo.simplewebsite.service;

import org.liupopo.simplewebsite.model.User;
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
import java.util.ResourceBundle;

/**
 *
 * @author liupopo
 */
public class UserManagerTest extends AbstractTransactionalDataSourceSpringContextTests {
   
    private UserManager userManager;
    private User user = null;
    protected ResourceBundle rb;
   
    public UserManagerTest() {
        // Since a ResourceBundle is not required for each class, just
        // do a simple check to see if one exists
        String className = this.getClass().getName();

        try {
            rb = ResourceBundle.getBundle(className);
        } catch (Exception mre) {
            //log.warn("No resource bundle found for: " + className);
        }
    }
   
    public void setUserManager(UserManager userManager) {
        this.userManager = userManager;
    }
   
    protected String[] getConfigLocations() {
        return new String[] {"classpath*:/**/applicationContext-*.xml"};
    }
   
    public void testSaveUserToDatabase() throws Exception {
        user = new User();
        user.setName("liupopo");
        user.setPassWord("liupopo");

        userManager.saveUser(user);
        assertNotNull(user.getId());
        user = new User();
        user.setName("aaa");
        user.setPassWord("liuaaaapopo");

        userManager.saveUser(user);
        assertNotNull(user.getId());
        assertNotNull(userManager.findAllUsers().size()>0);
    }
   
}

All tests passed.. 
OK,Clean And Build Project,NetBeans帮我们打Jar包。
:)数据访问层的开发工作告一段落。
其实业务逻辑层应该是比Dao层要复杂的,因为很多业务逻辑要在这里实现,但我这网站功能很简单,所以这里反而不用写太多东西。


八、开发WEB层,页面显示
实现一个网站,调用Service层的功能,做到在页面输入用户名和密码,向逻辑层发送保存用户的请求,将用户对象保存进数据库中。

打开NetBeans5.0,这里我们要新建的不是“Java Application”的项目,应该是一个Web Project。NetBeans会给我们把目录安排好,最后网站的打包、发布,都不用我们操心了。

“New Project”-》“Web”-》“Web Applictaion”
“Next”
Project Name:SimpleWebSite_web
Project Location为:D:\liupopo\ProjectNetBeans\SimpleWebSite
Source Structrue:Java BluePrints(选这一项,我们的后台源代码会生成到src/java目录下)
Server:Bundled Tomcat(5.5.9)
J2EE Version:1.4
Context Path:/sws(这里请注意一下,我没有用默认的/SimpleWebSite_web,因为这个是我们在浏览器URL里要访问的名称,太长了输起来太麻烦,呵呵)
选上“Set Source Level to 1.4”
选上“Set as Main Project”
“Next”
在这个项目里,我们不用JSF和Struts,MVC框架选用的是WebWork2.1.6
所以直接点“Finish”

大家可以看一下NetBeans帮我们生成的目录,呵呵,这是当初我喜欢并执着的用着NetBeans的起因。
好了,继续,在这里,我仍把Lib目录下的所有包引用了进来,其实这个项目与上面两个是不同的,因为最终要打包成War包,会把相依赖的Jar包都打包进去,我选了很多没有用到的Jar包,会增大发布的War包的容量,呵呵,不过先不管,因为我们以后不断的扩展功能,会用到这些包的,先这样。
然后还要再引入两个项目,Dao和Service。

先把Service项目中的Spring配置文件(现在是三个Xml和一个Properties)拷贝到src/java(这里才是Classpath的根目录)目录下。

因为我们把WebWork包等所要用到的Jar包都已经引入项目了,下面就是开始配置相关文件。

先要更改web.xml文件,这是站点的核心布署文件。在这里我们要加入以下内容:
增加、配置WebWork的Servlet:我们要用WebWork当然要做这一步,跟用Struts一样的。
增加一个环境常量context-param:这是Spring要用到的,把我们写的那些Spring的配置文件指明到哪里去调用。
增加两个listener:一个是Spring调用配置文件要用到的,另一个是Spring与WebWork集成用到的。
关于这部分内容包括后面关于WebWork的配置可以参考WebWork的文档,呵呵,我以前都是用的Struts,头一次用WebWork,照猫画虎效率也挺高的。

整个web.xml文件的内容如下:
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">
    <display-name>My SimpleWebSite</display-name>
  
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:/**/applicationContext-*.xml</param-value>
    </context-param>
 
    <servlet>
        <servlet-name>webwork</servlet-name>
        <servlet-class>com.opensymphony.webwork.dispatcher.ServletDispatcher</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>webwork</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>com.opensymphony.xwork.spring.SpringObjectFactoryListener</listener-class>
    </listener>
   
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
   
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

“New XML Document”
File Name:xwork
“Finish”

xwork.xml:WebWork用到的Action的配置文件,我们可以从WebWork的示例文件中拷贝出来进行修改。
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-1.0.dtd">

<xwork>
    <!-- Include webwork defaults (from WebWork JAR). -->
    <include file="webwork-default.xml" />
   
    <!-- Configuration for the default package. -->
    <package name="default" extends="webwork-default">   
        <default-interceptor-ref name="defaultStack" />
        <action name="register" class="register.key">
            <result name="error" type="dispatcher">register.jsp</result>
            <result name="success" type="dispatcher">ok.jsp</result>
        </action>
    </package>
</xwork>

“New XML Document”
File Name:validators
“Finish”

validators.xml:WebWork提供的进行数据验证的文件,和上面那个文件一样,我是从WebWork的示例中拷贝出来进行修改的,呵呵,不过这个文件是原样照搬,不做任何改动。
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator
1.0//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.dtd">

<validators>
    <validator name="required"
        class="com.opensymphony.xwork.validator.validators.RequiredFieldValidator"/>
    <validator name="requiredstring"
        class="com.opensymphony.xwork.validator.validators.RequiredStringValidator"/>
    <validator name="int"
        class="com.opensymphony.xwork.validator.validators.IntRangeFieldValidator"/>
    <validator name="date"
        class="com.opensymphony.xwork.validator.validators.DateRangeFieldValidator"/>
    <validator name="expression"
        class="com.opensymphony.xwork.validator.validators.ExpressionValidator"/>
    <validator name="fieldexpression"
        class="com.opensymphony.xwork.validator.validators.FieldExpressionValidator"/>
    <validator name="email"
        class="com.opensymphony.xwork.validator.validators.EmailValidator"/>
    <validator name="url"
        class="com.opensymphony.xwork.validator.validators.URLValidator"/>
    <validator name="visitor"
        class="com.opensymphony.xwork.validator.validators.VisitorFieldValidator"/>
    <validator name="conversion"
        class="com.opensymphony.xwork.validator.validators.ConversionErrorFieldValidator"/>
</validators>


“New XML Document”
File Name:applicationContext-webwork
“Finish”

applicationContext-webwork.xml:将WebWork的Action和Spring的Bean进行结合的配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="register.key" class="org.liupopo.simplewebsite.web.action.RegisterAction">
        <property name="userManager">
            <ref bean="userManager"/>
        </property>
    </bean>
</beans>

好了,看xwork.xml文件中,“register”这个Action如果成功就到“ok.jsp”,失败就回到“index.jsp”,他的执行类是“register.key”,到要applicationContext-webwork中去找,并且可以看到它引用了“userManager”。

修改NetBeans提供的index.jsp,NetBeans为我们提供了简单的JSP文件的编辑功能,呵呵,我原来写JSP一直用的EditPlus,象DW、FontPage等可视的页面编辑软件从来不用,因为我还要大量的修改那些东西给我生成的没用的代码,修改我的变量等等。现在可以只用NetBeans啦,不过NetBeans如果能提供个象EditPlus那样的页面预览功能就太好了。
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>

        <h1>JSP Page</h1>
        <form action="register.action" method="POST">
            username:<input type="text" name="userName" value="" /><br/>
            password:<input type="text" name="password" value="" /><br/>
            <p><input type="submit" value="register" /></p>
        </form>
    </body>
</html>


“New Java Class”
Class Name:RegisterAction
Package:org.liupopo.simplewebsite.web.action
“Finish”

RegisterAction:用户注册的Action,在applicationContext-webwork有配置的。
package org.liupopo.simplewebsite.web.action;

import com.opensymphony.xwork.ActionSupport;
import org.liupopo.simplewebsite.model.User;
import org.liupopo.simplewebsite.service.UserManager;

/**
 *
 * @author liupopo
 */
public class RegisterAction extends ActionSupport{
   
    /** Creates a new instance of RegisterAction */
    public RegisterAction() {
    }
   
    private String userName;
    private String password;
    private UserManager userManager;
   
    //这里的userManager是由Spring注入的
    public void setUserManager(UserManager userManager){
        this.userManager = userManager;
    }
   
    //Action默认执行的动作,WebWork好象可以配置自己的执行方法,比Struts强
    public String execute() throws Exception {
        if(register()){
            return SUCCESS;
        } else {
            return this.ERROR;
        }
    }
   
    //进行注册
    private boolean register(){
        boolean result = false;
        if (userName == null || userName.length() < 1) {
            result = false;
        } else {
            User user = new User(); //WebWork可以直接Save一个User对象的,我还没从Struts里出来,呵呵,先这样写吧。
            user.setName(userName);
            user.setPassWord(password);
            userManager.saveUser(user);
            result = true;
        }
        return result;
    }
   
    //在ok.jsp中准备把用户名返回,所以加上这个方法
    public String getUserName() {
        return userName;
    }
   
    //从页面Form中取userName的值
    public void setUserName(String userName) {
        this.userName = userName;
    }
   
    //从页面Form中取password的值
    public void setPassword(String password) {
        this.password = password;
    }
}


“New JSP”
JSP File Name:ok
“Finish”

ok.jsp:用户注册成功转向的页面。
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@taglib prefix="ww" uri="webwork"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>

    <h1>JSP Page</h1>
    操作成功!
    <br/>
    欢迎你:<ww:property value="userName" />
   
    </body>
</html>



现在一个网站已经完成啦,虽然只有两个页面和一个保存动作。让我们看看效果吧。
Clean and Build Project..
记得启动数据库server.bat
run Project
输入用户名和密码,register..。OK..
打开数据库管理manager.bat,看看我们刚刚插入的数据。一个最简单的网站已经完成啦。


九、补充

前面的代码与示例,实在是太简单太粗糙啦,在实际的开发环境中应该是不具有实用价值的,但按照上面的步骤一步步做下来,已经实现了一个整体的框架,使我们整个工程的思路非常清析,通过不断的新增与重构,更加复杂的业务逻辑、功能等都可以一点点的完善。
NetBeans给我们提供了一个简单、实用、高效的开发环境,在开发中不断的发掘它的功能,会大大提高我们的开发效率,尤其它对项目目录的组织,对我理顺上面三层的关系非常有帮助。
把一个工程分成上面提到的三个项目,也是有好处的,不仅仅是结构清析,而且Dao和Service的可复用性非常的高,我用Swing写了一个很简单的注册界面,直接调用的Service层的保存功能,回头如果要实现PDA上的显示、网站改用其他架构等等,数据层和逻辑层几乎都不用做修改了。如果数据访问层不用Hibernate改为其他的,业务逻辑层与界面层都不需要改动。对于以前的老的项目,一般都有数据层了,改动逻辑层与界面层,也会有一个很合理的结构。
顺便提一下,用NetBeans开发Swing客户端就是一个爽字,呵呵。不象写WEB那样要配置来配置去的,比VB用着还要感觉爽,写Web时又查资料又改配置的费了将近半小时的时间才做完了一个注册页面,实现同样的功能写Swing只用了四五分钟,呵呵,以后要好好的研究一下Swing做客户端了。如果实现资源文件的国际化,也可以直接把Web的资源拿来修改就可以啦。呵呵,想想,做成Swing的多漂亮啊。

这个工程是参照AppFuse来实现的,采用驱动开发(TDD)的模式,我对驱动开发一知半解,有时间需要好好研究一下,先写测试再写程序实现,而且NetBeans将测试代码放在单独的源码目录里,使程序的代码结构非常整洁。
对源代码进行版本控制、每日构建和集成测试,一个人开发体现不出,如果是团队开发的话,这些功能是非常重要的。因为NetBeans用Ant进行项目的管理,实现这些功能应该会很方便。

目前还存在的问题:
1.HsqlDb存入中文的时候乱码。
2.就是Spring的配置文件,还是要各层用各层的,打到Jar包里,不用每个项目里都拷贝。


要添加的功能:
1.页面的布局,用SiteMesh来实现,整个网站分成Head,Body,Footer三部分。
2.增加用户查询,用DisplayTag来做表格显示。
3.加入角色管理,用Acegi来实现安全机制。
4.界面展示采用Velocity做为模板
5.菜单:Appfuse1.8用的Struts-menu做菜单,很方便使用,而且可以实现权限控制等,但在最新的Appfuse1.9中好象没有用到,等用过后再说。
6.网站加入更多的业务逻辑,考虑做一个BBS或者Blog,不断增加与重构,使这个工程具有实际的价值。


呵呵,到现在,这个网站工程才刚刚开始......

发表于 @ 2006年03月25日 02:53:00|评论(loading...)|编辑

评论

#HelloX 发表于2006-08-22 13:41:00  IP: 221.194.5.*
清晰适用,是很好的教科书。
发表评论  


当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
Csdn Blog version 3.1a
Copyright © liupopo