`

在实际项目开发中的六层划分

阅读更多

      在实际项目的开发过程中,常常为了减弱类之间的耦合性,同时便于项目的维护和复用,往往要分层进行编写代码。自己在实际的项目中发现,一般的项目分的很细的话,会分这样的五层:

      VIEW层:表面展现层,该层是直接面向用户的,即展现层。

      Control层:控制层,控制跳转的

      VO层:值对象,有人也叫模型层,主要是和数据库中表相对应的,字段可少可多。

      QO层:查询对象,当涉及到页面的查询比较多的时候可以将每个查询条件封装起来,作为一层。

      BO层:业务层,处理具体的业务。

      DAO层:数据访问层,该层直接和数据库打交道,用于数据库的增、删、改、查。

      有句话描述的这个项目层次的关系很生动、也很形象。当然表面层我用struts来代替的,语言描述如下:

      数据流向描述:

      FORM,QO和VO只是用来运输数据,FORM就像是大卡车,QO就是放查询条件的包裹,VO是放业务数据的包裹,FORM拉着这两个包裹在VIEW和ACTION中间跑。在VIEW中把查询条件包到QO中,FORM拉上这个QO,把它给了ACTIION,ACTION将QO给BO,BO用这个QO通过DAO向数据库取数,取到的数包到VO中,由BO再给ACTION,FROM再从ACTION中把这个VO包拉给跳转过去的VIEW,VIEW把VO包中数据显示出来。

     下面关于一个简单六层的测试例子来分析详细分析:

      该例子是从页面输入查询条件,点击提交,最后在另一页面显示查询结果的例子:

将一个小小的工程分成六层来完成这个查询:

1、view的查询页面:

   查询页面

<%@ page contentType="text/html;charset=GBK"%>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>
<html>
  <head> 
    <title>WELCOME</title>
  </head>
  
  <body>
    <html:form action="/testAction.do">
      <table>
        <tr>
          <td>First Name:</td>
          <td><html:text name="testForm" property="firstName" /></td>
        </tr>        
        <tr>
          <td>Last Name:</td>
          <td><html:text name="testForm" property="lastName" /></td>        
        </tr>
        <tr>
          <td><html:submit value="submit" /></td>
        </tr>
      </table>
    </html:form>
  </body>
</html>

结果显示页面:

<%@ page contentType="text/html;charset=GBK"%>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>
<html>
	<head>
		<title>TEST</title>
	</head>

	<body>
		<html:form action="/testAction.do">
			<table border="1">
				<tr>
					<td>
						First Name:
					</td>
					<td>
						<bean:write name="testForm" property="firstName" />
					</td>
				</tr>
				<tr>
					<td>
						Last Name:
					</td>
					<td>
						<bean:write name="testForm" property="lastName" />
					</td>
				</tr>
				<!-- 用标签显示那两个VO -->
				<!-- 先判断一下form里的VO List 是否是空,要不是空再显示 -->
				<logic:notEmpty name="testForm" property="testVOList">
					<tr>
						<td>
							company
						</td>
						<td>
							department
						</td>
					</tr>
					<!-- 遍历VO List -->
					<logic:iterate name="testForm" property="testVOList" id="testVO">
						<tr>
							<td>
								<bean:write name="testVO" property="company" />
							</td>
							<td>
								<bean:write name="testVO" property="department" />
							</td>
						</tr>
					</logic:iterate>
				</logic:notEmpty>
				<tr>
			</table>
		</html:form>
	</body>
</html>

 

 2、action中的两个类(本例子用了struts)

public class TestAction extends Action {
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {

		// 取出页面传回来的form
		TestForm testForm = (TestForm) form;

		// 从form中取查询对象QO
		TestQO testQO = testForm.getTestQO();

		// 用BO处理业务
		TestBO testBO = new TestBO();
		List testVOList = testBO.doBusiness(testQO);

		// 将处理后的VO List放回form中,用于页面显示
		testForm.setTestVOList(testVOList);

		// 跳转页面
		ActionForward forward = mapping.findForward("success");
		return forward;
	}
}

 

public class TestForm extends ActionForm {
	private String firstName;
	private String lastName;
	private TestQO testQO; // 这个是你的QO,要有get和set方法
	private TestVO testVO; // 这个是你的VO,要有get和set方法
	// 一般来说,返回到页面的值对象VO不是一个,因为从数据库查出的是多条记录
	// 这就要把它分放到一个List中
	private List testVOList;
	
	public void reset(ActionMapping mapping ,HttpServletRequest request){
		super.reset(mapping, request);
		testQO = new TestQO();
		testVO = new TestVO();
	}

	public TestVO getTestVO() {
		return testVO;
	}

	public void setTestVO(TestVO testVO) {
		this.testVO = testVO;
	}

	public TestQO getTestQO() {
		return testQO;
	}

	public void setTestQO(TestQO testQO) {
		this.testQO = testQO;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public List getTestVOList() {
		return testVOList;
	}

	public void setTestVOList(List testVOList) {
		this.testVOList = testVOList;
	}
}

 3、QO层

/**
 * @author:gaojie
 * @作用:查询对象,该对象封装了页面的查询条件,可以封装好多的条件在里面, 
 * @ 本例中只封裝了两个查询字段firstName和lastName。
 */
public class TestQO {

	// 每个查询条件对应这里的一个字段,记得写相应的get和set方法
	private String firstName;// 第一个查询条件
	private String lastName;// 第二个查询条件
	
	/**
	 * 获取第一查询条件
	 * @return
	 */
	public String getFirstName() {
		return firstName;
	}
	/**
	 * 设置第一查询条件
	 * @param firstName
	 */
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	/**
	 * 获取第二查询条件
	 * @return
	 */
	public String getLastName() {
		return lastName;
	}
	/**
	 * 设置第二查询条件
	 * @param lastName
	 */
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

}

 4、vo层

/**
 * @author gaojie
 * @作用:值对象,与数据库中的表是基本对应的,其包含的结构字段应小于等于数据库中的表。
 * 
 */
public class TestVO {
	
	private String firstName;  //第一个名字
	private String lastName;   //最后的名字
	private String department; //部门字段
	private String company;    //公司名称
	
	/**
	 * 获取第一个名字
	 * @return
	 */
	public String getFirstName() {
		return firstName;
	}
	/**
	 * 设置第一个名字
	 * @param firstName
	 */
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	/**
	 * 获取最后的名字
	 * @return
	 */
	public String getLastName() {
		return lastName;
	}
	/**
	 * 设置最后的名字
	 * @param lastName
	 */
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}	
	/**
	 * 返回部门名称
	 * @return
	 */
	public String getDepartment() {
		return department;
	}
	/**
	 * 设置部门名称
	 * @param department
	 */
	public void setDepartment(String department) {
		this.department = department;
	}
	/**
	 * 返回公司名称
	 * @return
	 */
	public String getCompany() {
		return company;
	}
	/**
	 * 设置公司名称
	 * @param company
	 */
	public void setCompany(String company) {
		this.company = company;
	}
}

 5、BO层

/**
 * 
 * @功能:该方法调用DAO的方法,,处理相关的业务。
 * @创建人 gao_jie
 * @创建日期 Jun 14, 2009
 * @版本 1.0
 * 
 */
public class TestBO {
	public List doBusiness(TestQO testQO) {
		// 好的方法应该用工厂模式和单例模式来生成DAO,这里采用的是单利模式
		ItestDAO Itest = null;
		try {
			Itest = TestDAO.getInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 用DAO从数据库中取到数据或写入数据
		// 这个例子只是取数据了,返回那个放了两个VO的List
		List conditonglist = Itest.getConditionList(testQO);

		// 按相应的业务逻辑处理这些数据,也可以把处理后的数据放在另一个容器中返回
		// 返回处理后的数据,用来在页面中显示等。
		// 这里没作处理,只是简单返回了查询得到的数据
		return conditonglist;
	}
}

 6DAO层

接口

/**
 * 
 * @功能 数据库操作的接口    
 * @创建人   gao_jie
 * @创建日期 Jun 14, 2009
 * @版本     1.0
 * 
 */
public interface ItestDAO {
	
	/**
	 * 获取查询的列表
	 * @param testQO
	 * @return
	 */
	public List getConditionList(TestQO testQO); 
}

 实现层

/**
 * @作者:gaojie
 * @作用:该类是DAO层,用来连接数据库,并执行查询、更新、插入、删除等操作数据库的操作, 如数据库中的SQL等。该类一般来说只是和数据库进行数据交互,不处理具体的业务,处理业务
 *                                              部分放到BO层中。该类在设计过程中常用的模式是工厂模式或单例模式,这里为了方便不做设计
 *                                              模式的定义。在该类的实际项目中会根据查询对象TestQO获取的值,拼装SQL语言,然后从数据
 *                                              库中获取数据存放到值对象中。
 */
public class TestDAO implements ItestDAO{
	private static ItestDAO dataSourceImpl = null;

	/**
	 * 单利模式
	 * @return
	 * @throws Exception
	 */
	public static ItestDAO getInstance() throws Exception {
		if (dataSourceImpl == null)
			dataSourceImpl = new TestDAO();
		return (TestDAO) dataSourceImpl;
	}
	/**
	 * *该方法的通过QO查询条件动态生成SQL语句,连接数据库进行查询数据 
	 * *本例子为了方便采用了XML文件做为数据库,所以在内容上简化了组装SQL的步骤
	 * 
	 * @param testQO
	 * @return
	 */
	public List getConditionList(TestQO testQO) {

		// 声明一个List来存放你从数据库里查出来的数据
		List<TestVO> conditionList = Collections
				.synchronizedList(new ArrayList<TestVO>());

		// 这里连接数据库,执行这条SQL,然后将返回值放到上面声明的xxxList中
		// 数据库中的一条记录就对应一个VO,xxxList中放的就是多个VO(就是多条数据库中的记录)
		try {
			Document document = loadXML(getDatasource());
			Element root = document.getRootElement();
			TestVO testVo = null;
			for (Object element : root.elements("persons")) {
				testVo = getTestVOFromElement((Element) element);
				if (testVo.getFirstName().equals(testQO.getFirstName())
						&& testVo.getLastName().equals(testQO.getLastName())) {
					conditionList.add(testVo);
				}
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return conditionList;
	}

	/**
	 * 获取文件路径
	 * 
	 * @return
	 */
	private String getWebPath() {
		String path = "";
		URL url = TestDAO.class.getClassLoader().getResource("");
		path = url.toString().substring(5, (url.toString().indexOf("WEB-INF")));
		return path;
	}

	/**
	 * 加载XML文件
	 * 
	 * @param xmlfile
	 * @return
	 * @throws FileNotFoundException
	 * @throws DocumentException
	 * @throws org.dom4j.DocumentException
	 */
	@SuppressWarnings("unused")
	private Document loadXML(String xmlfile) throws FileNotFoundException,
			DocumentException, org.dom4j.DocumentException {
		SAXReader reader = new SAXReader();
		Document doc = reader.read(new FileInputStream(xmlfile));
		return doc;
	}

	/**
	 * 向XML中写入
	 * 
	 * @param doc
	 * @param filePath
	 * @param encoding
	 */
	private static void writeToFile(Document doc, String xmlfile) {
		XMLWriter writer = null;
		try {
			OutputFormat format = OutputFormat.createPrettyPrint();
			format.setEncoding("UTF-8");
			writer = new XMLWriter(new FileOutputStream(xmlfile), format);
			writer.write(doc);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (writer != null) {
				try {
					writer.flush();
					writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 
	 * 获取TestVo对象
	 * 
	 * @param element
	 * @return
	 */
	@SuppressWarnings("unused")
	private TestVO getTestVOFromElement(Element element) {
		TestVO testVo = new TestVO();
		testVo.setFirstName(getAttributeValue(element, "firstName"));
		testVo.setLastName(getAttributeValue(element, "lastName"));
		testVo.setDepartment(getAttributeValue(element, "department"));
		testVo.setCompany(getAttributeValue(element, "company"));
		return testVo;
	}

	/**
	 * 获取属性元素的值
	 * 
	 * @param element
	 * @param attribute
	 * @return
	 */
	private String getAttributeValue(Element element, String attribute) {
		return element.attributeValue(attribute);
	}

	/**
	 * 获取数据源的操作
	 * @return
	 */
	@SuppressWarnings("unused")
	private String getDatasource() {
		return getWebPath() + "testdatasource.xml";
	}
}

struts的配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">

<struts-config>
	<data-sources />
	<form-beans>
		<form-bean name="testForm" type="test.action.TestForm" />
	</form-beans>
	<global-exceptions />
	<global-forwards />
	<action-mappings>
		<action name="testForm" path="/testAction" scope="request"
			type="test.action.TestAction">
			<forward name="success" path="/test.jsp" />
		</action>
	</action-mappings>
	<message-resources parameter="test.ApplicationResources" />
</struts-config>

 

总结:这个简单的例子通过一个查询页面提交,到后台经过层层的处理,最终把数据查询结果展现在用户面前,该例子的结构体现了在项目开发中的详细分层。本例子的数据库采用的是xml文件。

下面一些词语解释:

一、PO:persistant object 持久对象,可以看成是与数据库中的表相映射的java对象。最简单的PO就是对应数据库中某个表中的一条记录,多个记录可以用PO的集合。PO中应该不包含任何对数据库的操作。
二、VO:value object值对象。通常用于业务层之间的数据传递,和PO一样也是仅仅包含数据而已。但应是抽象出的业务对象,可以和表对应,也可以不,这根据业务的需要.个人觉得同DTO(数据传输对象),在web上传递。

三、DAO:data access object 数据访问对象,此对象用于访问数据库。通常和PO结合使用,DAO中包含了各种数据库的操作方法。通过它的方法,结合PO对数据库进行相关的操作。

四、BO:business object 业务对象,封装业务逻辑的java对象,通过调用DAO方法,结合PO,VO进行业务操作。

五、POJO:plain ordinary java object 简单无规则java对象,我个人觉得它和其他不是一个层面上的东西,VO和PO应该都属于它。

  • 大小: 37.8 KB
1
1
分享到:
评论

相关推荐

    采用六层架构+抽象工厂设计模式+反射机制搭建CRM项目框架

    在IT行业中,构建高效、可扩展的软件系统是至关重要的,而"采用六层架构+抽象工厂设计模式+反射机制搭建CRM项目框架"正是这样的一个技术实践。这种框架设计能够帮助开发者实现模块化的代码结构,增强系统的灵活性...

    六层架构抽象工厂简单应用

    通过以上介绍,我们可以看出六层架构和抽象工厂设计模式在实际项目中的应用,有助于理解如何组织和构建大型C#应用程序。这样的设计思路不仅提高了代码的可读性和可维护性,还使得系统更容易适应未来的需求变化。

    Java Web项目整合开发源码

    实战突击部分可能涵盖了从项目初始化、环境配置、模块划分、数据库设计、控制器编写、服务实现、视图展示、异常处理、安全策略到项目部署的全过程,旨在通过实际操作加深对Java Web开发的理解。 通过对上述知识点的...

    Python项目高手训练营 Python大数据+教育行业项目实战开发 Python高级项目剖析

    - **项目概述**:本课程旨在培养学员通过Python语言进行大数据处理及应用开发的能力,特别聚焦于教育行业的实际应用场景。 - **教育项目背景**:详细介绍了教育行业的现状和发展趋势,以及在该领域中运用Python进行...

    软件项目开发规范文档

    - **参考资料**:文档中未列出,实际应用时需根据项目具体情况添加必要的参考文献或资料。 #### 四、项目开发流程规范详解 ##### 1. 业务需求调研阶段 - **目标**:深入了解客户需求及其业务背景,为后续的设计和...

    MVC架构在工程项目管理系统中的应用

    在工程项目管理系统中,MVC模式的应用使得开发人员可以更清晰地划分职责,提高开发效率。例如,模型层可以专注于业务逻辑处理和数据存储,视图层则专注于用户界面的展示,而控制器层则处理用户输入并协调模型和视图...

    《电子商务综合业务实训》实训项目开发验收汇报.pptx

    《电子商务综合业务实训》实训项目开发验收汇报主要关注的是电子商务专业学生的实践教学环节,旨在通过一系列的实训活动,提升学生的专业技能和实际操作能力。以下是对这个实训项目的详细说明: 一、实训项目开发...

    学院网站建设项目的工作分解结构

    - 项目计划:在项目启动阶段制定详细的项目开发计划,包括时间表、预算和资源分配等。 - 规章制度:制定项目实施过程中所需遵循的各项规章制度。 ##### 2. 需求确定(1200) 需求确定阶段是项目成功的关键。在这个...

    OA系统开发步骤项目文档

    2. **分层结构**:对系统进行层次划分,比如分为界面层、业务逻辑层、数据访问层等,每一层负责特定的功能。 3. **编写用例文档**:详细描述每一个用例的具体实现过程,包括前置条件、执行步骤、预期结果等。 4. **...

    项目管理模拟题

    - **B选项**:识别干系人的需求并在项目规划和执行过程中满足这些需求非常重要,但“尽量超过”这些需求可能不是最佳做法。 - **C选项**:应用各种技术规范、计划、方法及其他系统是提高组织经营效率的方式之一,...

    人力资源管理系统(需求技术项目开发文档)

    在本文档中,我们将深入探讨系统的核心功能、技术选型、开发流程以及项目管理策略,旨在为企业的信息化建设提供清晰的指导。 一、系统概述 人力资源管理系统(HRMS)是企业用来自动化和优化人力资源管理流程的关键...

    5143.67平米,六层框架办公楼(含计算书、建筑、结构图).zip

    该压缩包文件“5143.67平米,六层框架办公楼(含计算书、建筑、结构图).zip”包含了一座六层办公楼的完整设计资料,涵盖了建筑设计、结构设计以及相关的计算书。这样的文件集合对于建筑师、结构工程师、施工团队...

    Python3项目开发AI智能联系人管理的程序

    传统的联系人管理方式已经无法满足当前的需求,因此开发一个集成了AI技术的智能联系人管理系统具有重要的实际应用价值。该系统能够帮助用户更有效地管理大量的联系人信息,并通过智能分析提供个性化的服务。 #### ...

    软件开发过程与质量保证项目管理PPT学习教案.pptx

    项目计划中包含的内容包括项目划分的各个实施阶段、每个阶段的工作重点和任务是什么、完成本阶段工作和任务的人力、资源需求、时间期限、阶段工作和任务的成果形式、项目实施过程中对风险、疑难、其他不可预见因素等...

    【楼层6层】6000平米六层框架住宅楼(计算书、建筑、结构图)-土木工程建造设计.zip

    该压缩包文件“【楼层6层】6000平米六层框架住宅楼(计算书、建筑、结构图)-土木工程建造设计.zip”包含了土木工程领域中的关键设计资料,特别是针对六层住宅楼的建造设计。这个住宅楼的总面积为6000平方米,设计内容...

    基于PHP面向对象的自定义MVC框架高级项目开发12天视频

    在现代Web开发中,MVC(Model-View-Controller)架构模式因其清晰的结构划分与高度的可维护性而被广泛采用。本系列视频教程旨在通过12天的学习与实践,帮助开发者掌握如何使用PHP语言构建一个面向对象的自定义MVC...

    在.NET框架下开发三层结构数据库应用系统 DB

    在.NET框架下开发三层结构数据库应用系统是一种常见的软件架构模式,它将应用程序分解为三个主要层次:表现层(Presentation Layer)、业务逻辑层(Business Logic Layer)和数据访问层(Data Access Layer)。...

    电信领域—敏捷软件开发思想

    2. **启动前的准备**:在项目启动之前,团队成员需要通过研讨会等形式加深对敏捷开发的理解,并就开发流程达成共识。此外,还需要建立持续集成环境,确保软件的质量。 3. **敏捷教练的作用**:敏捷教练对于项目的...

    新产品开发流程和研发项目管理归类.pdf

    新产品开发流程和研发项目管理是科技型企业成功的关键因素,它们涉及到如何有效协调市场压力、客户需求、内部组织结构以及资源配置等多个方面。以下是对这些关键知识点的详细解析: 首先,企业需要在市场竞争和客户...

Global site tag (gtag.js) - Google Analytics