基于ssh的任务调度系统设计与实现(项目报告+答辩PPT+源代码+数据库+截图+部署视频)

项目报告

基于SSH的任务调度系统的设计与实现

随着科学技术的飞速发展和各行各业的分工愈发明细化,对于改革传统的人工任务调度方式的呼声越来越大。得益于快速发展的计算机技术,我们看到了改革的方向。本系统是针对企业或者事业单位甚至一个小团队的任务调度而设计的,目的是改变传统的调度方式,通过计算机来计算各项任务的最佳人员分配和最佳时间分配,绘制出任务调度图,以此更好地进行各项任务的调度和团队协作,该系统是一种任务调度系统。

本系统采用了B/S体系结构,主要实现语言是JAVA,后台数据库使用的是MySql。整个系统实现角色将分为组长和组员,实现功能包括帐号注册、修改信息、项目管理、任务管理、消息管理、团队管理等功能。本任务调度系统的设计实现可以远程实现任务的调度与科学分配,并通过评估各项任务与参与人员,来使项目更好的进行任务调度。

关键词: 任务调度;B/S;SSH

 

目  录

摘 要................................................................................................................................ I

Abstract........................................................................................................................... II

目  录........................................................................................................................... III

1  引言............................................................................................................................ 1

1.1  课题研究意义及背景......................................................................................... 1

1.2  论文的目的及设计要求..................................................................................... 1

2  研究现状及设计目标................................................................................................... 2

2.1  任务调度系统的现状......................................................................................... 2

2.2  任务调度系统优缺点分析.................................................................................. 2

2.3现行研究存在的问题及解决方法.......................................................................... 2

2.3.1  现行研究存在的问题.............................................................................. 2

2.3.2  解决办法................................................................................................ 3

2.4  本课题要达到的设计目标.................................................................................. 3

2.5  经济效益分析................................................................................................... 4

3  关键问题及分析.......................................................................................................... 5

3.1  问题分析与设计................................................................................................ 5

3.1.1  核心问题即任务调度.............................................................................. 5

3.1.2  数据表间联系......................................................................................... 6

3.1.3  系统安全性............................................................................................ 6

4  调度算法设计.............................................................................................................. 7

5  需求分析..................................................................................................................... 8

5.1  USE-CASE用例图............................................................................................... 8

5.2  类图................................................................................................................. 8

5.3  活动图.............................................................................................................. 9

5.4  功能需求........................................................................................................ 10

5.5  开发环境........................................................................................................ 10

5.6  系统交互图..................................................................................................... 11

5.6.1  系统架构类交互图................................................................................ 11

5.6.2  系统协作图.......................................................................................... 12

5.6.3  系统状态图.......................................................................................... 13

6  系统设计................................................................................................................... 15

6.1  系统体系结构................................................................................................. 15

6.2  系统功能结构................................................................................................. 15

6.3  系统架构的设计目标....................................................................................... 16

6.4  系统架构设计................................................................................................. 16

6.5  数据库表结构................................................................................................. 17

6.5.1  数据库设计原则................................................................................... 17

6.5.2  数据库设计概述................................................................................... 18

6.5.3  数据库设计周期................................................................................... 18

6.5.4  数据字典.............................................................................................. 19

7  系统实现................................................................................................................... 21

7.1  公共模块........................................................................................................ 21

7.1.1  模块功能.............................................................................................. 21

7.1.2  模块代码.............................................................................................. 21

7.2  注册模块........................................................................................................ 26

7.2.1  模块功能.............................................................................................. 26

7.2.2  模块代码.............................................................................................. 26

7.3  登录模块........................................................................................................ 29

7.3.1  模块功能.............................................................................................. 29

7.3.2  模块代码.............................................................................................. 29

7.4  搜索模块........................................................................................................ 31

7.4.1  模块功能.............................................................................................. 31

7.4.2  模块代码.............................................................................................. 31

7.5  项目管理模块................................................................................................. 33

7.5.1  模块功能.............................................................................................. 33

7.5.2  模块代码.............................................................................................. 33

7.6  任务调度模块................................................................................................. 40

7.6.1  模块功能.............................................................................................. 40

7.6.2  模块代码.............................................................................................. 40

8  结论与展望............................................................................................................... 49

参考文献........................................................................................................................ 50

致  谢........................................................................................................................... 51

引言

在实际生产生活中,许多项目是由多个任务组成的,并且这多个任务存在约束关系,有一类约束关系为树状的约束关系,小至产品,大至广场的修建。如产品由工件装配而成,而工件又由一系列精加工任务组成,再如广场由各类功能区组成,而各类功能区又由一系列建造流程租出。所以任务调度是各行各业都离不开的,在以前这些工作都由人力完成,或者采用低效的任务调度策略。到了现在,各行各业都在运用计算机进行复杂计算或自动化处理事务,计算机能够进行快速复杂计算,可以实现远程办公,团队协作,并有将数据可视化的能力。使用计算机并且加上高效的调度策略,不仅能提高工作效率,还能进行更科学更客观的分配。

计算越复杂,计算机的优越性体现的越明显。在多任务的项目中,计算机可通过各类算法,如关键路径算法或多机调度算法,来进行任务评估和总体任务调度,计算机与人们的生产生活密切相关,故现在开发任务调度系统。本系统运用了当前的流行框架Spring,Struts2,Hibernate,保证了可扩展性与可维护性。

1.1  课题研究意义及背景

虽然科技进步在改革开发这几十年来速度飞快,计算机行业也发展迅速,但仍然有大量商家或企业,甚至项目组,采用落后的人工管理方式或者低效的任务调度策略,这无疑是对计算机的一种无视。

计算机处理信息的准确度与高效率远远超过人类,在团队协作中项目又可以被分成一个个小任务。故此,本人开发这套基于SSH的任务调度系统,使团队协作与任务分派更加科学高效,进而促进企业经济效益的提高。

1.2  论文的目的及设计要求

任务调度系统主要目的是对企事业单位项目的任务集进行调度分配,敏捷高效地处理任何或大或小的项目。使项目小组的工作效率大大提高,工作成本大大降低。本系统开发主要包括调度算法的设计,后台程序的处理,后台数据库的建立和维护,和前端页面的展示开发。算法要求高效性和可实现性,后台要求业务逻辑的合理性与科学性,数据库要求数据的完整性和一致性,前台页面又要求美观性与功能完备性。正因为此,本人选择采用SSH三大框架的整合技术和MySQL数据库进行系统的开发。

本系统的实现角色将包括项目组长和项目组员这两个角色,用户可同时扮演两种角色,共有的功能包括修改登录密码、发起项目、删除项目、参与项目、添加任务、删除任务、添加成员、删除成员、处理消息。其中组长部分的功能还包括组员管理、更新项目,其中组员部分的功能还包括申请加入与申请退出。并且,不光保证实现这些功能,还得为本任务调度系统提供一个良好的人机交互,提高系统友好性。

研究现状及设计目标

2.1  任务调度系统的现状

长久以来一般的大小项目组均采用传统的人工方式或者低效的调度算法来负责项目任务集合的日常管理工作,在以前,也就是计算机尚未普及前,基于树状任务集的项目的管理方式是人工管理,这样的缺点是显而易见的,效率低下并且错误率高。如果我们应用计算机来代替落后的人工管理方式,无疑会极大程度地提高效率和准确率,使我们更加精准的管理项目。

目前存在的调度算法多以时间轮转为主,虽然保证了项目树状结构的横向,但忽略了纵向。针对这个问题,本文提出了更优秀的调度算法。

2.2  任务调度系统优缺点分析

1.优点

(1) 采用可扩展性强、分离度高的B/S模式。

(2) 数据库选用了市场上应用广泛的关系型数据库。

(3) 界面美观大气,操作逻辑科学合理。

2.缺点

(1) 软件稳定性有待提高

目前,B/S模式已经广泛应用于网站和系统建设,但同时,B/S模式也存在着很多需要我们注意的问题,如并发性操作、大数据量访问等,这就很考验系统的设计和代码,因为他们会极大影响软件的稳定性。另外,软件行业中,版本更迭是非常常见的,但在更新版本的过程中,因为没有进行良好的交接,很容易造成系统的不稳定,为后期的维护工作带来巨大的困难。

(2) 存在安全隐患

B/S模式系统中的B是浏览器的意思,暨客户端操作是通过浏览器进行的,而浏览器又常采用脚本模式,脚本语言目前尚未完善,所以存在一些安全隐患。

2.3现行研究存在的问题及解决方法

2.3.1  现行研究存在的问题

1. 调度系统形式落后

多以人工为主进行项目任务的调度,没能做到与时俱进,采用计算机和网络来进行调度。

  1. 调度算法低效暴力

先行算法多以时间轮询为主,忽略了任务可并行以及树状结构任务调度以纵向

为主的机理。

3.数据库选择问题

市面上的数据库种类繁多,从这么多中选出一个适合本系统、拥有强大功、移植性强的数据库是非常重要的。选择时必须保证它可以有效的与其它数据库结合,降低系统的特定数据库的依赖,增强软件的可移植性。

4.可扩展性

因为需求的增多减少,或者弥补系统现有缺陷,程序进行修改和升级是必然的,这就要求程序具有良好的可扩展性。

5.开发平台和语言

选择一个良好的的开发平台和适合本系统的语言能够降低开发成本,延长生命周期。

2.3.2  解决办法

考虑到目前任务调度系统的需求与研究现状,想要解决上述问题应该从以下几方面的要求出发:

1.数据库选用MySql,足以保证数据存放的持久性,当存储设备改变时,不用重写程序代码就可以方便的移植过去。

2.系统实现模式采用B/S架构,实现过程也做到模块化,把用户界面与跳转逻辑分开,把业务信息又按应用功能分开,同时与数据交互层分开,任一方的改变都不会过多影响对方。

3.开发平台选用Eclipse,语言选用JAVA作为主要的开发语言,该语言一次编写随处运行以及强大的可伸缩性对于系统的开发和维护提供了强有力的保障。

4.设计一个能兼顾树状任务集纵横两个方向的调度算法,充分利用参与人员的时间空档,来缩短整个项目的完成时间

2.4  本课题要达到的设计目标

本课题采用B/S模式,面向或大或小的项目管理而开发的任务调度系统,为了系统的安全性,该系统只允许已经注册到该系统的用户使用。系统有两种角色:项目组长和项目组员。各用户可同时承担所有角色,各角色功能如下:

1.共有功能:

a、注册、登录功能,个人信息管理功能,如对密码的修改。

b、部分项目管理功能,实现了对项目的管理操作,包括对项目的搜索、查看操作。

c、部分任务管理功能,实现了对所有项目任务的管理操作,包括对任务集的查看操作。

2.项目组长:

a、具有管理组员、处理申请功能

b、具有部分项目管理功能,包括对项目的删除操作。

3.项目组员:

a、具有申请加入与退出项目组的功能。

2.5  经济效益分析

本任务调度系统是针对项目组任务调度和团队协作而开发的,一方面因为系统的人机交互界面的友好型和功能的全面性,工作效率与沟通成本均能得到较大改善,另一方面,系统开发运行成本低,所以经济效益是不言而喻的,能够用低成本得到高回报。

关键问题及分析

一个相对成熟的系统,对于稳定性和安全性都有很高的要求,本系统也不例外,所以本系统应用分层思想,通过前后台分离开发,来保证系统的稳定性与安全性。考虑项目组长和组员进入系统后功能需求的不同,需要对各用户类型的不同功能做详细分析。

3.1  问题分析与设计

在本次系统的设计中,势必会遇到许多以前没遇到过的问题,会需要许多曾经没有接触过的技术去攻克难点。所以,现将研究设计中要解决的问题总结如下:

3.1.1  核心问题即任务调度

此次所研究的问题是在3个约束下使由树状任务集组合而成的项目所用时间尽可能短。3个约束指的是:(1)对于每个任务, 必须等待其所有的前继任务完成后才能处理此任务;(2)对于每个组员, 任意时刻只能进行一个任务, 且必须满足完成一个任务后才能开始另一个任务;(3)不存在相同任务。

1、任务树和任务分类

由于项目的任务图呈树状结构,仅仅边的方向与正常的树相反,姑且可称之为任务树。任务树上的结点代表任务,有向边代表任务之间的次序关系。其中,叶结点任务为刚开始就可被进行的任务,根结点任务为最终进行的任务。当根结点任务完成,标志着整个项目完成。

设有一个项目, 项目由N任务组成.这N个任务可绘制出树状结构。在某个任务完成后, 剩下的未完成任务仍可绘制出树状结构。由任务树和问题的约束条件可知, 初始时只能调度某个叶节点任务.当某个任务结点的所有子节点任务全部完成, 则此任务结点就转换为叶节点任务。 现在分类任务:可调度任务是属于某空闲组员的叶节点任务;[i]准可调度任务是属于某非空闲组员的叶结点任务;不可调度任务是所有非叶节点任务;所有可调度任务和准可调任务的任务集为备选任务集[ii];若某个任务X在某个任务Y之后,且中间再无其他任务,则成X为Y的直接后继任务。

2、调度策略分析

关键路径为图中的概念,树作为特殊的一种图,我们可将其概念引申过来,在这里我们将任务树中需要进行时间最长的路径称为关键路径,所以整个项目的完成时间在很大程度上由关键路径的有效调度所决定。值得注意的是,关键路径是在不断发生变化的,在某个任务完成后,剩余任务树的关键路径是有可能发生变化的,所以在调度中如果始终保持一条关键路径不变,就无法保证整个项目用时最短。所以我们首先采用动态关键路径策略。

除此之外,由于任务是从备选任务中调度,故多个可调度任务同时争夺一个组员的情况是很有可能发生的,于此同时还可能发生这多个任务的路径长度均为最长即均在关键路径上。考虑到这种情况,我们在这里可以采用最短用时策略,优先调度用时较短的那个任务。

在整个项目中,一个项目组是有一个或多个组员的,为了是各个任务尽早开始,故我们使任务选择最早空闲的组员即选择最早适合开始任务的空隙。这里采用首次适应调度策略。

3.1.2  数据表间联系

任务调度系统涉及到的数据复杂,业务逻辑关系也较复杂,尤其是调度算法的逻辑,所以可能需要用到临时表,表与表之间也需要通过外键联系起来。外键的联系保证在项目组任务调度过程中业务操作稳定的关键。底层数据库设计的好坏直接影响着整个系统的稳定运行。

由于任务调度系统涉及到了具体的用户更新维护项目信息、项目任务集信息、个人登录信息功能操作,数据库中的数据不能随意删除,以防出现信息丢失的问题。所以必须重视表间的联系,倘若不够完善,系统运行起来就会报出许多bug或error,结果造成的损失将无法弥补,程序的可维护性也大打折扣。

3.1.3  系统安全性

本任务调度系统是基于B/S模式的,需要通过浏览器来进行访问,也就是说所有用户都可以通过浏览器来访问本系统。

因此本系统加入了注册和登录模块,只有注册用户输入正确的帐号密码后,才可以访问本系统,并且根据不同的用户角色分配不同的功能权限。于此同时,使用Spring中的拦截器,在除了主页和注册、登录页面意外的页面,都会验证登录状态,最大程度的防止用户以非法途径进入到本系统中。

调度算法设计

基于树状任务集组成的项目问题调度算法如下:

  1. 按照约束对项目构造任务树
  2. 根据任务树将可调度任务和准可调度任务加入备选任务集。如果任务集为空,则表示项目完成,转至第5步。
  3. 根据动态关键路径策略从备选任务集中选出路径长度最长的可调度任务。若任务唯一,则选取此任务,若不唯一,则选取用时最短的任务。
  4. 应用首次适应调度算法调度选出来的任务,接着从任务树上删除此任务结点,从备选任务集中删除此任务。回到第2步。
  5. 结束

算法流程图如图4.1所示:

图4.1 算法流程图

需求分析

需求分析可以说是软件开发过程各个阶段中最重要的,其定义是回答“系统做什么”的问题。计算机与软件技术近年来不断发展,信息管理系统已经覆盖了人们生活的方方面面,对于日常的信息统计管理起着越来越大的作用,在目前的潮流驱动下,为了项目组任务调度和团队协作的需求,基于SSH的任务调度系统被设计和开发。

5.1  USE-CASE用例图                 

任务调度系统分为项目组长和项目组员这两类用户角色。如图5.1所示为本系统的用例图。

图5.1 用例图

5.2  类图

任务调度细分类很多,如若运用了设计模式,接口或者抽象类数目也很庞大。在需求分析阶段,设计核心类如图5.2所示:

图5.2任务调度系统底层核心类图

5.3  活动图

活动图通过动作来组织,用于描述系统中某一行为,在需求分析阶段,我选用了比较重要,跨度较大的两个行为:修改密码、任务调度,如图5.3、5.4所示分别为对应的活动图:

图5.3 修改密码活动图

图5.4 任务调度活动图

5.4  功能需求

1、登录验证功能:本系统只对注册用户开发,所以在进入本系统时,用户必须进行注册登录,系统会对用户名和密码进行验证,无误后才可进入本系统,用户名和密码错误的话会出现错误提示并要求用户重新输入。

2、项目管理功能:用户共有功能,实现了对项目的管理操作,包括对项目的搜索、查看、添加和删除操作。

3、消息处理功能:用户共有功能,实现了对消息的管理操作,包括发送消息,查看消息,删除消息操作。

4、项目任务管理功能:项目组长功能,实现了对项目任务集的管理操作,包括对任务的添加、删除操作。

5、项目组成员管理功能:项目组长功能,实现了对项目组成员的管理操作,包括对组员的添加和删除操作。

5、申请功能:项目组员功能,实现了对感兴趣项目的操作,包括申请加入该项目与申请退出该项目。

5.5  开发环境

操作系统:Windows 7

开发语言:Java语言

数据库:MySQL

WEB服务器:Tomcat 8

开发工具:StarUML、Eclipse neon.1

客户端浏览器:Chrome

©5.6  系统交互图

5.6.1  系统架构类交互图

工作流程的系统架构:

1、在接收到用户输入的请求后,显示层的对象,将请求发送到WEB层进行处理。

2、接收到请求对象后,WEB进行权限验证,验证通过后将请求转发到Serviec层中相应的处理对象。

3、Service层处理对象进行业务逻辑的处理,并在需要时将请求对象发送到Manager层进行中间业务处理。

4、在这个问题上根据验证结果如下处理业务代理:不符合授权消息请求返回;满足的特权的请求,该请求被转发到业务事项。

5、业务流程的业务对象。用于处理业务数据保留的操作中,通过访问数据库访问对象,任何例外处理期间的异常处理的对象进行操作。最后,将结果返回给代理对象上的业务信息。

6、业务代理回给用户界面的结果在处理对象的信息。

系统架构类的交互图如图5.5所示:

图5.5 系统架构类的交互图

项目从申请加入到任务调度主要涉及:搜索项目,查看项目,申请加入项目,任务调度,回送消息,分派任务。该流程时序图如下图5.6所示:

图 5.6 申请并调度任务的时序图

该系统功能均为注册用户才能使用,用户注册时序图如下图5.7所示:

图5.7 用户注册的时序图

5.6.2  系统协作图

交互图来说明系统如何实现的使用情况或特殊用途的情况。 UML提供了两种类型的交互图,时序图和协作图的。时序图描述系统定时的元素之间的相互作用;按照时间和空间的顺序来描述该系统的元件之间的相互作用的协作图。

用户注册协作图如图5.8所示:

图 5.8 用户注册的协作图

用户创建项目协作图如图5.9所示:

图5.9 用户创建项目协作图

5.6.3  系统状态图

状态图是由对象的类型建模来描述的动态行为中的一个对象的变化的生命周期。状态图显示了状态机,这是唯一的一个状态机与投影机,这意味着包括该状态机的状态图的所有功能的元件。用户注册,用户登录,创建项目,用这三种状态来完成创建项目过程,所以用户创建项目状态图如图5.10所示:

图 5.10 用户创建项目的状态图

用户注册时用户信息状态图如图5.11所示:

图5.11 用户注册状态图

系统设计

任务调度系统设计的好坏将对系统的开发和维护起着至关重要的作用。系统的实现需要符合所有用户的要求,只有对用户的要求考虑的全面,才会开发出功能强大稳定的任务调度系统。

6.1  系统体系结构

本系统采用的是B/S的体系结构模式,通过浏览器展示系统界面,所有的事务逻辑均在后台服务端实现。                                                                                                                                                 

6.2  系统功能结构

根据需求调研结果确定本任务调度系统的功能结构,最终系统实现的系统将分为组长和组员两个角色,其中两个角色共有功能包括修改登录密码、项目搜索、项目查看、项目管理、消息管理。组长部分的功能有任务管理、项目组成员管理,组员部分的功能有申请调动功能。如图6.1所示为任务调度系统的功能结构图。

基于SSH的任务调度系统

用户

组员

项目搜索

项目查看

修改密码

项目管理

消息管理

申请

调动

组长

任务管理

任务管理

6.1 系统功能结构图

6.3  系统架构的设计目标

软件架构设计,以实现以下目标:

1.可行性。架构是可行的,是系统设计的基础。

2.可靠性。系统软件是为业务运营和用户管理极为重要,因此应该是可靠的软件系统。

3.安全性。进行软件系统的商业价值高的交易

安全系统是非常重要的。

4.可定制。同一组的软件,可以根据变化的客户和市场基础的各种需求进行调整。

5.可扩展性。出现在新的技术,应该允许一个软件系统新技术的进口,扩大现有系统的功能和性能。

6.可维护性。维护软件系统有两个方面,一个是排除现有的错误,第二个将需要新的软件,以反映在现有的系统中。可以有效地降低技术支持一个易于维护的系统成本。

7.可升级。应该能够使用该软件,用户数量的情况下迅速地提高用户的,保持合理的性能。只有这样,才能适应不断扩大的市场份额的可能性了。

8.客户体验。应该是易于使用的网站。该网站最终用户很有可能是不具备计算机专业技术人才。

6.4  系统架构设计

下面我们要发展的系统设计和基于信息系统的原则,系统模型系统的原则。我们对项目进行应用分层,如图6.2所示。

图6.2 系统体系架构图

1、开放接口层:直接封装Service接口,可以选择暴露成RPC接口;或者通过Web协议封装为http接口;网关控制层等,本项目中不提供此开放层。

2、终端显示层:各类客户端的模板渲染并执行的显示层。目前生产生活中主要是JSP渲染,JS渲染,velocity渲染,移动端展示层等,在本项目中主要变现为JS渲染。

3、Web层:对访问控制进行转发,业务逻辑前的预处理工作,如各类基本参数校验,或者简单业务处理等。

4、Service层:具体的业务逻辑服务层。

5、Manager层:通用业务处理层,包含特征:

1) 封装第三方平台,转化异常信息以及预处理业务和返回结果等;

2)下沉Service层通用能力,比如缓存方案、中间件通用处理;

3) 与DAO层交互,封装DAO的业务通用能力。缓存方案、中间件通用处理;

6、DAO层:数据访问层,与底层各类数据库或缓存方案进行数据交互。

7、外部接口或第三方平台:包括其他公司基础平台,或者RPC接口,也包括其它的HTTP接口,本项目中不依赖该层服务。

然后得到如图6.3所示的包图:

图6.3 网站模块包图

6.5  数据库表结构

6.5.1  数据库设计原则

数据库应用程序开始在数据库设计,数据库设计和数据的内容和组织。在设计数据库时,需要考虑的第一件事是在目标数据库的设计。一个良好的数据库,不应该有冗余数据,可以快速地创建一个记录,并且很容易维护。当然当到达所有数据库的设计目标,它是最完美的,但两者之间是相互排斥的,这是不可能同时实现的,例如,要消除冗余数据,就不可避免的要降低定位记录的速度。在本系统中考虑实际情况及需要,采用了以下的设计原则。

6.5.2  数据库设计概述

无论什么样的计算机信息系统,最终落点都为系统数据库。所以说,数据库是该类系统的核心,数据库与数据库管理系统,提供信息的收集,整理,存储,检索,更新,处理和传播统计业务的支持。

6.5.3  数据库设计周期

软件工程的介绍之后,数据库设计周期可分为六个步骤:

规划:提供的计划,软件系统,性能和可靠性等方面发展的总体目标确定给定的功能。

需求分析:仔细,以便了解的数据处理要求的系统边界的函数的用户被确定此阶段的最终结果是提供一种用于该系统作为一个规范草案,包括对硬件和软件环境的要求的基础。并有一套完整的数据流。

设计阶段:需求分析阶段,以确定细化的功能,是概念阶段,逻辑设计阶段,物理设计阶段的主要工作,那么对于室内设计细节的过程的每个阶段。

该方法的准备阶段:在一个或多个特定的语言对每个模块确定顺序控制程序的一个阶段,结构化编程方法应遵循..

调试阶段:该设备具有良好的程序调试(副音),整体调试(FBI)和系统测试(验收)放在一起。

运行与维护阶段。是整个设计周期最长的阶段,其重点是收集和记录数据的系统操作需要维护数据库的完整性操作,数据必须有效地处理故障和数据库恢复同时解决。在发展过程中的突出问题,纠正错误,才能充分发挥功能。数据是系统,运行整个系统的基础的灵魂,是一个系统的数据库,因此数据库设计的好坏对整个系统的功能和效率产生巨大的影响,使我们,一个数据文件和数据库设计的实现充分考虑了数据存储的一致性完整性,可靠性,安全性和数据,并允许运营问题等方面。

一个完整的信息系统的建设不是一步。在实际施工中,各子系统的第一次后,开发人员,他已建成的分配提出的观点的建设时间,涉及到兼容性问题,其他的我建立了各子系统之间。根据现有的软件级别,系统之间的追求相互兼容的应用程序有困难,而且还共享数据兼容的数据,它既是极其重要的,更容易达到相对兼容的应用程序的系统。为了提高数据。交换主要可以绘制从数据库中的系统结构考虑的数据的一致性,这会考虑两个下列标准,以确保数据的一致性:

领域的标准:标准不统一字段难以共享的主要原因为数据库中的一个,因为场的基础数据库设计的设计,或者可以说是最基本的水平,如果该水平不能统一,这将直接影响到对数据库中的共享数据。

码标准:为了保持数据的数据库中的一致性引入代码是一个重要的工具。

此外,该数据库的设计遵循以下原则:数据库文件,安全性,数据库文件,数据库文件,节省磁盘空间的独立性实用性。

数据库设计是,在特定应用环境(DBMS)中通过合理的逻辑设计和物理设计有效,数据库模式,子模式的最佳结构,建立一个数据库和设计应用将各种用户信息的需求。物理结构设计的原则如下:

1.尽可能减少数据冗余和重复。

2.结构设计与运行设计。

3.数据结构具有相对稳定性。

基于以上设计原则,本系统设计了一个数据库,包含基本信息表

6.5.4  数据字典

在系统设计中,数据库的设计占据了非常重要的地位,系统的成败取决于数据库的设计,也可以说数据是设计的基础。由于前期的疏忽,使得数据库的设计不完善、不合理,这将在系统的开发中,甚至后期的维护中引发严重的问题。根据系统需求,创建了6张表,下面是表数据结构描述。

表1   USER(用户表)

序号

列名

数据类型

长度

允许为空

说明

1

userId

int

12

用户编号

2

username

char

18

用户名

3

email

varchar

20

用户邮箱

4

password

varchar

20

用户密码

表2  PROJECT(项目表)

序号

列名

数据类型

长度

允许为空

说明

1

projectId

int

12

项目编号

2

name

varchar

18

项目名

3

description

varchar

50

项目描述

4

leadId

Int

12

项目发起人编号

5

weight

Int

12

项目完成时长

表3  JOB(项目任务表)

序号

列名

数据类型

长度

允许为空

说明

1

jobId

int

12

任务编号

2

name

varchar

18

任务名

3

description

varchar

50

任务描述

4

weight

int

12

任务权值

5

projectId

int

12

所属项目编号

表4  JOIN_PROJECTS(参与项目表)

序号

列名

数据类型

长度

允许为空

说明

1

userId

int

12

用户编号

2

projectId

int

12

项目编号

表5   JOB_CONNECTION(任务关系表)

序号

列名

数据类型

长度

允许为空

说明

1

connectionId

int

12

关系编号

2

jobId

Int

12

任务编号

3

nextJob

Int

12

后继任务编号

表6  MESSAGE(消息表)

序号

列名

数据类型

长度

允许为空

说明

1

messageId

int

12

消息编号

2

title

varchar

18

消息标题

3

content

varchar

50

消息内容

4

src

int

12

消息发送用户编号

5

dest

int

12

消息接收用户编号

系统实现

7.1  公共模块

7.1.1  模块功能

系统采用struts+hibernate+spring开发,采用了MVC模式,并且采用了分层思想,结构分为表现层,业务层和数据访问层。struts框架开发表现层;业务层封装业务流程,对于每个业务又有相应的service层和manager层,在这之中运用面向接口编程的原则;利用spring的ioc功能将实现类注入给表现层的action;数据访问层借助于hibernate实现,可适应不同数据库。

公共模块主要包括公共的配置文件,按业务模块将bean类分别放在相应的配置文件中,有助于统一管理,还包括一些拦截器,如统一编码为UTF-8的拦截器和检测登录状态拦截器等。

7.1.2  模块代码

applicationContext-common.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans >

<!-- 启用spring注解支持 -->

<context:annotation-config />

<!-- 启动Spring自动扫描功能 -->

    <context:component-scan base-package="com.fcq.schedule.job" />

<!--配数据源 -->

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"

     destroy-method="close">

     <property name="driverClass" value="com.mysql.jdbc.Driver" />

     <property name="jdbcUrl"

         value="jdbc:mysql://localhost:3306/generation_design?characterEncoding=utf8&amp;useSSL=true" />

     <property name="user" value="root" />

     <property name="password" value="123456" />

     <property name="maxPoolSize" value="80" />

     <property name="minPoolSize" value="1" />

     <property name="initialPoolSize" value="1" />

     <property name="maxIdleTime" value="20" />

</bean>

<!--定义Hibernate的SessionFactory -->

<!-- SessionFactory使用的数据源为上面的数据源 -->

<!-- 指定了Hibernate的映射文件和配置信息 -->

<bean id="sessionFactory"

     class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">

     <property name="dataSource" ref="dataSource" />

     <property name="hibernateProperties">

         <props>

              <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>

              <prop key="show_sql">true</prop>

              <prop key="hibernate.jdbc.batch_size">20</prop>

              <!-- 自动创建数据表 -->

              <prop key="hibernate.hbm2ddl.auto">update</prop>

         </props>

     </property>

     <!-- 使用配置文件 -->

     <property name="mappingLocations">

         <list>

              <value>classpath:com/fcq/schedule/job/po/*.hbm.xml</value>

         </list>

     </property>

     <!-- Spring自动加载annotatedClass -->

     <!-- <property name="annotatedClasses"> <list> <value>com.jialin.entity.User</value>

         </list> </property> -->

</bean>

    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">

        <property name="sessionFactory" ref="sessionFactory"></property>

    </bean>

<!-- 配置事务管理器 (声明式的事务) -->

<bean id="transactionManager"

     class="org.springframework.orm.hibernate5.HibernateTransactionManager">

     <property name="sessionFactory" ref="sessionFactory" />

</bean>

<!-- 配置事务通知属性 -->

<tx:advice id="txadvice" transaction-manager="transactionManager">

     <!-- 定义事务传播属性 -->

     <tx:attributes>

         <!-- <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="delete*"

              propagation="REQUIRED" /> <tx:method name="modify*" propagation="REQUIRED"

              /> hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到 <tx:method name="*" propagation="REQUIRED"

              read-only="true" /> -->

         <tx:method name="get*" read-only="false" propagation="REQUIRED" />

         <tx:method name="find*" read-only="false" propagation="REQUIRED" />

         <tx:method name="save*" read-only="false" propagation="REQUIRED" />

         <tx:method name="reg*" read-only="false" propagation="REQUIRED" />

         <tx:method name="modify*" read-only="false" propagation="REQUIRED" />

         <tx:method name="remove*" read-only="false" propagation="REQUIRED" />

         <tx:method name="*" propagation="REQUIRED" read-only="true" />

     </tx:attributes>

</tx:advice>

<!-- 配置事务切面;那些类那些方法使用事务 -->

<aop:config>

     <!-- 只对业务逻辑层实施事务 -->

     <aop:pointcut id="allManagerMethod"

         expression="execution(* com.fcq.schedule.job.service..*.*(..))" />

     <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txadvice" />

</aop:config>

</beans>

applicationContext-beans.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans >

<!-- Spring管理Struts2的Action -->

<bean name="registerAction" class="com.fcq.schedule.job.action.RegisterAction"

     scope="prototype">

     <property name="userManager" ref="userManager"></property>

</bean>

<bean name="loginAction" class="com.fcq.schedule.job.action.LoginAction"

     scope="prototype">

     <property name="userManager" ref="userManager"></property>

</bean>

<bean name="ajaxUserNameVerifyAction" class="com.fcq.schedule.job.action.AjaxUserNameVerifyAction"

     scope="prototype">

     <property name="userManager" ref="userManager"></property>

</bean>

<bean name="queryUserOrProjectAction" class="com.fcq.schedule.job.action.QueryUserOrProjectAction"

     scope="prototype">

     <property name="userManager" ref="userManager"></property>

     <property name="projectManager" ref="projectManager"></property>

</bean>

<bean name="userMainAction" class="com.opensymphony.xwork2.ActionSupport"

     scope="prototype"></bean>

<!-- Spring管理Struts2的Interceptor -->

<!-- <bean name="checkLoginInterceptor" class="com.fcq.schedule.job.interceptor.CheckLogin"

     scope="prototype"></bean> -->

    <!--用户业务逻辑类 -->

    <bean name="userManager" class="com.fcq.schedule.job.service.impl.UserManagerImpl">

        <property name="userDao" ref="baseDao"></property>

    </bean>

    <bean id="baseDao" class="com.fcq.schedule.job.dao.impl.UserDao">

        <property name="hibernateTemplate" ref="hibernateTemplate" />

    </bean>

    <!-- 项目业务逻辑类 -->

    <bean name="projectManager" class="com.fcq.schedule.job.service.impl.ProjectManagerImpl">

        <property name="projectDao" ref="projectDao"></property>

    </bean>

    <bean id="projectDao" class="com.fcq.schedule.job.dao.impl.ProjectDao">

        <property name="hibernateTemplate" ref="hibernateTemplate" />

    </bean>

    <!-- 任务业务逻辑类 -->

    <bean name="jobManager" class="com.fcq.schedule.job.service.impl.JobManagerImpl">

        <property name="jobDao" ref="jobDao"></property>

    </bean>

    <bean id="jobDao" class="com.fcq.schedule.job.dao.impl.JobDao">

        <property name="hibernateTemplate" ref="hibernateTemplate" />

    </bean>

<!-- 任务关系业务逻辑类 -->

<bean id="jobConnectionManager" class="com.fcq.schedule.job.service.impl.JobConnectionManagerImpl">

   <property name="jobConnectionDao" ref="jobConnectionDao"></property>

</bean>

<bean id="jobConnectionDao" class="com.fcq.schedule.job.dao.impl.JobConnectionDao">

     <property name="hibernateTemplate" ref="hibernateTemplate" />

</bean>

<!-- 消息业务逻辑类 -->

<bean id="messageManager" class="com.fcq.schedule.job.service.impl.MessageManagerImpl">

   <property name="messageDao" ref="messageDao"></property>

</bean>

<bean id="messageDao" class="com.fcq.schedule.job.dao.impl.MessageDao">

     <property name="hibernateTemplate" ref="hibernateTemplate" />

</bean>

</beans>

7.2  注册模块

7.2.1  模块功能

本系统出于安全性与经济效益的考虑,仅供已注册用户使用。故开发了该注册模块,让用户通过设置帐号、密码、邮箱就可注册成为本系统会员。

如图7.1所示为本任务调度系统的主页以及注册页面。

图7.1 主页暨注册页面

7.2.2  模块代码

注册form代码

<form action="register" class="uk-form" method="post"

                           accept-charset="utf-8">

                           <div class="uk-form-row">

                               <input class="uk-width-1-1" name="user.username"

                                    placeholder="用户名" type="text" οnfοcus="delData()">

                           </div>

                           <div class="uk-form-row" id="accDiv"></div>

                           <div class="uk-form-row">

                               <input class="uk-width-1-1" name="user.email" placeholder="邮箱"

                                    type="text" οnblur="formatEmail()" οnfοcus="delEmail()">

                           </div>

                           <div class="uk-form-row" id="emailDiv"></div>

                           <div class="uk-form-row">

                               <input class="uk-width-1-1" name="user.password" value=""

                                    autocomplete="off" placeholder="密码" type="password"

                                    οnblur="formatPwd()" οnfοcus="delPwd()">

                           </div>

                           <div class="uk-form-row" id="pwdDiv"></div>

                           <div class="uk-form-row">

                               <input class="uk-width-1-1" name="passwordCF" value=""

                                    autocomplete="off" placeholder="密码确认" type="password"

                                    οnblur="return verifyPwd()" οnfοcus="delCFPwd()">

                           </div>

                           <div class="uk-form-row" id="pwdCFDiv"></div>

                           <div class="uk-form-row">

                               <button

                                    class="uk-button uk-width-1-1 uk-text-bold uk-text-uppercase bg-blue text-white"

                                    type="submit" name="submit" value="submit">注册</button>

                           </div>

                          </form>

注册Controller层代码

ActionSupport子类代码 暨注册页面控制器代码:

public String execute() throws Exception {

     // TODO Auto-generated method stub

     try {

         userManager.regUser(user);

         Map session = ActionContext.getContext().getSession();

         session.put("user", user);

         return SUCCESS;

     } catch (Exception e) {

         // TODO: handle exception

         e.printStackTrace();

         return ERROR;

     }

    }

Service层代码

public void regUser(User user) throws HibernateException {

     userDao.saveObject(user);

DAO层代码

public void saveObject(Object obj) throws HibernateException {

     // TODO Auto-generated method stub

     try {

         hibernateTemplate.save((User) obj);

     } catch (Exception e) {

         // TODO: handle exception

         e.printStackTrace();

     }

    }

7.3  登录模块

7.3.1  模块功能

为了方便管理并且方便更高效的进行任务调度,本系统各项功能必须在已注册用户登录的状态下方可使用。用户进入系统之后首先要进入到系统的主页面及注册页面,可以在导航栏中选择进入登录页面,在登录页面中将验证用户输入的用户名以及密码是否正确,输入正确的用户名及密码才可以成功的登录系统,如果用户名或者密码错误将返回错误提示,

如图7.2所示为任务调度系统的登录页面:

图7.2 登录页面

7.3.2  模块代码

登录form代码

<form action="login" class="uk-form" method="post"

                           accept-charset="utf-8">

                           <div class="uk-form-row">

                               <input class="uk-width-1-1" name="user.username"

                                    placeholder="用户名" type="text" οnfοcus="delData()">

                           </div>

                           <div class="uk-form-row" id="accDiv"></div>

                           <div class="uk-form-row">

                               <input class="uk-width-1-1" name="user.password" value=""

                                    autocomplete="off" placeholder="密码" type="password"

                                    οnblur="formatPwd()" οnfοcus="delPwd()">

                           </div>

                           <div class="uk-form-row" id="pwdDiv"></div>

                           <div class="uk-form-row">

                               <button

                                    class="uk-button uk-width-1-1 uk-text-bold uk-text-uppercase bg-blue text-white"

                                    id="submit" type="submit" name="submit" value="submit">登录</button>

                           </div>

                          </form>

登录Controller层代码

public String execute() throws Exception {

     if(userManager.findUser(user)!=null){

         Map session = ActionContext.getContext().getSession();

         session.put("user", user);

         return SUCCESS;

     }else{

         return ERROR;

     }

    }

Service层代码

public User findUser(User user) {

     // TODO Auto-generated method stub

     return (User) userDao.findByUsernameAndPassword(user);

    }

DAO层代码

public User findByUsernameAndPassword(User user) throws HibernateException {

     // TODO Auto-generated method stub

     List<User> list = null;

     try {

         String hql = "from User  where  username=? and password=?";

         list = (List<User>) hibernateTemplate.find(hql, user.getUsername(), user.getPassword());

     } catch (Exception e) {

         // TODO: handle exception

         e.printStackTrace();

     }

     if (list != null && list.size() > 0) {

         return list.get(0);

     }

     return null;

    }

7.4  搜索模块

7.4.1  模块功能

该模块的目的主要是实现对已注册用户以及已发起的项目的搜索,来使用户根据自己的兴趣进行项目或者项目leader的选择,给用户提供了丰富的可能性。该模块支持模糊搜索,并标红搜索字段。

如图7.3所示为任务调度系统导航栏的搜索框:

图7.3 搜索框

如图7.4所示为任务调度系统的搜索结果页面:

图7.4 搜索结果页面

7.4.2  模块代码

前台Form代码

         <form action="queryUserOrProject">

              <div class="search_main">

                  <button class="search_btn" type="submit"></button>

                  <input class="search_text" name="UserOrProject" type="text"

                       placeholder="用户/项目"> <span class="close_btn"></span>

              </div>

             </form>

搜索Controller层代码

public String execute() throws Exception {

     // TODO Auto-generated method stub

     try {

         Map session = ActionContext.getContext().getSession();

         HttpServletRequest request = ServletActionContext.getRequest();

         String name = request.getParameter("UserOrProject");

         request.setAttribute("keyword", name);

         List<User> listUser = userManager.findByBlurUsername(name);

         List<Project> listProject = projectManager.findByBlurProjectName(name);

         request.setAttribute("listUser", listUser);

         request.setAttribute("listProject", listProject);

         return SUCCESS;

     } catch (Exception e) {

         // TODO: handle exception

         e.printStackTrace();

         return ERROR;

     }

    }

搜索Service层代码

public List<User> findByBlurUsername(String username) {

     return (List<User>) userDao.findByBlurUsername(username);

}

public List<Project> findByBlurProjectName(String name) {

     return projectDao.findByBlurProjectName(name);

    }

搜索DAO层代码

     public List<User> findByBlurUsername(String username) throws HibernateException {

     List<User> list = null;

     try {

         String hql = "from User where username like '%" + username + "%'";

         list = (List<User>) hibernateTemplate.find(hql);

     } catch (Exception e) {

         // TODO: handle exception

         e.printStackTrace();

     }

     if (list != null && list.size() > 0) {

         return list;

     }

     return null;

}

public List<Project> findByBlurProjectName(String name) {

     List<Project> list = null;

     try {

         String hql = "from Project where name like '%" + name + "%'";

         list = (List<Project>) hibernateTemplate.find(hql);

     } catch (Exception e) {

         // TODO: handle exception

         e.printStackTrace();

     }

     if (list != null && list.size() > 0) {

         return list;

     }

     return null;

    }

7.5  项目管理模块

7.5.1  模块功能

该模块为本系统的核心模块之一,该模块包括了添加项目,删除项目,编辑项目等功能,编辑项目主要指的是更新项目中的任务与参与者,这是进行任务调度必须有的一个关键步骤。

如图7.5所示为任务调度系统的项目编辑页面:

图7.5 项目编辑页面

7.5.2  模块代码

Controller层代码

public String execute() throws Exception {

     // TODO Auto-generated method stub

     try {

         String[] path = { "config/applicationContext-beans.xml" };

         ApplicationContext context = new ClassPathXmlApplicationContext(path);

         User user = (User) context.getBean("user");

         project.setLeader(user);

         projectManager.saveProject(project);

         ((ConfigurableApplicationContext) context).close();

         return SUCCESS;

     } catch (Exception e) {

         // TODO: handle exception

         e.printStackTrace();

         return ERROR;

     }

    }

Service层代码

        public void saveProject(Project project) {

         projectDao.saveProject(project);

        }

        public void removeProject(Project project) {

     projectDao.removeProject(project);

         }

public void modifyProject(Project project) {

     projectDao.modifyProject(project);

}

public Project findByName(String name) {

     return projectDao.findByName(name);

}

public Set<Project> findLeadProjectsByUsername(String username) {

     return projectDao.findLeadProjectsByUsername(username);

}

public Set<Project> findJoinProjectsByUsername(String username) {

     return projectDao.findJoinProjectsByUsername(username);

}

public List<Project> findByBlurProjectName(String name) {

     return projectDao.findByBlurProjectName(name);

    }

DAO层代码

/**

 * 保存项目

 *

 * @param project

 * @throws HibernateException

 */

public void saveProject(Project project) throws HibernateException {

     // TODO Auto-generated method stub

     try {

         hibernateTemplate.save(project);

     } catch (Exception e) {

         e.printStackTrace();

     }

}

/**

 * 删除项目

 *

 * @param project

 * @throws HibernateException

 */

public void removeProject(Project project) throws HibernateException {

     try {

         hibernateTemplate.delete(project);

     } catch (Exception e) {

         // TODO: handle exception

         e.printStackTrace();

     }

}

/**

 * 更改项目

 *

 * @param project

 * @throws HibernateException

 */

public void modifyProject(Project project) throws HibernateException {

     try {

         hibernateTemplate.update(project);// 会把这个表中的所有字段更新一遍。

     } catch (Exception e) {

         // TODO: handle exception

         e.printStackTrace();

     }

}

/**

 * 通过项目名查找项目

 *

 * @param name

 * @return

 * @throws HibernateException

 */

public Project findByName(String name) throws HibernateException {

     List<Project> list = null;

     try {

         String hql = "from Project where name=?";

         list = (List<Project>) hibernateTemplate.find(hql, name);

     } catch (Exception e) {

         // TODO: handle exception

         e.printStackTrace();

     }

     // hql:from 后面跟的类名+类对象 where后用对象的属性做条件

     if (list != null && list.size() > 0) {

         return list.get(0);

     }

     return null;

}

/**

 * 通过项目名模糊查找相关项目

 *

 * @param name

 * @return

 */

public List<Project> findByBlurProjectName(String name) {

     List<Project> list = null;

     try {

         String hql = "from Project where name like '%" + name + "%'";

         list = (List<Project>) hibernateTemplate.find(hql);

     } catch (Exception e) {

         // TODO: handle exception

         e.printStackTrace();

     }

     if (list != null && list.size() > 0) {

         return list;

     }

     return null;

}

/**

 * 通过用户名查找该用户所领导的项目

 *

 * @param username

 * @return

 */

public Set<Project> findLeadProjectsByUsername(String username) {

     List<Project> list = null;

     Set<Project> set = new HashSet<Project>();

     try {

         String hql = "select p from Project p,User u where p.leader=u and u.username=? ";

         list = (List<Project>) hibernateTemplate.find(hql, username);

     } catch (Exception e) {

         // TODO: handle exception

         e.printStackTrace();

     }

     if (list != null && list.size() > 0) {

         for (Project l : list) {

              set.add(l);

         }

         return set;

     }

     return null;

}

/**

 * 通过用户名查找该用户参与的项目集

 *

 * @param username

 * @return

 */

public Set<Project> findJoinProjectsByUsername(String username) {

     List<Project> list = null;

     Set<Project> set = new HashSet<Project>();

     try {

         String hql = "select p from Project p,User u where p.projectId in elements(u.joinProjects) and u.username=?";

         list = (List<Project>) hibernateTemplate.find(hql, username);

     } catch (Exception e) {

         // TODO: handle exception

         e.printStackTrace();

     }

     if (list != null && list.size() > 0) {

         for (Project l : list) {

              set.add(l);

         }

         return set;

     }

     return null;

    }

7.6  任务调度模块

7.6.1  模块功能

该模块为本系统的核心模块之一,后台通过运行调度算法来计算项目最佳调度方式,并展现给用户,故只有一个核心调度算法,无层次划分。

7.6.2  模块代码

Dispatcher类代码

/**

 * 任务调度核心类|| 核心方法为dispatcherCore(project)

 */

public class Dispatcher {

public UserManager userManager;

public ProjectManager projectManager;

public JobManager jobManager;

public JobConnectionManager jobConnectionManager;

Map<Integer, JobNode> mapJobNode;// 存储任务结点的Map集合。 在算法中为虚拟任务树

Map<JobNode, JobConnection> mapJobConnectionByJobNode;// 存储任务结点的连接信息.该Map初始化完毕后不用动key为当前结点,value为向下指向该结点的连接信息的集合

// 一个任务结点被分出去后,需要从下面这个Map中删除关于这个结点的连接信息。(需借助上面这个Map)看TA是不是叶子结点来选出备选集

Map<JobNode, List<JobConnection>> mapJobConnectionListByNextJobNode;// 存储任务结点的连接信息.key为当前结点,value为从该结点向下指出去的连接信息的集合

List<WorkerNode> listWorkerNode;// 初始化完成后无需再动

List<JobNode> optionJob;

public Dispatcher() {

     // TODO Auto-generated constructor stub

     userManager = new UserManagerImpl();

     projectManager = new ProjectManagerImpl();

     jobManager = new JobManagerImpl();

     jobConnectionManager = new JobConnectionManagerImpl();

}

public void dispatcherCore(Project project) {

     init(project);

     greedy(mapJobNode, listWorkerNode);

}

/**

 * 初始化项目和项目参与人员,将其添加至集合中

 *

 * @param project

 */

public void init(Project project) {

     Set<Job> setJob = project.getJobs();// 该项目含有的任务的集合

     mapJobNode = new HashMap<Integer, JobNode>();// 该项目JobNode的Map集合

     mapJobConnectionByJobNode = new HashMap<JobNode, JobConnection>();

     mapJobConnectionListByNextJobNode = new HashMap<JobNode, List<JobConnection>>();

     for (Job jobs : setJob) {

         JobNode jobNode = new JobNode(jobs.getJobId(), jobs.getWeight());

         mapJobNode.put(jobs.getJobId(), jobNode);

         JobConnection jobConnection = jobConnectionManager.findByJobId(jobs.getJobId());

         if (jobConnection != null) {

              mapJobConnectionByJobNode.put(jobNode, jobConnection);

         }

         List<JobConnection> listJobConnectionByNextJob = jobConnectionManager.findListByNextJobId(jobs.getJobId());

         if (listJobConnectionByNextJob != null) {

              mapJobConnectionListByNextJobNode.put(jobNode, listJobConnectionByNextJob);

         }

     }

     Set<User> setUser = userManager.findJoinerByProjectName(project.getName());// 项目参与者的集合

     listWorkerNode = new ArrayList<WorkerNode>();

     for (User set : setUser) {

         WorkerNode workerNode = new WorkerNode(set.getUserId());

         listWorkerNode.add(workerNode);

     }

}

public void greedy(Map<Integer, JobNode> mapJobNode, List<WorkerNode> listWorker) {

     int sum = 0;

     LinkedList<WorkerNode> listWorkerNode = (LinkedList) listWorker;

     // 每次循环都对Worker进行一次排序

     do {

         // 1、从任务树中选出备选任务集

         optionJob = selectOptionJob(mapJobNode);

         // 2、从备选任务集中选出路径长度最长的任务结点

         JobNode nowJobNode = selectLongestJobNode(optionJob);

         // 3、先将最长任务结点分配出去

         Collections.sort(listWorkerNode);

         WorkerNode nowWorkerNode = listWorkerNode.peek();

         System.out.println("将组员" + nowWorkerNode + "从第" + nowWorkerNode.getAvail() + "天到第"

                  + (nowWorkerNode.getAvail() + nowJobNode.getDay()) + "天的时间段分配给任务" + nowJobNode.getId());

         nowWorkerNode.setAvail(nowWorkerNode.getAvail() + nowJobNode.getDay());

         // 4、删除该任务结点

         deleteJobNode(nowJobNode);

     } while (optionJob.size() != 0);

}

/**

 * 删除JobNode

 *

 * @param jobNode

 */

public void deleteJobNode(JobNode jobNode) {

     // 4、将已分配到组员的任务删除分3步 :1.从备选任务集中删除 2.从任务树中删除 3.删除该结点相关的连接

     optionJob.remove(jobNode);

     mapJobNode.remove(jobNode.getId());

     // 删除该结点相关连接又分3步:1、获得该结点连接 2、获得该结点后继结点的map V值 3、从该V值中删除该结点连接

     JobConnection jobConnection = mapJobConnectionByJobNode.get(jobNode);

     List<JobConnection> waitRemove = mapJobConnectionListByNextJobNode.get(jobConnection.getNextJob());

     waitRemove.remove(jobConnection);

}

/**

 * 从任务树中选出备选任务集

 *

 * @param map

 * @return

 */

public List<JobNode> selectOptionJob(Map<Integer, JobNode> map) {

     List<JobNode> list = new ArrayList<JobNode>();

     for (JobNode values : map.values()) {

         if (isLeaf(values)) {// 如果是叶子结点

              list.add(values);

         }

     }

     return list;

}

/**

 * 判断是否为叶子结点

 *

 * @param jobNode

 * @return

 */

public boolean isLeaf(JobNode jobNode) {

     if (!mapJobConnectionListByNextJobNode.get(jobNode).isEmpty()) {

         return false;

     }

     return true;

}

/**

 * 从备选任务集中选出路径长度最长的任务

 *

 * @param optionJobNode

 * @return

 */

public JobNode selectLongestJobNode(List<JobNode> optionJobNode) {

     // 此时给一个函数计算路径

     JobNode longestJobNode = null;

     int max = 0;

     for (JobNode list : optionJobNode) {

         int nowLength = calculatePath(list);

         if (nowLength >= max) {

              max = nowLength;

              longestJobNode = list;

         }

     }

     return longestJobNode;

}

/**

 * 计算给出任务结点的路径长度

 *

 * @param jobNode

 * @return

 */

public int calculatePath(JobNode jobNode) {

     int pathLength = 0;

     JobConnection jobConnection = mapJobConnectionByJobNode.get(jobNode);

     while (jobConnection != null) {

         jobNode = mapJobNode.get(jobConnection.getNextJob());

         pathLength++;

     }

     return pathLength;

}

}

JobNode类代码

public class JobNode implements Comparable<JobNode> {

private Integer id;// 真实ID

private Integer day;

public JobNode(Integer id, Integer day) {

     // TODO Auto-generated constructor stub

     this.id = id;

     this.day = day;

}

@Override

public boolean equals(Object obj) {

     // TODO Auto-generated method stub

     if (obj == null) {

         return false;

     } else if (obj instanceof JobNode) {

         JobNode j = (JobNode) obj;

         if (this.id == j.getId() && this.day == j.getDay()) {

              return true;

         }

     }

     return false;

}

WorkerNode类代码

package com.fcq.schedule.job.core;

/**

 * 用来简化User类

 * @author 撒旦的奶爸

 *

 */

public class WorkerNode implements Comparable<WorkerNode> {

private Integer id;// 真实ID

private Integer avail;// worker空闲的时刻(即worker做完某一项工作的时间)

public WorkerNode(Integer id) {

     this.id = id;

     this.avail = 0;

}

@Override

public int compareTo(WorkerNode o) {

     int m = o.getAvail();

     if (avail < m)

         return -1;

     if (avail == m)

         return 0;

     return 1;

}

@Override

public boolean equals(Object obj) {

     if (obj == null) {

         return false;

     } else if (obj instanceof WorkerNode) {

         WorkerNode j = (WorkerNode) obj;

         if (this.id == j.getId()) {

              return true;

         }

     }

     return false;

}

}

结论与展望

大学即将过去,在这半年的时间里,这算是检验我的最终考试了。通过这次的毕业设计,我认识到了我的不足,基础不牢靠,解决方案选择不合理,眼界窄等等等等各种问题,在这即将踏入社会前夕通通暴露了出来,我很害怕也很高兴,害怕的是自己要进入社会了,却还有这么多问题,高兴的是自己没有发现太晚,问题暴露出来就是好事,我可以继续改正。

这半年中,从头到尾进行一个系统的设计与实现,对我的帮助无疑是巨大的,让我从稍高一层的层次中看待一个系统的实现,对于我以后相信也有非常大的帮助。系统实现运用了三大框架,体会到了框架的优势与劣势,也慢慢体会到了点工业界为什么会放弃struts2和hibernate,而去转用SpringMVC和MyBatis,也知道了注解和配置文件的适用场景,更重要的是,体会到了一个系统在自己手里从无到有的过程,这个过程是令人兴奋的,也令我有了坚持走技术路线的决心。

在这次毕业设计中,我总觉得技术不够用,从而了解到了其他方面的一些技术,虽然没在此次设计用运用,但这种欠缺感无疑会对我学习他们有着强大的驱动力,对我以后的工作和学习都有正面积极效应。

总之,很感谢这半年的自己,更感谢这四年来的大学生活。谢谢老师们,陪我度过了这人生中最宝贵的四年。

参考文献

  1. 朱大勇, 杨德明, 向金珍. AOE网的关键路径算法在网络工序中的应用[J]. 计算机应用, 2000, 20(6):49-51.
  2. 刘芳, 王玲. 基于动态规划思想求解关键路径的算法[J]. 计算机应用, 2006, 26(6):1440-1442.
  3. 陶维. 基于SSH多架构Web系统设计及其应用[J]. 科技和产业, 2009, 9(3):101-104.
  4. 刘振元, 陈鑫鹏. 活动成本目标多模式资源受限项目调度的组合调度算法[C]// 中国系统工程学会学术年会. 2012.
  5. 谢志强, 杨静, 周勇,等. 基于工序集的动态关键路径多产品制造调度算法[J]. 计算机学报, 2011, 34(2):406-412.
  6. 王希望, 孟祥书, 王福顺. 基于SSH架构的Web系统的开发方法[J]. 河北农业大学学报:农林教育版, 2010, 12(4):538-541.
  7. 翟高粤. 基于J2EE技术的SSH框架的改进及应用[J]. 计算机时代, 2012(10):24-26.
  8. Liu L R, Du D H C, Chen H C. An efficient parallel critical path algorithm[C]// Design   Automation Conference, 1991. ACM/IEEE. IEEE, 1991:535-540.
  9. Ren Y, Xing T, Chai X, et al. Study of Using Critical Path Method to Formulate the Algorithm of Software Project Schedule Planning[C]// International Conference on Information Management, Innovation Management and Industrial Engineering. IEEE, 2010:126-129.
  10. Mcgovern J, Tyagi S, Stevens M E, et al. Java Web Services Architecture[J]. 2003.

中文译文

Java Web服务体系结构

什么是Web服务?

“Web服务是由URI识别的软件应用程序,其接口和绑定能够被XML工件识别,描述和发现,并支持通过基于Internet的协议使用基于XML的消息与其他软件应用程序的直接交互。

Web服务是一个暴露了使用标准Web技术可访问并符合Web服务标准的功能的应用程序。 这点非常重要,因为Web服务是可以使用任何编程语言开发和部署到任何平台上的。 Web服务技术没有革命性或特殊性。 实际上,您可能已经使用并且开发了已经包含大部分Web服务技术的应用程序。

第3章:基于组件的服务开发

需求分析完成后,可以开始设计阶段。在开始设计阶段时,您不必等到所有的需求都被记录到文档中。在设计过程中,您将明确需求不完整的地方,以及发现更多的需求。设计和实施应以小增量进行,以创建服务。在每个阶段,只要有新的信息就需要改变以前的阶段。

在应用的设计阶段:

1、必须设计组成应用程序的服务。

2、服务层中服务的设计必须支持在需求分析过程中确定的QoS要求。

3、该设计还必须支持所确定的功能要求。

4、设计必须支持功能列表和用例。

5、设计必须映射到业务架构和概念服务模型。

6、必须确定可以重复使用的现有服务。

架构

设立服务产品线的组织为简历服务建立了一套核心方案。出于讲述的目的,我们将这些资产分为三个不同的架构视角:应用程序架构,技术架构和流程架构。每个架构视角都包含了解决我们特别关注的方面的工件。

应用架构

基于组件的服务层的应用程序架构包括指导和提供服务设计和实现设计目标的工件。这些工件中的一些包括概念架构,框架和库,基线架构,开发人员指南和计划大纲。这些工件确定服务层中服务的软件体系结构。概念架构提供了基于组件的服务中各层的描述和图表,以及这些层如何协作来提供功能性服务。

当组织开始为应用程序开发服务层时,通常会创建一组框架来帮助开发人员创建服务。这些框架实现了概念架构。这些框架使服务开发人员可以在服务的每一层提供功能代码。它们还规定了消息在层与层之间传递的方式。该框架提供了将功能开发人员与许多平台细节分开的可能,因此编写功能代码的开发人员不用太关心执行环境的技术细节。良好的服务框架将使功能服务开发人员专注于实现业务问题的解决方案,而不是创建技术问题的解决方案。

一旦框架完成,架构师将选择一组“架构有意义的”用例来实现基线体系结构。用例应足以消除项目的技术风险。应选择它们来证明可以满足非功能性要求。在大多数情况下,只会选择几个用例,基线架构将全面实施。他们应该通过架构的所有层次和层次展示一个主线,并提供足够的架构演示,促使系统的成功开发。

除了概念架构,框架和架构基准之外,架构还应包括详细的开发人员文档。本文档为功能开发人员提供了实现基于组件的服务的其余用例所需的信息。此外,在典型的产品线中,应开发一套大纲,其中包含开发服务的示例应用程序。这些大纲显示了使用提供的产品线资产使用框架开发服务的最佳做法。

分层架构服务层的概念架构是描绘分层建筑风格的模型。分层架构风格中的每一层都是一个软件包,它具有一个定义明确的界面和一些与其他层次的众所周知的依赖关系。每个层在服务中实现一个技术功能。例如,数据访问层负责封装用于访问数据库的技术。对数据库的所有数据访问请求都将通过该数据库的数据访问层。数据访问层负责从上层隐藏数据访问机制。

在封闭层系统中,层可以仅访问相邻层。在开放层系统中,层可以访问系统中的任何其他层,而不仅仅是它们相邻的层。我们建议使用开放分层的架构风格进行J2EE服务开发。这使开发人员能够交换层,从而大大提高了服务的可维护性。如果一层改变,而新层支持与其正在替换的层相同的接口契约,则相邻层不一定需要改变。分层的建筑风格也促进了开发中的并行性。一旦为每个层定义了范围,多个开发团队可以独立实施每一层。只要每一层的合同都不破坏,项目结束时的整合任务就是完成开发所必需的。

代理层代理层遵循“四人帮”的经典代理设计模式(Gamma等,1994)。 J2EE模式书(Alur,Crupi和Malks 2001)将此层称为“业务代理”。代理层由服务使用者访问服务的本地对象组成。代理抽象查询服务的所有细节并调用远程方法。它为服务客户端提供了强类型化的接口,不允许客户端发送不正确类型的数据。如果服务需要整数和字符串,代理将确保客户端使用这些数据类型。

客户端使用本地对象的本地方法调用。例如,银行帐户服务代理将具有称为借记帐户的方法,银行帐号为String和BigDecimal amount参数。代理人在注册表中查找银行帐户服务的URL,将参数转换为SOAP XML消息,并将其发布到服务中。服务代理处理注册表查找的所有复杂性,SOAP,XML和URL连接。服务开发人员为任何希望使用该服务的客户端创建代理。例如,如果Java客户端,Visual Basic客户端和Perl脚本都需要访问该服务,则开发人员为每个客户端提供一个代理,以使访问尽可能简单。

为每个服务创建不同代理的替代方法是使用动态代理。动态代理使用WSDL契约规范来动态提供与WSDL规范相匹配的强类型方法。它使用反射来创建与WSDL文档中的规范相匹配的方法。这种技术允许开发人员和消费者对所有可用服务使用单一代理。

服务外观接收服务请求,将其转换为本地方法调用,并在组件上调用正确的方法。它适配于在基于服务的环境中使用的组件。例如,JAX-RPC本身就是服务外墙层。它接受SOAP消息,并使用SOAP消息中的参数调用无状态会话bean。它还将调用无状态会话bean并将结果格式化为SOAP,然后将其返回给代理。服务外观了解Web服务环境中服务环境的协议和数据格式:通常是SOAP和HTTP。服务可以为服务支持的每种协议类型提供多个服务外观。例如,服务可能同时使用JAX-RPC通过HTTP公开服务,以及一个通过JMS接受SOAP消息的消息驱动bean。服务外观层也可以将SOAP消息转换为传递给会话外观的ValueObject进行执行。

会话外观层实现组件的分布式接口。例如,执行银行帐户服务逻辑的无状态会话bean具有会话外观。它支持组件接口的远程方法调用(RMI)。会话外观不实现业务逻辑本身。相反,会话外观将请求分派到业务逻辑层执行。会话外观了解组件的本机协议和数据格式。

业务逻辑层包含执行业务功能的对象。应该考虑命令模式来实现这些对象。使用Command模式,需求文档中的每个用例都被实现为在业务逻辑层中执行的单独命令或一组命令。每个命令对象实现一个命令接口。命令界面有一个简单的execute(ValueObject)方法。值对象只包含数据,没有业务逻辑,并且意图将数据从一个层或层传输到另一层。它具有简单的属性和getter和setter。它是从传递到会话外观层的SOAP消息构建的。

每个命令对象在其execute方法中都有业务逻辑。 execute方法的value对象参数包含执行use case命令所需的请求数据。典型的执行方法执行诸如访问数据访问层,执行业务逻辑以及将包含用例的结果的值对象返回到会话外观等功能。

在会话外观和业务逻辑层的典型UML图中,业务逻辑命令由实现CommandInvoker接口的会话外观执行。命令调用者负责创建正确的命令,执行它,并将结果返回到上游层。

服务层的技术架构是服务执行的运行时环境。 J2EE应用服务器,数据库服务器,目录服务器以及使服务层运行的任何其他机器,网络和操作系统。技术架构在服务器的版本和配置方面影响应用程序体系结构。例如,如果使用聚类,则会对框架必须使用技术环境的方式产生影响。这些框架不能支持bean引用,因为如果服务器关闭,引用可能会从一个服务器切换到另一个服务器。软件版本也对应用程序架构有影响。框架和库将使用特定版本的J2EE环境。如果应用程序服务器被升级,那么在它们上运行的框架也是如此。

虽然应用程序架构对服务层的可修改性,可重用性,可集成性和可测试性有重大影响,但技术架构在很大程度上影响了服务的性能,安全性,可用性,可靠性和可移植性。性能,可用性和可靠性在很大程度上是技术架构可扩展性的结果。强大的技术架构使得将应用程序和数据库服务器节点添加到集群和集线器到网络变得非常简单。如果一个节点出现故障,那么将该节点上的进程动态移动到另一个节点的能力对于服务层的可靠性至关重要。如果技术架构不能很好地执行并且批处理周期需要数小时,这将降低系统的可用性。如果进程无法动态分配给多个节点进行执行,则性能将受到影响。

应用架构和技术架构必须具有一致的设计,以满足基于架构的服务的所有QoS要求。有两类服务:功能服务和技术服务。

技术服务技术服务是一个全面的服务,与供应商平台配合,构成完整的服务执行环境。常用服务包括记录,转换,配置数据,事务管理,参考数据等。这些通用服务被其他服务和应用程序用于执行特定的技术功能。虽然商业服务可能实施银行帐户的功能,但技术服务可以围绕技术问题领域实现功能。

技术服务使用所有相同的服务产品线资产。它们使用与业务服务相同的框架,库和平台构建。技术服务和框架也作为业务服务与平台的具体方面之间的“分层”。例如,日志服务发布业务服务使用的接口。该接口支持业务服务的要求,与实现日志服务的特定技术无关。在内部,日志服务可能会使用Log4J来记录消息。在外部,这是不知道的任何商业服务。如果日志服务的实现发生变化,只要它支持相同的接口合同,那么任何服务都不需要了解更改。

像网络中的任何其他服务一样访问技术服务。但是,出于性能考虑,可以在代理中实现所有技术服务。因此,日志服务代理可以登录到本地文件。如果需要更强大的实现,则可以定期扫描文件并将其转储到数据库中进行报告。如果性能降低到一个问题并且需要实时记录,那么可以将代理交换为执行实时日志记录到日志记录服务的代理。在每种情况下,业务服务的接口保持不变。

为了使设计更加灵活,可以从代理工厂检索代理。在运行时环境中配置代理工厂以返回实现相同日志记录代理接口的特定类型的代理。服务的运行时配置可能有一天会返回实现基于文件的方案的代理,第二天返回通过网络记录的代理。这可以在不改变任何代码的情况下完成,只能配置文件。

处理

设计服务接口对于成功开发服务至关重要。该服务支持独特的业务功能,清晰自主的业务概念。例如,信用卡验证服务,储蓄账户服务和股票代码服务等服务都支持这一概念。上一章讨论了模块化服务的模块化和接口定义。定义接口的接口和属性必须被捕获的过程最好通过Bertrand Meyer(1997)的“按合同设计”方法的原理解决,并由Richard Mitchell和Jim McKim(2001)进行了扩展。

按合同设计按照接口合同设计的合同方式进行设计是为了设计类的接口而开发的,但其原理适用于服务接口设计,尽管倾斜不一。

接口设计合同设计基于六个原则:

1、从派生查询中分离基本查询。派生查询可以根据基本查询来指定。派生查询是使用其他查询获得最终答案的查询。基本查询直接在数据源之后才能获取数据。考虑支持银行所有帐户活动的银行帐户服务,包括支票和储蓄账户。如果客户需要获得帐户的余额,它将调用GetBalance服务。该方法查询账户持有者的支票和储蓄账户余额,并将其结算并返回结果。如果所有的客户需求是总体平衡,那永远不会有问题。然而,如果客户只需要支票账户余额,那么该服务就不会满足这一需求。因此,需要从两个帐户的复合派生查询中分离GetBalance的“基本”查询以节省和检查帐户。正确的设计将包括三个服务接口:支票账户服务的GetBalance,储蓄账户服务以及复合的BankAccount服务。复合派生服务方法将使用基本查询来代表客户端导出数据。

2、对于每个命令,写一个指定每个基本查询的值的后置条件。后置条件指定调用服务功能的效果。例如,支票帐户服务上的Withdraw命令将保证如果方法成功,GetBalance查询将返回之前的余额减去提款金额。

3、对于每个查询命令,决定一个合适的前提条件。对于需要多个步骤的方法,请指定多个步骤成功所需的前提条件。例如,考虑信用卡验证顺序,其中第一步是持卡人未超过事务的信用限额的验证。第二种方法实际上确认了事务。确认事务的前提条件是确认事务已经发生的前提条件。

4、对于每个派生查询,请编写一个后置条件,指定根据一个或多个基本查询返回的结果。如果我们知道基本查询的值,我们将知道派生查询的值。例如,在上一个示例中,派生的BankAccount服务上的GetBalance方法的后置条件指定结果是支票账户服务上的GetBalance方法与储蓄账户服务上的GetBalance方法的总和。

5、从命令中分离查询。编写界面契约的第一个原则是将查询与命令分开。查询检查服务的状态,并且命令更新服务的状态。例如,考虑一个银行帐户服务。GetBalance查询检索银行帐户服务的状态。命令Withdraw更新帐户中余额的状态。一个坏的设计将返回帐户的新的余额,当抽取被调用。这将结合查询与命令。这是不合需要的原因是,用户将被诱惑调用Withdraw方法来查询帐户的余额,从而无意中导致服务状态发生变化。 Withdraw方法只能返回服务调用的结果,例如“OK”或“Fail”。

6、编写不变量来定义对象的不变属性。例如,储蓄账户服务中的账户余额永远不能小于零。将这些不变量指定在某处有助于定义服务的所有可能状态,因此可以构建正确的错误处理

第14章:事务管理

概念

事务可能被认为是与系统的交互,导致系统状态的改变。虽然交互正在改变系统状态,但任何数量的事件都可以中断交互,使状态变化不完整,系统状态不一致,不合需要的形式。因此,事务边界内对系统状态的任何改变必须确保更改使系统处于稳定和一致的状态。

事务满足以下四个基本事务性质:原子性,一致性,隔离性和耐久性(ACID)。我们将详细检查每个属性。

原子性

将一次存取称为“工作单元”是很常见的。在将事务描述为工作单元时,我们将描述事务的一个基本属性:其中的活动必须被视为不可分割的,即原子的。

长笛银行客户可以与Flute的ATM交互,并将支票从支票账户转入储蓄账户。在长笛银行软件系统中,转帐交易涉及两种行为:支票账户的借方和储蓄账户的贷方。要使传输事务成功,两个操作都必须成功完成。如果任一个失败,则事务失败。事务的原子属性指示构成事务的所有单个操作必须成功,以使事务成功,相反,如果任何单个操作失败,整个事务整体将失败。

一致性

数据库或其他持久性存储通常定义参照和实体完整性规则,以确保商店中的数据是一致的。更改数据的事务必须确保数据保持一致状态 - 不会违反数据完整性规则,而不管事务是成功还是失败。存储中的数据在事务持续时间可能不一致,但其他事务不可见,并且事务完成时必须恢复一致性。

隔离性

当多个事务正在进行时,一个事务可能想要读取另一个事务已更改但未提交的相同数据。在事务提交之前,其所做的更改应被视为暂态,因为事务可以回滚更改。如果其他事务读取由正在进行的事务引起的中间或瞬态,则必须执行附加的应用逻辑来处理具有读潜在错误数据的某些事务的影响。事务的隔离属性指示对同一个数据子集行为的并发事务的行为。也就是说,隔离属性决定了作用在同一应用程序状态子集上的多个事务的影响彼此隔离的程度。

在最低级别的隔离中,事务可能会读取正在被另一个事务改变但尚未被提交的数据。如果第一个事务被回滚,则读取数据的事务将读取未提交的值。此级别的隔离读取未提交或“脏读”可能导致错误的结果,但确保最高的并发性。

读提交的隔离确保事务只能读取已提交的数据。这种隔离级别比读取未提交的隔离级别更具限制性(并且因此提供较少的并发性),并有助于避免与后一级隔离相关的问题。

可重复读取的隔离级别意味着读取一条数据的事务保证在事务完成之前数据不会被另一个事务更改。这种隔离级别的名称“可重复读取”来自于具有此隔离级别的事务可以重复读取相同的数据并保证看到相同的值。

最严格的隔离形式是可序列化的。此级别的隔离组合了可重复读取和读取提交的隔离级别的属性,有效地确保了对同一数据段执行的事务被序列化并且不会同时执行。

持久性

存取的持久性属性是指事务的有效性必须超出事务和应用程序的生命周期。 也就是说,在事务边界内进行的状态更改必须持久存储在永久存储介质(如磁盘,数据库或文件系统)上。 如果事务提交后应用程序发生故障,系统应保证当应用程序重新启动时事务的影响将可见。 事务资源也是可以恢复的:如果持久化的数据被破坏,可以执行恢复过程以将数据恢复到一个时间点(只要必要的管理任务被正确执行)。 一个事务提交的任何更改必须持久,直到另一个有效的事务更改数据为止。

隔离级别和锁

传统上,事务隔离级别是通过对它们访问的数据进行锁定来实现的,直到事务完成为止。锁有两种主要方式:乐观和悲观。这两种模式的必要性在于,当事务访问数据时,其意图改变(或不改变)数据可能不是很明显的。

某些系统采取悲观的方法并锁定数据,以便其他事务可能会读取,但不会更新第一个事务访问的数据,直到第一个事务完成。悲观锁定保证第一个事务可以随时对其首次访问的数据进行更改。

在乐观锁定模式下,第一个事务会访问数据,但不会对其进行锁定。第二个事务可能在第一个事务进行时更改数据。如果第一个事务后来决定更改其访问的数据,则必须检测数据现在已更改的事实,并通知发起者事实。因此,在乐观锁定中,首先访问数据的事务不能保证在稍后阶段更新事务。

在最基本的层面上,锁可以被分为(日益严格的限制)共享,更新和排他锁。共享锁表示另一个事务可以在同一数据块上进行更新或另一个共享锁。数据读取时通常使用共享锁(通常为悲观锁定模式)。

更新锁可确保另一个事务只能对同一数据执行共享锁定。更新锁由旨在更改数据(不只是读取)的事务持有。

如果事务用独占锁锁定一条数据,则其他事务不会对数据进行锁定。例如,具有读取未提交的隔离级别的事务不会对事务读取的数据造成任何锁定,并且具有可重复读取隔离的事务只能对已读取的数据执行共享锁定。

实现事务隔离的锁定对于所有事务环境可能不实用;然而,它仍然是实现事务隔离的最常见机制。

事务管理

在与数据库管理系统(DBMS)交互的简单Java应用程序中,应用程序可以使用显式SQL提交和回滚来划分事务边界。更复杂的应用环境,通过跨网络分布的多个事务资源,需要专门的组件来管理协调事务的复杂性以完成。

事务管理器与应用程序和应用程序服务器一起提供服务以控制事务的范围和持续时间。事务管理器还帮助协调跨多个事务资源管理器(例如,数据库管理系统)的全局事务的完成,为事务同步和恢复提供支持,并且可以提供与其他事务管理器实例进行通信的能力。

事务上下文包含有关事务的信息。在概念上,事务上下文是包含唯一事务标识符,超时值以及控制事务范围的事务管理器引用的数据结构。在Java应用程序中,事务管理器将事务上下文与当前执行的线程相关联。如果可能,多线程可能与相同的事务上下文相关联 - 将事务的工作分解为并行任务。如果事务跨越多个事务管理器,则上下文也必须从一个事务管理器传递到另一个事务管理器。

参考资料:

基于ssh的任务调度系统毕业设计(项目报告+答辩PPT+源代码+数据库+截图+部署视频)icon-default.png?t=N5K3https://download.csdn.net/download/dwf1354046363/87813624Java毕业设计174例,包含部署视频_易小侠的博客-CSDN博客icon-default.png?t=N5K3https://cv2022.blog.csdn.net/article/details/124463185?spm=1001.2014.3001.5502

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐无限出发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值