怎么样,看到这么绚丽的效果之后,大家心痒了吧!这些都是extjs产生的效果,RIA(富客户端应用)是今后的潮流和趋势,建议大家多了解下客户端的技术,特别是些优秀的JS组件。好咧,工欲善其事,必先利其器。我们先来准备开发环境:
各种开源框架环境及下载:
ExtJS:2.X http://extjs.com/
DWR:2.X http://directwebremoting.org/dwr/download
JSON:JSON可以到http://www.json.org/查看详细内容,这里使用json-lib http://json-lib.sourceforge.net/
Spring:2.x http://springframework.org/
Hibernate:3.x http://www.hibernate.org/ 需要hibernate core 和annotations 包。
我们采用的开发工具是Eclipse3.4(或MyEclipse7.0)+SqlServer 2000。准备就绪,现在就开始吧!
先执行数据库脚本,完成数据库的设计:
CREATE DATABASE hrproject
go
USE hrproject;
go
CREATE TABLE person (
id int NOT NULL identity(1,1),
name varchar(200) default NULL,
age varchar(20) default '0',
unitName varchar(200) default NULL,
address varchar(200) default NULL,
telephone varchar(20) default NULL,
gender varchar(20) default NULL,
PRIMARY KEY (id)
)
go
CREATE TABLE unit (
id int NOT NULL identity(1,1),
name varchar(200) NOT NULL,
description varchar(200) default NULL,
parentId int default NULL,
PRIMARY KEY (id)
)
go
CREATE TABLE userInfo (
id int NOT NULL identity(1,1),
userName varchar(200) default NULL,
passWord varchar(200) default NULL,
isValid int default NULL,
PRIMARY KEY (id)
)
INSERT INTO person (name, age, unitName, address, telephone, gender) VALUES
('许亮','30','交通部','武汉市武昌区华中电脑数码城','13234534431','男')
INSERT INTO person (name, age, unitName, address, telephone, gender) VALUES
('张飞','41','交通部','武汉市武昌区华中电脑数码城','13321136431','男')
INSERT INTO person (name, age, unitName, address, telephone, gender) VALUES
('关羽','53','税务部','武汉市武昌区华中电脑数码城','13831115753','男')
INSERT INTO person (name, age, unitName, address, telephone, gender) VALUES
('貂蝉','32','人事部','武汉市武昌区华中电脑数码城','13631115753','女')
COMMIT;
INSERT INTO unit ( name, description, parentId) VALUES
('交通部','管交通的',0)
INSERT INTO unit ( name, description, parentId) VALUES
('税务部','管税务的',1)
INSERT INTO unit ( name, description, parentId) VALUES
('人事部','管人的',1);
COMMIT;
INSERT INTO userInfo (userName, passWord, isValid) VALUES
('leno','123',1);
COMMIT;
select * from person
好了,在sqlserver 2000的查询分析器里面执行成功后,数据库的设计就告一段落。我们再来看看WEB应用程序的核心配置文件:web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 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">
<welcome-file-list>
<welcome-file>logon.jsp</welcome-file>
</welcome-file-list>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/applicationContext.xml
</param-value>
</context-param>
<servlet>
<servlet-name>Dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/applicationContext.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Dispatcher</servlet-name>
<url-pattern>*.hr</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>
org.directwebremoting.servlet.DwrServlet
</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>classes</param-name>
<param-value>java.lang.Object</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
我们在上面主要配置了Spring MVC的核心DispatcherServlet和DWR的服务器端核心DwrServlet,为我们后续使用做准备。(接着可以利用MyEclipse开发工具增加对hibernate和spring框架的支持),你用Eclipse也没关系。下面是Hibernate框架的核心配置文件:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- configure datasource -->
<property name="connection.driver_class">
com.microsoft.jdbc.sqlserver.SQLServerDriver
</property>
<property name="connection.url">
jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=hrproject;SelectMethod=cursor
</property>
<property name="connection.username">sa</property>
<property name="connection.password">123</property>
<property name="hibernate.connection.pool_size">20</property>
<property name="hibernate.c3p0.min_size">1</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.max_statements">50</property>
<!-- configure fetch_depth -->
<property name="hibernate.max.fetch_depth">5</property>
<!-- configure dialect -->
<property name="dialect">
org.hibernate.dialect.SQLServerDialect
</property>
<!--auto generate datatable-->
<!-- <property name="hibernate.hbm2ddl.auto">create</property> -->
<!-- configure show_sql -->
<property name="hibernate.show_sql">true</property>
<!-- configure transactionFactory -->
<property name="hibernate.transaction.factory_class">
org.hibernate.transaction.JDBCTransactionFactory
</property>
<mapping class="org.leno.hr.Person" />
<mapping class="org.leno.hr.User" />
<mapping class="org.leno.hr.Unit" />
</session-factory>
</hibernate-configuration>
上面主要配置了数据源,hibernate的各项属性,以及实体类的映射!里面用到了3个实体类如下:
1. User.java
package org.leno.hr;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* User entity.
*
* @author MyEclipse Persistence Tools
*/
@Entity
@Table(name = "userInfo", schema = "dbo", catalog = "hrproject")
public class User implements java.io.Serializable {
// Fields
/**
*
*/
private static final long serialVersionUID = 2348712504535787456L;
private Integer id;
private String userName;
private String passWord;
private Integer isValid;
// Constructors
/** default constructor */
public User() {
}
/** full constructor */
public User(String userName, String passWord, Integer isValid) {
this.userName = userName;
this.passWord = passWord;
this.isValid = isValid;
}
// Property accessors
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name = "userName", length = 200)
public String getUserName() {
return this.userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Column(name = "passWord", length = 200)
public String getPassWord() {
return this.passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
@Column(name = "isValid")
public Integer getIsValid() {
return this.isValid;
}
public void setIsValid(Integer isValid) {
this.isValid = isValid;
}
}
2. Person.java
package org.leno.hr;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* Person entity.
*
* @author MyEclipse Persistence Tools
*/
@Entity
@Table(name = "person", schema = "dbo", catalog = "hrproject")
public class Person implements java.io.Serializable {
// Fields
/**
*
*/
private static final long serialVersionUID = 31884724861871585L;
private Integer id;
private String name;
private String age;
private String unitName;
private String address;
private String telephone;
private String gender;
// Constructors
/** default constructor */
public Person() {
}
/** full constructor */
public Person(String name, String age, String unitName, String address,
String telephone, String gender) {
this.name = name;
this.age = age;
this.unitName = unitName;
this.address = address;
this.telephone = telephone;
this.gender = gender;
}
// Property accessors
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name = "name", length = 200)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "age", length = 20)
public String getAge() {
return this.age;
}
public void setAge(String age) {
this.age = age;
}
@Column(name = "unitName", length = 200)
public String getUnitName() {
return this.unitName;
}
public void setUnitName(String unitName) {
this.unitName = unitName;
}
@Column(name = "address", length = 200)
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
@Column(name = "telephone", length = 20)
public String getTelephone() {
return this.telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
@Column(name = "gender", length = 20)
public String getGender() {
return this.gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
3. Unit.java
package org.leno.hr;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* Unit entity.
*
* @author MyEclipse Persistence Tools
*/
@Entity
@Table(name = "unit", schema = "dbo", catalog = "hrproject")
public class Unit implements java.io.Serializable {
// Fields
/**
*
*/
private static final long serialVersionUID = -1267061245966981171L;
private Integer id;
private String name;
private String description;
private Integer parentId;
// Constructors
/** default constructor */
public Unit() {
}
/** minimal constructor */
public Unit(String name) {
this.name = name;
}
/** full constructor */
public Unit(String name, String description, Integer parentId) {
this.name = name;
this.description = description;
this.parentId = parentId;
}
// Property accessors
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name = "name", nullable = false, length = 200)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "description", length = 200)
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
@Column(name = "parentId")
public Integer getParentId() {
return this.parentId;
}
public void setParentId(Integer parentId) {
this.parentId = parentId;
}
}
大家可能已经注意到,我们这里并没有编写类和表的XML映射文件,而是在具体的实体类中用注解的方式说明它们的映射关系。所以我们才需要用到Hibernate的元数据注解包。下面是Spring框架的核心配置文件applicationContext.xml
<?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.annotation.AnnotationSessionFactoryBean">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
<!-- Hibernate 事务管理 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="baseTransactionProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<props>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="persist*">
PROPAGATION_REQUIRED,-Exception
</prop>
<prop key="remove*">
PROPAGATION_REQUIRED,-Exception
</prop>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="save">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="edit*">PROPAGATION_REQUIRED</prop>
<prop key="del*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="query*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="disPlay*">PROPAGATION_REQUIRES_NEW</prop>
</props>
</property>
</bean>
<!-- DAO Objects -->
<bean id="logonDAO" class="org.leno.hr.dao.LogonDAO"
lazy-init="true" singleton="true">
</bean>
<bean id="unitDAO" class="org.leno.hr.dao.UnitDAO" lazy-init="true"
singleton="true">
</bean>
<bean id="personDAO" class="org.leno.hr.dao.PersonDAO"
lazy-init="true" singleton="true">
</bean>
<!-- Service Objects -->
<bean id="logonService" parent="baseTransactionProxy">
<property name="target">
<bean class="org.leno.hr.service.LogonService">
<property name="logonDAO">
<bean class="org.leno.hr.dao.LogonDAO">
<property name="sessionFactory"
ref="sessionFactory" />
</bean>
</property>
</bean>
</property>
</bean>
<bean id="unitService" parent="baseTransactionProxy">
<property name="target">
<bean class="org.leno.hr.service.UnitService">
<property name="unitDAO">
<bean class="org.leno.hr.dao.UnitDAO">
<property name="sessionFactory"
ref="sessionFactory" />
</bean>
</property>
</bean>
</property>
</bean>
<bean id="personService" parent="baseTransactionProxy">
<property name="target">
<bean class="org.leno.hr.service.PersonService">
<property name="personDAO">
<bean class="org.leno.hr.dao.PersonDAO">
<property name="sessionFactory"
ref="sessionFactory" />
</bean>
</property>
</bean>
</property>
</bean>
<!-- 后端控制器 -->
<bean id="logonController"
class="org.leno.hr.controller.LogonController" lazy-init="true"
singleton="true">
<property name="logonService">
<ref bean="logonService" />
</property>
</bean>
<bean id="unitController"
class="org.leno.hr.controller.UnitController" lazy-init="true"
singleton="true">
<property name="unitService">
<ref bean="unitService" />
</property>
</bean>
<bean id="personController"
class="org.leno.hr.controller.PersonController" lazy-init="true"
singleton="true">
<property name="personService">
<ref bean="personService" />
</property>
</bean>
<!-- URL Mapping Configurations 路径映射器 -->
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!-- logon mapping -->
<prop key="/logon.hr">logonController</prop>
<prop key="/unit.hr">unitController</prop>
<prop key="/person.hr">personController</prop>
</props>
</property>
</bean>
<!-- 视图控制器 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass">
<value>org.springframework.web.servlet.view.JstlView</value>
</property>
<property name="prefix">
<value>/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="beanNameViewResolver"
class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order">
<value>1</value>
</property>
</bean>
</beans>
在这里,hibernate.cfg.xml和applicationContext.xml默认都要放在我们应用的/src目录下。在applicationContext.xml中,我们配置了很多bean以及它们的相互关联。如果大家对Spring的配置文件以及它的MVC运行流程不太熟悉,请参阅拙作:http://blog.csdn.net/lenotang/archive/2008/06/18/2562348.aspx ,里面有详细的介绍。下面是DWR框架的核心配置文件dwr.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://www.getahead.ltd.uk/dwr/dwr20.dtd">
<dwr>
<allow>
<!-- At here, you will find that i just use dwr technology in query and remove.-->
<convert converter="bean" match="org.leno.hr.Unit" />
<convert converter="bean" match="org.leno.hr.User" />
<convert converter="bean" match="org.leno.hr.Person" />
<create creator="spring" javascript="unitController">
<param name="beanName" value="unitController" />
<include method="getRecords" />
<include method="removeRecords" />
</create>
<create creator="spring" javascript="userController">
<param name="beanName" value="logonController" />
<include method="getRecords" />
<include method="removeRecords" />
</create>
<create creator="spring" javascript="personController">
<param name="beanName" value="personController" />
<include method="getRecords" />
<include method="removeRecords" />
</create>
</allow>
</dwr>
主要是<create>和<convert>两个节点大家要熟悉。通俗地讲,远程Bean会被created,参数会被converted。所以,前者是可以在客户端使用的js,后者是数据传递过程中作为参数的bean.