标签:
相信很多人都认同JavaWeb开发是遵从MVC开发模式的,遵从三层架构进行开发的,是的,大家都这么认同。但是相信大家都会有过这样一个疑问,if(MVC三层模式==三层架构思想)out.println(“请继续观看……”)
首先让我们了解下MVC(Model-View-Controller)的概念:
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,主要提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。主要使用的技术:数据模型:实体类(JavaBean),数据访问:JDBC,Hibernate等,
View(视图):负责进行模型的展示,一般就是我们见到的用户界面,比如JSP,Html等
Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。主要使用的技术:servlet,Struts中的Action类等。
MVC是一个框架模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。最典型的MVC就是JSP + servlet + javabean的模式。
三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:表现层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)。区分层次的目的即为了“高内聚低耦合”的思想。在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层、业务逻辑层(又或称为领域层)、表示层。
表现层(UI):通俗讲就是展现给用户的界面,用于显示数据和接收用户输入的数据,为用户提供一种交互式操作的界面。
业务逻辑层(BLL):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理。对于数据访问层而言,它是调用者;对于表示层而言,它却是被调用者。也将业务逻辑层称为领域层。
数据访问层(DAL):该层所做事务直接操作数据库,针对数据的增、删、改、查。如果要加入ORM的元素,那么就会包括对象和数据表之间的mapping,以及对象实体的持久化。也称为是持久层。数据访问层中包含实体层(Model 实体层)
JavaWeb中典型的三层架构是:Jsp+Struts/Spring+Hibernate的开发模式
MVC是一种设计模式,我们可以用它来创建在域对象和UI表示层对象之间的区分。它是根据项目的具体需求来决定是否适用于该项目。
三层架构是一个分层式的软件体系架构设计,它可适用于任何一个项目。
三层架构和MVC设计模式侧重点不一样,三层是一种笼统的架构思想,没有限制具体的设计;而MVC就比较具体的说明它的设计方法。我们从接手一个项目开始,首先,我们需要进行架构设计,一般我们采用的就是分层式的架构设计,即我们的三层架构。然后,在确定了架构以后,我们再根据项目的具体需求去考虑是否需要应用一些设计模式,比如是否应用我们的MVC模式,抽象工厂模式等等。
三层侧重的是整体的一个解耦,而MVC侧重的是web系统的解耦,即侧重jsp和Servlet的一个解耦。
三层架构将整个项目划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。
MVC :即Model(模型),View(视图),Controller(控制)。
下图可以说明他们的区别与联系:通过图中可以看到不是一一对应的关系:V是UI,C是BLL,M是DAL的观点是错误的。
在我们项目中选择了三层架构的基础上在根据具体需求决定是否需要使用MVC,于是我们常说的MVC中总是伴随着三层架构,也就造成了两者的容易混淆。其实,通过上图我们可以看到MVC将三成架构中的UI分成了控制层和试图层。将三层架构中的数据访问层和业务逻辑层整合成了模型层。
SSH多个框架(struts2+spring+hibernate)的集成,是目前较流行的一种企业及Web应用程序开源集成框架。
Struts2是流行和成熟的基于MVC设计模式的Web应用程序框架。 Struts2不只是Struts1下一个版本,它是一个完全重写的Struts架构。Struts对Model,View和Controller都提供了对应的组件。但是在ssh开发过程中主要用Struts作为三层架构中的表现层,也就是MVC中的View和Control层。
Struts2提供了表单提交参数封装成POJO类,提交参数的类型转换,输入校验,文件的上传下载,程序的国际化,Struts2标签,以及对AJAX的支持。
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,说的简单点:就是功能更加强大的JDBC。
Hibernate实现了对象到数据库端的封装。就是常说的ORM(Object Relation Mapping),它的出现使得编程更加的面向对象,在传统的编程上,我们要将对象存储到关系数据库中,需要写很多代码来实现,而且需要考虑跨数据库的平台的问题。有了Hibernate可以方便的实现从对象转换到关系数据库。这就是对象持久化。
主要包含两个重要功能:IOC和AOP,也就是常说的依赖注入和面向切面编程。当然还有Spring的事务功能,不过这一功能是在结合前面两者的功能实现的。
IOC:依赖注入(控制反转),是一种设计模式。一层含义是控制权的转移:由传统的在程序中控制依赖转移到由容器来控制;第二层是依赖注入:将相互依赖的对象分离,在spring配置文件中描述他们的依赖关系。他们的依赖关系只在使用的时候才建立。简单来说就是不需要NEW一个对象了。
AOP这是一种面向切面的编程思想,这种思想使得编程思想上得到了历史性的进步。它将程序的执行过程切割成不同的面,在面之间可以插入我们想执行的逻辑。
一进行javaWeb开发很多时候我们按照这样的层次进行划分:
1、在表示层中,首先通过JSP页面实现交互界面,负责传送请求(Request)和接收响应(Response),然后Struts根据配置文件(struts-config.xml)将ActionServlet接收到的Request委派给相应的Action处理,然后action进行对请求处理并转发给JSP页面。
2、在业务逻辑层中,管理服务组件的Spring IoC容器负责向Struts2提供具体的Action对象,提供业务模型(Model)组件和该组件的协作对象数据处理(DAO)组件完成业务逻辑,并提供事务处理、缓冲池等容器组件以提升系统性能和保证数据的完整性。
3、在数据访问层中,则依赖于Hibernate的对象化映射和数据库交互,处理DAO组件请求的数据,并返回处理结果,给业务逻辑层。
按照MVC模式时:Jsp对应着表现层,struts2对应控制层,Spring和Hibernate对应模型层。
分层不是绝对的,每个人的见解是不一样的,仅供参考;
从MVC说道ssh整合开发上就介绍到这里,下部分主要是对ssh框架的整合,会介绍怎么使用ssh取开发一个简单的web应用。
这章主要讲整合开发,直接从实战讲起
详细请看源代码注释:
全部代码下载(csdn):链接
Github链接:链接https://github.com/wpeace1212/javaBlog/tree/master/sshDemo
针对一个简单项目,让大家对三层机构和MVC有一个简单的认识,以及怎样整合ssh框架;
1.整合的项目介绍:
(1) 企业人事管理系统!要求对员工信息进行维护。
(2) 后台系统先登陆,才能操作员工: 添加/修改/删除
(3) 没有登陆,只能查看列表,不能操作!
2.功能分类:
(1) 管理员模块:对应AdminAction中实现
登陆/注册
(2) 员工模块:对应EmployeeAction中实现
添加一个员工, 指定添加的部门
对指定的员工信息修改
删除选择员工
列表展示
3.需要的技术:
(1) Struts2:对是否登陆的拦截,对各个功能请求的分别处理,模型驱动。
(2) Hibernate4:建立多对一关系的数据库,以及实现增删改查
表t_admin:存放管理员信息
表t_dept:存放部门信息,要用到one-to-many关联员工表
表t_employee:存放员工信息,要用到many-to-one关联部门表
(3) Spring:实现bean对象的创建管理,整合,事务管理
(4) 大体按照下面的流程进行介绍:设计数据库直接在实体存中实现
- Jar包引入
- entity层映射
- Spring配置
- hibernate配置
- Dao层
- Service层
- web.xml配置
- struts.xml配置
- Action层
- jsp层
三层架构:其中2,4,5步是数据访问层,3,6步是业务逻辑层,7,9,10步表现层
MVC:其中2,3,4,5,6步是模型层,7,9,步是控制层,10步是视图层
(5) 工程简图:
第一步当然是建立web项目、引入jar文件、准备环境了,建立就不介绍了,只介绍最小包的引入:
我的最小包下载地址(ssh最小包):http://download.csdn.net/detail/peace1213/9412092
1.Struts 2.3.16.1
下载地址:http://struts.apache.org/download
Struts中需要引入的包:struts-2.3.16.1/apps/struts2-blank/WEB-INF/lib:该lib下面的包都可以引入;
2.spring-framework-4.2.3.RELEASE-dist.zip
下载地址:http://repo.springsource.org/libs-release-local/org/springframework/spring/
需要引入的包:
3.Hibernate 4.1.6
下载地址:http://sourceforge.net/projects/hibernate/files/hibernate4
需要引入的包:
4.Aopalliance 1.0
该包在struts的lib中有
下载地址:http://sourceforge.net/projects/aopalliance
aopalliance.jar
5.Aspectj 1.7.0
下载地址:http://www.eclipse.org/aspectj/downloads.php
aspectjrt.jar
aspectjweaver.jar
6.Cglib 2.2.3
下载地址:http://sourceforge.net/projects/cglib/files
cglib-2.2.3.jar
7.Asm 3.3
该包在struts的lib中有
下载地址:http://forge.ow2.org/projects/asm
asm-3.3.jar
8.Log4j 1.2.17
该包在struts的lib中有
下载地址:http://logging.apache.org/log4j/1.2/download.html
log4j-1.2.17.jar
9.mysql-connector-java-5.1.37-bin.jar
下载地址:http://dev.mysql.com/downloads/connector/j
mysql-connector-java-5.1.37-bin.jar
10.Commons Logging 1.1.1
该包在struts的lib中有
下载地址:http://commons.apache.org/logging
commons-logging-1.1.1.jar
其他需要引入的jar:
1.需要建立三个实体类:Admin.java,Dept.java,Employee.java,如下:
此处都省略get和set方法:
public class Admin {
private int id;
private String adminName;
private String pwd;
......
public class Dept {
private int id;
private String name;
private Set<Employee> emps=new LinkedHashSet<>();
......
public class Employee {
private int id;
private String empName;
private double salary;
private Dept dept;
......
2.建立对应的映射文件:×.hbm.xml
1.Admin.hbm.xml:
<class name="Admin" table="t_admin">
<id name="id">
<generator class="native"></generator>
</id>
<property name="adminName" length="20"></property>
<property name="pwd" length="20"></property>
</class>
2.Dept.hbm.xml:
<class name="Dept" table="t_dept">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name" column="Dname"></property>
<set name="emps" cascade="save-update,delete" table="t_employee" >
<key column="dept_id"></key>
<one-to-many class="Employee"></one-to-many>
</set>
3.Employee.hbm.xml:
<class name="Employee" table="t_employee">
<id name="id">
<generator class="native"></generator>
</id>
<property name="empName" length="20"></property>
<property name="salary" type="double"></property>
<many-to-one name="dept" column="dept_id" class="Dept"></many-to-one>
</class>
Spring分为:bean-base.xml,bean-dao.xml,bean-service.xml,bean-action.xml,以及整合成一个的bean.xml
辞去暂时介绍bean-base.xml基础功能文件和bean.xml,其他文件到相应的介绍地方再进行介绍;
1.bean-base.xml:主要配置Hibernate的工厂sessionFactory和事务,连接池
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 1. 数据源对象: C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/day01?useUnicode=true&characterEncoding=UTF8"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
<property name="initialPoolSize" value="3"></property>
<property name="maxPoolSize" value="10"></property>
<property name="maxStatements" value="100"></property>
<property name="acquireIncrement" value="2"></property>
</bean>
<!-- ###########Spring与Hibernate整合 start########### -->
<!-- 【推荐】方式所有的配置全部都在Spring配置文件中完成 -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- 注入连接池对象 -->
<property name="dataSource" ref="dataSource"></property>
<!-- Hibernate常用配置 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<!-- hibernate映射配置-->
<property name="mappingLocations">
<list>
<value>classpath:com/rlovep/entity/*.hbm.xml</value>
</list>
</property>
</bean>
<!-- ###########Spring与Hibernate整合 end########### -->
<!-- 事务配置 -->
<!-- a. 配置事务管理器类 -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- b. 配置事务增强(拦截到方法后如果管理事务?) -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" read-only="false"/>
</tx:attributes>
</tx:advice>
<!-- c. Aop配置 -->
<aop:config>
<aop:pointcut expression="execution(* com.rlovep.service.impl.*.*(..))" id="pt"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
<!-- 用于建表 -->
<bean id="appDao" class="com.rlovep.entity.AppDao">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
</beans>
2.bean.xml:
....省略.....
<!-- 引入其他配置文件 -->
<import resource="config/bean-base.xml"/>
<import resource="config/bean-dao.xml"/>
<import resource="config/bean-service.xml"/>
<import resource="config/bean-action.xml"/>
</beans>
Spring中已经配置好了Hibernate,此处主要讲解建立数据库中的三个表;
1、建立AppDao类文件:bean已经在bean.hbm.xml中配置了
/*
* 用来创建数据库中的表
*/
public class AppDao {
//工厂通过spring注入
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
//@Test
public void test(){
//sessionFactory=(SessionFactory)ac.getBean("sessionFactory");
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
//保存管理员,并创建表
Admin admin=new Admin();
admin.setAdminName("admin");
admin.setPwd("123456");
session.save(admin);
//保存部门和雇员,并创建表
Dept dept1=new Dept();
Dept dept2=new Dept();
....省略.....
//持久化
session.save(dept1);
....省略.....
session.save(employee4);
tx.commit();
session.close();
}
2.建立类App类创建数据库和存数据:
public class App {
private ApplicationContext ac=new ClassPathXmlApplicationContext("config/bean-base.xml");
@Test
public void test(){
//ac.getBean("deptDao");
AppDao appDao = (AppDao)ac.getBean("appDao");
appDao.test();
}
}
3.点击运行App的test方法就可以完成数据库的创建;
1.先建立接口: IAdminDao,IDepDao,IEmployee,IBaseDao(所有Dao的通用操作接口定义)
此处只贴出IBaseDao接口的定义:
/*
* * 所有dao的通用操作接口定义
*/
public interface IBaseDao<T> {
/**
* 保存
* @param obj
*/
void save(T obj);
....省略.....
}
2.接口的实现:AdminDao,DepDao,Employee,BaseDao(所有Dao的通用操作,希望所有的dao都继承此类)
BaseDao实现:
/*
* 所有dao的通用操作,希望所有的dao都继承此类
*/
public class BaseDao<T> implements IBaseDao<T>{
//当前操作实际的bean类型
private Class<T>clazz;
//获取类名称
private String className;
// IOC容器(依赖)注入SessionFactory对象
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public BaseDao() {
Type type=this.getClass().getGenericSuperclass();
//转换为参数化类型
ParameterizedType pt=(ParameterizedType)type;// BaseDao<Employee>
//得到实际类型
Type types[]=pt.getActualTypeArguments();
//获取实际类型
clazz=(Class<T>)types[0];
className = clazz.getSimpleName();//例如:Employee
}
....省略.....
@Override
public List<T> getAll() {
Query query = sessionFactory.getCurrentSession().createQuery("from "+className);
List<T> list = query.list();
return list;
}
}
其他接口实现:
//只需要继承通用操作,和特点接口就行:这里接口中没有方法,可以加方法
public class DeptDao extends BaseDao<Dept> implements IDepDao{
}
同样先建立接口再建立类,此处不贴出代码,介绍bean-dao.xml,bean-service.xml的建立,以及对刚刚建立的Dao和service进行测试
1.bean-dao.xml
<!-- dao实例 -->
<bean id="adminDao" class="com.rlovep.dao.impl.AdminDao">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="deptDao" class="com.rlovep.dao.impl.DeptDao">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="employeeDao" class="com.rlovep.dao.impl.EmployeeDao">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
2.bean-service.xml
<!-- service 实例 -->
<bean id="adminService" class="com.rlovep.service.impl.AdminService">
<property name="adminDao" ref="adminDao"></property>
</bean>
<bean id="deptService" class="com.rlovep.service.impl.DeptService">
<property name="deptDao" ref="deptDao"></property>
</bean>
<bean id="employeeService" class="com.rlovep.service.impl.EmployeeService">
<property name="employeeDao" ref="employeeDao"></property>
</bean>
3.测试刚刚建立的dao和service:
在包service中建立App测试类:public class App {
//加载spring的配置文件
private ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
//测试Admin的操作
@Test
public void testAdmin(){
//获得bean
IAdminService adminService=(IAdminService)ac.getBean("adminService");
Admin admin=new Admin();
admin.setAdminName("admin");
admin.setPwd("123456");
System.out.println( adminService.login(admin));
}
//测试Dept的操作
@Test
public void testDept(){
IDeptService service=( IDeptService)ac.getBean("deptService");
System.out.println( service.findById(1));
}
//测试Employee的操作
@Test
public void testEmployee(){
IEmployeeService service=( IEmployeeService)ac.getBean("employeeService");
List<Employee> list = service.getAll();
System.out.println( service.findById(9));
}
}
1、需要配置Spring
2、需要配置Struts2
3、配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>sshDemo</display-name>
<!-- 配置spring的OpenSessionInView模式 【目的:JSp页面访问懒加载数据】 -->
<!-- 注意:访问struts时候需要带上*.action后缀 -->
<filter>
<filter-name>OpenSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInView</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<!-- Struts2的配置 -->
<filter>
<!-- 配置过滤器的名字 -->
<filter-name>struts2</filter-name>
<!-- 配置核心过滤器类 -->
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<!--配置要拦截的URL,辞去配置全部拦截 -->
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--在web.xml中加入如下代码令服务器自动加载Spring -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:bean.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 首页配置 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
1.由于spring的整合,在 struts.xml配置文件中的class属性直接使用:spring的配置文件bean-action.xml中定义的bean
2.struts.xml文件:
<package name="struts2" extends="struts-default">
<!-- 配置action,class属性使用Spring中定义的bean->
<action name="admin_*" class="adminAction" method="{1}">
<!-- 登陆失败 -->
<result name="loginFaild">/login.jsp</result>
<!-- 登陆成功 -->
<result name="index" type="redirectAction">emp_list</result>
</action>
<action name="emp_*" class="employeeAction" method="{1}">
<!-- 列表展示 -->
<result name="list">/WEB-INF/list.jsp</result>
<!-- 进入添加页面视图 -->
<result name="add">/WEB-INF/add.jsp</result>
<!-- 添加成功,进入列表 (防止刷新就多一条记录问题,所以用重定向) -->
<result name="listAction" type="redirectAction">emp_list</result>
<!-- 进入修改页面 -->
<result name="edit">/WEB-INF/edit.jsp</result>
</action>
3.bean-action.xml文件:
<!-- 指定action多例 -->
<bean id="adminAction" class="com.rlovep.action.AdminAction" scope="prototype">
<property name="adminService" ref="adminService"></property>
</bean>
<bean id="employeeAction" class="com.rlovep.action.EmployeeAction" scope="prototype">
<property name="deptService" ref="deptService"></property>
<property name="employeeService" ref="employeeService"></property>
</bean>
1、建立AdminAction文件:继承ActionSupport类,和实现ModelDriver接口
2、建立EmployeeAction文件:继承ActionSupport类,和实现ModelDriver接口
3、建立拦截器类:AdminInterceptor类用于判断是否登陆;继承AbstractInterceptor
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//得到当前执行的方法
String method = invocation.getProxy().getMethod();
//判断:当不为登陆方法和list方法时
if(!"login".equals(method)&&!"list".equals(method)){
Object obj= ActionContext.getContext().getSession().get("adminInfo");
if(obj==null){
//没有登陆
return "login";
}else{
//放行
return invocation.invoke();
}
}
//放行
return invocation.invoke();
}
建立相应的jsp文件:
主要有:index,login,edit,add,list等jsp文件;详情见工程源代码;
测试登陆
测试添加
测试删除
测试修改
好的本章介绍到这里
标签:
原文地址:http://www.cnblogs.com/knitmesh/p/5439918.html