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

阿西可可

发布日期: 2020-07-29 11:00:54 浏览量: 57
评分:
star star star star star star star star star star_border
*转载请注明来自write-bug.com

摘 要

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

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

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

Abstract

With the rapid development of science and technology and the division of labor in all walks of life more and more refined, for the reform of the traditional task of scheduling tasks more and more. Thanks to the rapid development of computer technology, we see the direction of reform. The purpose of this system is based on the design and implementation of the task scheduling system based on SSH, which is designed for the task scheduling of enterprises or institutions or even a small team. The purpose is to change the traditional scheduling mode and calculate the most Good staff allocation and the best time allocation, draw the task scheduling map, in order to better carry out the task scheduling and team collaboration, the system is a task scheduling system.

The system uses a B / S architecture, the main realization of the language is JAVA, the background database using MySql. The whole system implementation role will be divided into group leader and team members, to achieve the functions, including account registration, modify information, project management, task management, message management, team management and other functions. The design and implementation of the task dispatching system can realize the scheduling and scientific allocation of the task remotely, and make the task plan be carried out by evaluating the tasks and the participants.

Keywords: Task scheduling; B/S; SSH

1 引言

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

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

1.1 课题研究意义及背景

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

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

1.2 论文的目的及设计要求

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

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

2 研究现状及设计目标

2.1 任务调度系统的现状

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

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

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

2.2.1 优点

  • 采用可扩展性强、分离度高的B/S模式

  • 数据库选用了市场上应用广泛的关系型数据库

  • 界面美观大气,操作逻辑科学合理

2.2.2 缺点

软件稳定性有待提高

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

存在安全隐患

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

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

2.3.1 现行研究存在的问题

  • 调度系统形式落后:多以人工为主进行项目任务的调度,没能做到与时俱进,采用计算机和网络来进行调度

  • 调度算法低效暴力:先行算法多以时间轮询为主,忽略了任务可并行以及树状结构任务调度以纵向为主的机理

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

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

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

2.3.2 解决办法

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

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

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

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

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

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

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

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

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

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

项目组长:

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

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

项目组员:

  • 具有申请加入与退出项目组的功能

2.5 经济效益分析

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

3 关键问题及分析

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

3.1 问题分析与设计

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

3.1.1 核心问题即任务调度

此次所研究的问题是在3个约束下使由树状任务集组合而成的项目所用时间尽可能短。3个约束指的是:

  • 对于每个任务,必须等待其所有的前继任务完成后才能处理此任务

  • 对于每个组员,任意时刻只能进行一个任务,且必须满足完成一个任务后才能开始另一个任务

  • 不存在相同任务

任务树和任务分类

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

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

调度策略分析

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

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

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

3.1.2 数据表间联系

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

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

3.1.3 系统安全性

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

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

4 调度算法设计

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

  • 按照约束对项目构造任务树

  • 根据任务树将可调度任务和准可调度任务加入备选任务集。如果任务集为空,则表示项目完成,转至第5步

  • 根据动态关键路径策略从备选任务集中选出路径长度最长的可调度任务。若任务唯一,则选取此任务,若不唯一,则选取用时最短的任务

  • 应用首次适应调度算法调度选出来的任务,接着从任务树上删除此任务结点,从备选任务集中删除此任务。回到第2步

  • 结束

算法流程图如图4.1所示:

5 需求分析

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

5.1 USE-CASE用例图

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

5.2 类图

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

5.3 活动图

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

修改密码活动图

任务调度活动图

5.4 功能需求

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

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

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

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

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

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

5.5 开发环境

  • 操作系统:Windows 7

  • 开发语言:Java语言

  • 数据库:MySQL

  • WEB服务器:Tomcat 8

  • 开发工具:StarUML、Eclipse neon.1

  • 客户端浏览器:Chrome

5.6 系统交互图

5.6.1 系统架构类交互图

工作流程的系统架构:

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

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

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

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

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

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

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

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

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

5.6.2 系统协作图

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

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

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

5.6.3 系统状态图

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

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

6 系统设计

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

6.1 系统体系结构

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

6.2 系统功能结构

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

6.3 系统架构的设计目标

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

  • 可行性:架构是可行的,是系统设计的基础

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

  • 安全性:进行软件系统的商业价值高的交易安全系统是非常重要的

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

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

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

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

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

6.4 系统架构设计

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

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

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

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

  • Service层:具体的业务逻辑服务层

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

    • 封装第三方平台,转化异常信息以及预处理业务和返回结果等
    • 下沉Service层通用能力,比如缓存方案、中间件通用处理
    • 与DAO层交互,封装DAO的业务通用能力。缓存方案、中间件通用处理
  • DAO层:数据访问层,与底层各类数据库或缓存方案进行数据交互

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

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

6.5 数据库表结构

6.5.1 数据库设计原则

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

6.5.2 数据库设计概述

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

6.5.3 数据库设计周期

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

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

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

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

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

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

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

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

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

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

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

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

  • 尽可能减少数据冗余和重复

  • 结构设计与运行设计

  • 数据结构具有相对稳定性

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

6.5.4 数据字典

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

USER(用户表)

序号 列名 数据类型 长度 允许为空 说明
1 userId int 12 用户编号
2 username char 18 用户名
3 email varchar 20 用户邮箱
4 password varchar 20 用户密码

PROJECT(项目表)

序号 列名 数据类型 长度 允许为空 说明
1 projectId int 12 项目编号
2 name varchar 18 项目名
3 description varchar 50 项目描述
4 leadId Int 12 项目发起人编号
5 weight Int 12 项目完成时长

JOB(项目任务表)

序号 列名 数据类型 长度 允许为空 说明
1 jobId int 12 任务编号
2 name varchar 18 任务名
3 description varchar 50 任务描述
4 weight int 12 任务权值
5 projectId int 12 所属项目编号

JOIN_PROJECTS(参与项目表)

序号 列名 数据类型 长度 允许为空 说明
1 userId int 12 用户编号
2 projectId int 12 项目编号

JOB_CONNECTION(任务关系表)

序号 列名 数据类型 长度 允许为空 说明
1 connectionId int 12 关系编号
2 jobId Int 12 任务编号
3 nextJob Int 12 后继任务编号

MESSAGE(消息表)

序号 列名 数据类型 长度 允许为空 说明
1 messageId int 12 消息编号
2 title varchar 18 消息标题
3 content varchar 50 消息内容
4 src int 12 消息发送用户编号
5 dest int 12 消息接收用户编号

7 系统实现

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

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans >
  3. <!-- 启用spring注解支持 -->
  4. <context:annotation-config />
  5. <!-- 启动Spring自动扫描功能 -->
  6. <context:component-scan base-package="com.fcq.schedule.job" />
  7. <!--配数据源 -->
  8. <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
  9. destroy-method="close">
  10. <property name="driverClass" value="com.mysql.jdbc.Driver" />
  11. <property name="jdbcUrl"
  12. value="jdbc:mysql://localhost:3306/generation_design?characterEncoding=utf8&amp;useSSL=true" />
  13. <property name="user" value="root" />
  14. <property name="password" value="123456" />
  15. <property name="maxPoolSize" value="80" />
  16. <property name="minPoolSize" value="1" />
  17. <property name="initialPoolSize" value="1" />
  18. <property name="maxIdleTime" value="20" />
  19. </bean>
  20. <!--定义Hibernate的SessionFactory -->
  21. <!-- SessionFactory使用的数据源为上面的数据源 -->
  22. <!-- 指定了Hibernate的映射文件和配置信息 -->
  23. <bean id="sessionFactory"
  24. class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
  25. <property name="dataSource" ref="dataSource" />
  26. <property name="hibernateProperties">
  27. <props>
  28. <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
  29. <prop key="show_sql">true</prop>
  30. <prop key="hibernate.jdbc.batch_size">20</prop>
  31. <!-- 自动创建数据表 -->
  32. <prop key="hibernate.hbm2ddl.auto">update</prop>
  33. </props>
  34. </property>
  35. <!-- 使用配置文件 -->
  36. <property name="mappingLocations">
  37. <list>
  38. <value>classpath:com/fcq/schedule/job/po/*.hbm.xml</value>
  39. </list>
  40. </property>
  41. <!-- Spring自动加载annotatedClass -->
  42. <!-- <property name="annotatedClasses"> <list> <value>com.jialin.entity.User</value>
  43. </list> </property> -->
  44. </bean>
  45. <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
  46. <property name="sessionFactory" ref="sessionFactory"></property>
  47. </bean>
  48. <!-- 配置事务管理器 (声明式的事务) -->
  49. <bean id="transactionManager"
  50. class="org.springframework.orm.hibernate5.HibernateTransactionManager">
  51. <property name="sessionFactory" ref="sessionFactory" />
  52. </bean>
  53. <!-- 配置事务通知属性 -->
  54. <tx:advice id="txadvice" transaction-manager="transactionManager">
  55. <!-- 定义事务传播属性 -->
  56. <tx:attributes>
  57. <!-- <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="delete*"
  58. propagation="REQUIRED" /> <tx:method name="modify*" propagation="REQUIRED"
  59. /> hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到 <tx:method name="*" propagation="REQUIRED"
  60. read-only="true" /> -->
  61. <tx:method name="get*" read-only="false" propagation="REQUIRED" />
  62. <tx:method name="find*" read-only="false" propagation="REQUIRED" />
  63. <tx:method name="save*" read-only="false" propagation="REQUIRED" />
  64. <tx:method name="reg*" read-only="false" propagation="REQUIRED" />
  65. <tx:method name="modify*" read-only="false" propagation="REQUIRED" />
  66. <tx:method name="remove*" read-only="false" propagation="REQUIRED" />
  67. <tx:method name="*" propagation="REQUIRED" read-only="true" />
  68. </tx:attributes>
  69. </tx:advice>
  70. <!-- 配置事务切面;那些类那些方法使用事务 -->
  71. <aop:config>
  72. <!-- 只对业务逻辑层实施事务 -->
  73. <aop:pointcut id="allManagerMethod"
  74. expression="execution(* com.fcq.schedule.job.service..*.*(..))" />
  75. <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txadvice" />
  76. </aop:config>
  77. </beans>

applicationContext-beans.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans >
  3. <!-- Spring管理Struts2的Action -->
  4. <bean name="registerAction" class="com.fcq.schedule.job.action.RegisterAction"
  5. scope="prototype">
  6. <property name="userManager" ref="userManager"></property>
  7. </bean>
  8. <bean name="loginAction" class="com.fcq.schedule.job.action.LoginAction"
  9. scope="prototype">
  10. <property name="userManager" ref="userManager"></property>
  11. </bean>
  12. <bean name="ajaxUserNameVerifyAction" class="com.fcq.schedule.job.action.AjaxUserNameVerifyAction"
  13. scope="prototype">
  14. <property name="userManager" ref="userManager"></property>
  15. </bean>
  16. <bean name="queryUserOrProjectAction" class="com.fcq.schedule.job.action.QueryUserOrProjectAction"
  17. scope="prototype">
  18. <property name="userManager" ref="userManager"></property>
  19. <property name="projectManager" ref="projectManager"></property>
  20. </bean>
  21. <bean name="userMainAction" class="com.opensymphony.xwork2.ActionSupport"
  22. scope="prototype"></bean>
  23. <!-- Spring管理Struts2的Interceptor -->
  24. <!-- <bean name="checkLoginInterceptor" class="com.fcq.schedule.job.interceptor.CheckLogin"
  25. scope="prototype"></bean> -->
  26. <!--用户业务逻辑类 -->
  27. <bean name="userManager" class="com.fcq.schedule.job.service.impl.UserManagerImpl">
  28. <property name="userDao" ref="baseDao"></property>
  29. </bean>
  30. <bean id="baseDao" class="com.fcq.schedule.job.dao.impl.UserDao">
  31. <property name="hibernateTemplate" ref="hibernateTemplate" />
  32. </bean>
  33. <!-- 项目业务逻辑类 -->
  34. <bean name="projectManager" class="com.fcq.schedule.job.service.impl.ProjectManagerImpl">
  35. <property name="projectDao" ref="projectDao"></property>
  36. </bean>
  37. <bean id="projectDao" class="com.fcq.schedule.job.dao.impl.ProjectDao">
  38. <property name="hibernateTemplate" ref="hibernateTemplate" />
  39. </bean>
  40. <!-- 任务业务逻辑类 -->
  41. <bean name="jobManager" class="com.fcq.schedule.job.service.impl.JobManagerImpl">
  42. <property name="jobDao" ref="jobDao"></property>
  43. </bean>
  44. <bean id="jobDao" class="com.fcq.schedule.job.dao.impl.JobDao">
  45. <property name="hibernateTemplate" ref="hibernateTemplate" />
  46. </bean>
  47. <!-- 任务关系业务逻辑类 -->
  48. <bean id="jobConnectionManager" class="com.fcq.schedule.job.service.impl.JobConnectionManagerImpl">
  49. <property name="jobConnectionDao" ref="jobConnectionDao"></property>
  50. </bean>
  51. <bean id="jobConnectionDao" class="com.fcq.schedule.job.dao.impl.JobConnectionDao">
  52. <property name="hibernateTemplate" ref="hibernateTemplate" />
  53. </bean>
  54. <!-- 消息业务逻辑类 -->
  55. <bean id="messageManager" class="com.fcq.schedule.job.service.impl.MessageManagerImpl">
  56. <property name="messageDao" ref="messageDao"></property>
  57. </bean>
  58. <bean id="messageDao" class="com.fcq.schedule.job.dao.impl.MessageDao">
  59. <property name="hibernateTemplate" ref="hibernateTemplate" />
  60. </bean>
  61. </beans>

7.2 注册模块

7.2.1 模块功能

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

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

7.2.2 模块代码

注册form代码

  1. <form action="register" class="uk-form" method="post" accept-charset="utf-8">
  2. <div class="uk-form-row">
  3. <input class="uk-width-1-1" name="user.username"
  4. placeholder="用户名" type="text" onfocus="delData()">
  5. </div>
  6. <div class="uk-form-row" id="accDiv"></div>
  7. <div class="uk-form-row">
  8. <input class="uk-width-1-1" name="user.email" placeholder="邮箱"
  9. type="text" onblur="formatEmail()" onfocus="delEmail()">
  10. </div>
  11. <div class="uk-form-row" id="emailDiv"></div>
  12. <div class="uk-form-row">
  13. <input class="uk-width-1-1" name="user.password" value=""
  14. autocomplete="off" placeholder="密码" type="password"
  15. onblur="formatPwd()" onfocus="delPwd()">
  16. </div>
  17. <div class="uk-form-row" id="pwdDiv"></div>
  18. <div class="uk-form-row">
  19. <input class="uk-width-1-1" name="passwordCF" value=""
  20. autocomplete="off" placeholder="密码确认" type="password"
  21. onblur="return verifyPwd()" onfocus="delCFPwd()">
  22. </div>
  23. <div class="uk-form-row" id="pwdCFDiv"></div>
  24. <div class="uk-form-row">
  25. <button
  26. class="uk-button uk-width-1-1 uk-text-bold uk-text-uppercase bg-blue text-white"
  27. type="submit" name="submit" value="submit">注册</button>
  28. </div>
  29. </form>

注册Controller层代码

  1. public String execute() throws Exception {
  2. // TODO Auto-generated method stub
  3. try {
  4. userManager.regUser(user);
  5. Map session = ActionContext.getContext().getSession();
  6. session.put("user", user);
  7. return SUCCESS;
  8. } catch (Exception e) {
  9. // TODO: handle exception
  10. e.printStackTrace();
  11. return ERROR;
  12. }
  13. }

Service层代码

  1. public void regUser(User user) throws HibernateException {
  2. userDao.saveObject(user);

DAO层代码

  1. public void saveObject(Object obj) throws HibernateException {
  2. // TODO Auto-generated method stub
  3. try {
  4. hibernateTemplate.save((User) obj);
  5. } catch (Exception e) {
  6. // TODO: handle exception
  7. e.printStackTrace();
  8. }
  9. }

7.3 登录模块

7.3.1 模块功能

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

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

7.3.2 模块代码

登录form代码

  1. <form action="login" class="uk-form" method="post"
  2. accept-charset="utf-8">
  3. <div class="uk-form-row">
  4. <input class="uk-width-1-1" name="user.username"
  5. placeholder="用户名" type="text" onfocus="delData()">
  6. </div>
  7. <div class="uk-form-row" id="accDiv"></div>
  8. <div class="uk-form-row">
  9. <input class="uk-width-1-1" name="user.password" value=""
  10. autocomplete="off" placeholder="密码" type="password"
  11. onblur="formatPwd()" onfocus="delPwd()">
  12. </div>
  13. <div class="uk-form-row" id="pwdDiv"></div>
  14. <div class="uk-form-row">
  15. <button
  16. class="uk-button uk-width-1-1 uk-text-bold uk-text-uppercase bg-blue text-white"
  17. id="submit" type="submit" name="submit" value="submit">登录</button>
  18. </div>
  19. </form>

登录Controller层代码

  1. public String execute() throws Exception {
  2. if(userManager.findUser(user)!=null){
  3. Map session = ActionContext.getContext().getSession();
  4. session.put("user", user);
  5. return SUCCESS;
  6. }else{
  7. return ERROR;
  8. }
  9. }

Service层代码

  1. public User findUser(User user) {
  2. // TODO Auto-generated method stub
  3. return (User) userDao.findByUsernameAndPassword(user);
  4. }

DAO层代码

  1. public User findByUsernameAndPassword(User user) throws HibernateException {
  2. // TODO Auto-generated method stub
  3. List<User> list = null;
  4. try {
  5. String hql = "from User where username=? and password=?";
  6. list = (List<User>) hibernateTemplate.find(hql, user.getUsername(), user.getPassword());
  7. } catch (Exception e) {
  8. // TODO: handle exception
  9. e.printStackTrace();
  10. }
  11. if (list != null && list.size() > 0) {
  12. return list.get(0);
  13. }
  14. return null;
  15. }

7.4 搜索模块

7.4.1 模块功能

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

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

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

7.4.2 模块代码

前台Form代码

  1. <form action="queryUserOrProject">
  2. <div class="search_main">
  3. <button class="search_btn" type="submit"></button>
  4. <input class="search_text" name="UserOrProject" type="text"
  5. placeholder="用户/项目"> <span class="close_btn"></span>
  6. </div>
  7. </form>

搜索Controller层代码

  1. public String execute() throws Exception {
  2. // TODO Auto-generated method stub
  3. try {
  4. Map session = ActionContext.getContext().getSession();
  5. HttpServletRequest request = ServletActionContext.getRequest();
  6. String name = request.getParameter("UserOrProject");
  7. request.setAttribute("keyword", name);
  8. List<User> listUser = userManager.findByBlurUsername(name);
  9. List<Project> listProject = projectManager.findByBlurProjectName(name);
  10. request.setAttribute("listUser", listUser);
  11. request.setAttribute("listProject", listProject);
  12. return SUCCESS;
  13. } catch (Exception e) {
  14. // TODO: handle exception
  15. e.printStackTrace();
  16. return ERROR;
  17. }
  18. }

搜索Service层代码

  1. public List<User> findByBlurUsername(String username) {
  2. return (List<User>) userDao.findByBlurUsername(username);
  3. }
  4. public List<Project> findByBlurProjectName(String name) {
  5. return projectDao.findByBlurProjectName(name);
  6. }

搜索DAO层代码

  1. public List<User> findByBlurUsername(String username) throws HibernateException {
  2. List<User> list = null;
  3. try {
  4. String hql = "from User where username like '%" + username + "%'";
  5. list = (List<User>) hibernateTemplate.find(hql);
  6. } catch (Exception e) {
  7. // TODO: handle exception
  8. e.printStackTrace();
  9. }
  10. if (list != null && list.size() > 0) {
  11. return list;
  12. }
  13. return null;
  14. }
  15. public List<Project> findByBlurProjectName(String name) {
  16. List<Project> list = null;
  17. try {
  18. String hql = "from Project where name like '%" + name + "%'";
  19. list = (List<Project>) hibernateTemplate.find(hql);
  20. } catch (Exception e) {
  21. // TODO: handle exception
  22. e.printStackTrace();
  23. }
  24. if (list != null && list.size() > 0) {
  25. return list;
  26. }
  27. return null;
  28. }

7.5 项目管理模块

7.5.1 模块功能

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

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

7.5.2 模块代码

Controller层代码

  1. public String execute() throws Exception {
  2. // TODO Auto-generated method stub
  3. try {
  4. String[] path = { "config/applicationContext-beans.xml" };
  5. ApplicationContext context = new ClassPathXmlApplicationContext(path);
  6. User user = (User) context.getBean("user");
  7. project.setLeader(user);
  8. projectManager.saveProject(project);
  9. ((ConfigurableApplicationContext) context).close();
  10. return SUCCESS;
  11. } catch (Exception e) {
  12. // TODO: handle exception
  13. e.printStackTrace();
  14. return ERROR;
  15. }
  16. }

Service层代码

  1. public void saveProject(Project project) {
  2. projectDao.saveProject(project);
  3. }
  4. public void removeProject(Project project) {
  5. projectDao.removeProject(project);
  6. }
  7. public void modifyProject(Project project) {
  8. projectDao.modifyProject(project);
  9. }
  10. public Project findByName(String name) {
  11. return projectDao.findByName(name);
  12. }
  13. public Set<Project> findLeadProjectsByUsername(String username) {
  14. return projectDao.findLeadProjectsByUsername(username);
  15. }
  16. public Set<Project> findJoinProjectsByUsername(String username) {
  17. return projectDao.findJoinProjectsByUsername(username);
  18. }
  19. public List<Project> findByBlurProjectName(String name) {
  20. return projectDao.findByBlurProjectName(name);
  21. }

DAO层代码

  1. /**
  2. * 保存项目
  3. *
  4. * @param project
  5. * @throws HibernateException
  6. */
  7. public void saveProject(Project project) throws HibernateException {
  8. // TODO Auto-generated method stub
  9. try {
  10. hibernateTemplate.save(project);
  11. } catch (Exception e) {
  12. e.printStackTrace();
  13. }
  14. }
  15. /**
  16. * 删除项目
  17. *
  18. * @param project
  19. * @throws HibernateException
  20. */
  21. public void removeProject(Project project) throws HibernateException {
  22. try {
  23. hibernateTemplate.delete(project);
  24. } catch (Exception e) {
  25. // TODO: handle exception
  26. e.printStackTrace();
  27. }
  28. }
  29. /**
  30. * 更改项目
  31. *
  32. * @param project
  33. * @throws HibernateException
  34. */
  35. public void modifyProject(Project project) throws HibernateException {
  36. try {
  37. hibernateTemplate.update(project);// 会把这个表中的所有字段更新一遍。
  38. } catch (Exception e) {
  39. // TODO: handle exception
  40. e.printStackTrace();
  41. }
  42. }
  43. /**
  44. * 通过项目名查找项目
  45. *
  46. * @param name
  47. * @return
  48. * @throws HibernateException
  49. */
  50. public Project findByName(String name) throws HibernateException {
  51. List<Project> list = null;
  52. try {
  53. String hql = "from Project where name=?";
  54. list = (List<Project>) hibernateTemplate.find(hql, name);
  55. } catch (Exception e) {
  56. // TODO: handle exception
  57. e.printStackTrace();
  58. }
  59. // hql:from 后面跟的类名+类对象 where后用对象的属性做条件
  60. if (list != null && list.size() > 0) {
  61. return list.get(0);
  62. }
  63. return null;
  64. }
  65. /**
  66. * 通过项目名模糊查找相关项目
  67. *
  68. * @param name
  69. * @return
  70. */
  71. public List<Project> findByBlurProjectName(String name) {
  72. List<Project> list = null;
  73. try {
  74. String hql = "from Project where name like '%" + name + "%'";
  75. list = (List<Project>) hibernateTemplate.find(hql);
  76. } catch (Exception e) {
  77. // TODO: handle exception
  78. e.printStackTrace();
  79. }
  80. if (list != null && list.size() > 0) {
  81. return list;
  82. }
  83. return null;
  84. }
  85. /**
  86. * 通过用户名查找该用户所领导的项目
  87. *
  88. * @param username
  89. * @return
  90. */
  91. public Set<Project> findLeadProjectsByUsername(String username) {
  92. List<Project> list = null;
  93. Set<Project> set = new HashSet<Project>();
  94. try {
  95. String hql = "select p from Project p,User u where p.leader=u and u.username=? ";
  96. list = (List<Project>) hibernateTemplate.find(hql, username);
  97. } catch (Exception e) {
  98. // TODO: handle exception
  99. e.printStackTrace();
  100. }
  101. if (list != null && list.size() > 0) {
  102. for (Project l : list) {
  103. set.add(l);
  104. }
  105. return set;
  106. }
  107. return null;
  108. }
  109. /**
  110. * 通过用户名查找该用户参与的项目集
  111. *
  112. * @param username
  113. * @return
  114. */
  115. public Set<Project> findJoinProjectsByUsername(String username) {
  116. List<Project> list = null;
  117. Set<Project> set = new HashSet<Project>();
  118. try {
  119. String hql = "select p from Project p,User u where p.projectId in elements(u.joinProjects) and u.username=?";
  120. list = (List<Project>) hibernateTemplate.find(hql, username);
  121. } catch (Exception e) {
  122. // TODO: handle exception
  123. e.printStackTrace();
  124. }
  125. if (list != null && list.size() > 0) {
  126. for (Project l : list) {
  127. set.add(l);
  128. }
  129. return set;
  130. }
  131. return null;
  132. }

7.6 任务调度模块

7.6.1 模块功能

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

7.6.2 模块代码

Dispatcher类代码

  1. /**
  2. * 任务调度核心类|| 核心方法为dispatcherCore(project)
  3. */
  4. public class Dispatcher {
  5. public UserManager userManager;
  6. public ProjectManager projectManager;
  7. public JobManager jobManager;
  8. public JobConnectionManager jobConnectionManager;
  9. Map<Integer, JobNode> mapJobNode;// 存储任务结点的Map集合。 在算法中为虚拟任务树
  10. Map<JobNode, JobConnection> mapJobConnectionByJobNode;// 存储任务结点的连接信息.该Map初始化完毕后不用动key为当前结点,value为向下指向该结点的连接信息的集合
  11. // 一个任务结点被分出去后,需要从下面这个Map中删除关于这个结点的连接信息。(需借助上面这个Map)看TA是不是叶子结点来选出备选集
  12. Map<JobNode, List<JobConnection>> mapJobConnectionListByNextJobNode;// 存储任务结点的连接信息.key为当前结点,value为从该结点向下指出去的连接信息的集合
  13. List<WorkerNode> listWorkerNode;// 初始化完成后无需再动
  14. List<JobNode> optionJob;
  15. public Dispatcher() {
  16. // TODO Auto-generated constructor stub
  17. userManager = new UserManagerImpl();
  18. projectManager = new ProjectManagerImpl();
  19. jobManager = new JobManagerImpl();
  20. jobConnectionManager = new JobConnectionManagerImpl();
  21. }
  22. public void dispatcherCore(Project project) {
  23. init(project);
  24. greedy(mapJobNode, listWorkerNode);
  25. }
  26. /**
  27. * 初始化项目和项目参与人员,将其添加至集合中
  28. *
  29. * @param project
  30. */
  31. public void init(Project project) {
  32. Set<Job> setJob = project.getJobs();// 该项目含有的任务的集合
  33. mapJobNode = new HashMap<Integer, JobNode>();// 该项目JobNode的Map集合
  34. mapJobConnectionByJobNode = new HashMap<JobNode, JobConnection>();
  35. mapJobConnectionListByNextJobNode = new HashMap<JobNode, List<JobConnection>>();
  36. for (Job jobs : setJob) {
  37. JobNode jobNode = new JobNode(jobs.getJobId(), jobs.getWeight());
  38. mapJobNode.put(jobs.getJobId(), jobNode);
  39. JobConnection jobConnection = jobConnectionManager.findByJobId(jobs.getJobId());
  40. if (jobConnection != null) {
  41. mapJobConnectionByJobNode.put(jobNode, jobConnection);
  42. }
  43. List<JobConnection> listJobConnectionByNextJob = jobConnectionManager.findListByNextJobId(jobs.getJobId());
  44. if (listJobConnectionByNextJob != null) {
  45. mapJobConnectionListByNextJobNode.put(jobNode, listJobConnectionByNextJob);
  46. }
  47. }
  48. Set<User> setUser = userManager.findJoinerByProjectName(project.getName());// 项目参与者的集合
  49. listWorkerNode = new ArrayList<WorkerNode>();
  50. for (User set : setUser) {
  51. WorkerNode workerNode = new WorkerNode(set.getUserId());
  52. listWorkerNode.add(workerNode);
  53. }
  54. }
  55. public void greedy(Map<Integer, JobNode> mapJobNode, List<WorkerNode> listWorker) {
  56. int sum = 0;
  57. LinkedList<WorkerNode> listWorkerNode = (LinkedList) listWorker;
  58. // 每次循环都对Worker进行一次排序
  59. do {
  60. // 1、从任务树中选出备选任务集
  61. optionJob = selectOptionJob(mapJobNode);
  62. // 2、从备选任务集中选出路径长度最长的任务结点
  63. JobNode nowJobNode = selectLongestJobNode(optionJob);
  64. // 3、先将最长任务结点分配出去
  65. Collections.sort(listWorkerNode);
  66. WorkerNode nowWorkerNode = listWorkerNode.peek();
  67. System.out.println("将组员" + nowWorkerNode + "从第" + nowWorkerNode.getAvail() + "天到第"
  68. + (nowWorkerNode.getAvail() + nowJobNode.getDay()) + "天的时间段分配给任务" + nowJobNode.getId());
  69. nowWorkerNode.setAvail(nowWorkerNode.getAvail() + nowJobNode.getDay());
  70. // 4、删除该任务结点
  71. deleteJobNode(nowJobNode);
  72. } while (optionJob.size() != 0);
  73. }
  74. /**
  75. * 删除JobNode
  76. *
  77. * @param jobNode
  78. */
  79. public void deleteJobNode(JobNode jobNode) {
  80. // 4、将已分配到组员的任务删除分3步 :1.从备选任务集中删除 2.从任务树中删除 3.删除该结点相关的连接
  81. optionJob.remove(jobNode);
  82. mapJobNode.remove(jobNode.getId());
  83. // 删除该结点相关连接又分3步:1、获得该结点连接 2、获得该结点后继结点的map V值 3、从该V值中删除该结点连接
  84. JobConnection jobConnection = mapJobConnectionByJobNode.get(jobNode);
  85. List<JobConnection> waitRemove = mapJobConnectionListByNextJobNode.get(jobConnection.getNextJob());
  86. waitRemove.remove(jobConnection);
  87. }
  88. /**
  89. * 从任务树中选出备选任务集
  90. *
  91. * @param map
  92. * @return
  93. */
  94. public List<JobNode> selectOptionJob(Map<Integer, JobNode> map) {
  95. List<JobNode> list = new ArrayList<JobNode>();
  96. for (JobNode values : map.values()) {
  97. if (isLeaf(values)) {// 如果是叶子结点
  98. list.add(values);
  99. }
  100. }
  101. return list;
  102. }
  103. /**
  104. * 判断是否为叶子结点
  105. *
  106. * @param jobNode
  107. * @return
  108. */
  109. public boolean isLeaf(JobNode jobNode) {
  110. if (!mapJobConnectionListByNextJobNode.get(jobNode).isEmpty()) {
  111. return false;
  112. }
  113. return true;
  114. }
  115. /**
  116. * 从备选任务集中选出路径长度最长的任务
  117. *
  118. * @param optionJobNode
  119. * @return
  120. */
  121. public JobNode selectLongestJobNode(List<JobNode> optionJobNode) {
  122. // 此时给一个函数计算路径
  123. JobNode longestJobNode = null;
  124. int max = 0;
  125. for (JobNode list : optionJobNode) {
  126. int nowLength = calculatePath(list);
  127. if (nowLength >= max) {
  128. max = nowLength;
  129. longestJobNode = list;
  130. }
  131. }
  132. return longestJobNode;
  133. }
  134. /**
  135. * 计算给出任务结点的路径长度
  136. *
  137. * @param jobNode
  138. * @return
  139. */
  140. public int calculatePath(JobNode jobNode) {
  141. int pathLength = 0;
  142. JobConnection jobConnection = mapJobConnectionByJobNode.get(jobNode);
  143. while (jobConnection != null) {
  144. jobNode = mapJobNode.get(jobConnection.getNextJob());
  145. pathLength++;
  146. }
  147. return pathLength;
  148. }
  149. }

JobNode类代码

  1. public class JobNode implements Comparable<JobNode> {
  2. private Integer id;// 真实ID
  3. private Integer day;
  4. public JobNode(Integer id, Integer day) {
  5. // TODO Auto-generated constructor stub
  6. this.id = id;
  7. this.day = day;
  8. }
  9. @Override
  10. public boolean equals(Object obj) {
  11. // TODO Auto-generated method stub
  12. if (obj == null) {
  13. return false;
  14. } else if (obj instanceof JobNode) {
  15. JobNode j = (JobNode) obj;
  16. if (this.id == j.getId() && this.day == j.getDay()) {
  17. return true;
  18. }
  19. }
  20. return false;
  21. }

WorkerNode类代码

  1. package com.fcq.schedule.job.core;
  2. /**
  3. * 用来简化User类
  4. * @author 撒旦的奶爸
  5. *
  6. */
  7. public class WorkerNode implements Comparable<WorkerNode> {
  8. private Integer id;// 真实ID
  9. private Integer avail;// worker空闲的时刻(即worker做完某一项工作的时间)
  10. public WorkerNode(Integer id) {
  11. this.id = id;
  12. this.avail = 0;
  13. }
  14. @Override
  15. public int compareTo(WorkerNode o) {
  16. int m = o.getAvail();
  17. if (avail < m)
  18. return -1;
  19. if (avail == m)
  20. return 0;
  21. return 1;
  22. }
  23. @Override
  24. public boolean equals(Object obj) {
  25. if (obj == null) {
  26. return false;
  27. } else if (obj instanceof WorkerNode) {
  28. WorkerNode j = (WorkerNode) obj;
  29. if (this.id == j.getId()) {
  30. return true;
  31. }
  32. }
  33. return false;
  34. }
  35. }

参考文献

[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.

上传的附件 cloud_download 基于SSH的任务调度系统的设计与实现.zip ( 20.17mb, 1次下载 )
error_outline 下载需要14点积分

发送私信

18
文章数
0
评论数
最近文章
eject