




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
OSWorkflow工作流引擎技术GWI
湖南长城信息金融设备有限责任公司主讲:孙家跃时间:2011年07月25日地点:长城信息办公楼OSWorkflow工作流引擎技术GWI湖南长城信息1主要内容工作流的基本概念什么是工作流工作流技术的起源与发展工作流的发展历程工作流技术的具体应用工作流的主要应用方向工作流管理系统工作流管理系统的解说工作流技术中存在的问题有那些问题存在OSWorkflow工作流引擎是一个”低端”工作流实现主要内容工作流的基本概念什么是工作流工作流技术的起源与发展工2工作流的概念工作流(WorkFlow)就是工作流程的计算模型,即将工作流程中的工作如何前后组织在一起的逻辑和规则在计算机中以恰当的模型进行表示并对其实施计算。工作流要解决的主要问题是:为实现某个业务目标,在多个参与者之间,利用计算机,按某种预定规则自动传递文档、信息或者任务。
简单地说,工作流就是一系列相互衔接、自动进行的业务活动或任务。
工作流的概念工作流(WorkFlow)就是工作流程的计算模3OSWorkFlow工作流引擎技术培训4OSWorkFlow工作流引擎技术培训5三大主流工作流引擎技术Jbpm工作流引擎 Jbpm的靠山是jboss。Jbpm3和JBPM4的持久层采用hibernate3来实现。Jbpm3的图形化流程定义通过嵌入到jbosseclipseIDE中实现图形化编辑。 JBPM对工作流中所需的各种应用提供很好的支持为开发应用提供方便,但JBPM的流程定义GPD插件与Eclipse支持不完善,目前jbpm4版本只支持Eclipse4.3版本,Jboss组织整合的IDE工具RedHatDeveloperStudio又为收费软件. JBPM应用前景被行业内人士很看好,被誉为顶替Shark和Osworkflow的新一代工作流引擎.JBPM4.0版本目前还是阿尔发版,还没有发展成为稳定的发布版本,并且现在一直在不停的重构,目前还不便于极力推广应用,而JBPM4.0较之JBPM3.0又做了很大的改进和变动,转而使用JBPM3.0有点得不偿失.JBPM4.0相关技术应用和文档支持都还不够,使用该框架还有待时日,需要静观其变.三大主流工作流引擎技术Jbpm工作流引擎6三大主流工作流引擎技术Osworkflow工作流引擎 Osworkflow是完全用java语言编写的开放源代码的工作流引擎,具有显著的灵活性及完全面向有技术背景的用户的特点。用户可以根据自身的需求利用这款开源软件设计简单或是复杂的工作流。通过使用,用户就可以把工作中心放在业务和规则的定义上,而不需通过硬编码的方式实现。用户可以以最小的代价把osworkflow整合到自己的程序中来。三大主流工作流引擎技术Osworkflow工作流引擎7工作流技术的具体应用工作流特殊服务类:质量管理对应流程、产品数据信息管理等各种通过表单逐步手工流转完成的任务均可应用工作流软件自动规范地实施。
关键业务流程:订单处理、报价处理、采购处理、合同审核、客户电话处理等客户服务类:客户信息管理、客户投诉、请求处理、售后服务管理等管理等。
财务相关类:付款请求、应收款处理、日常报销处理、出差报销、预算和计划申请等。行政管理类:出差申请、加班申请、请假申请、用车申请、购买申请、日报周报等凡是原来手工流转处理的行政表单。人事管理类:员工培训安排、绩效考评、职位变动处理、员工档案信息管理等。
工作流技术的具体应用工作流特殊服务类:关键业务流程:客户服务8工作流管理系统工作流管理系统定义工作流管理系统功能工作流管理系统分类工作流管理系统工作流管理系统参考模型工作流管理系统工作流管理系统定义工作流管理系统功能工作流管理9工作流管理系统的定义WFMC给出的工作流管理系统的定义是:“工作流管理系统是一个软件系统,它完成工作流的定义和管理,并按照在计算机中预先定义好的工作流逻辑推进工作流实例的执行”。通常,工作流管理系统指运行在一个或多个称为工作流引擎的软件上的用于定义、实现和管理工作流运行的一套软件系统,它和工作流执行者(人、应用)交互,推进工作流实例的执行,并监控工作流的运行状态。工作流管理系统的定义WFMC给出的工作流管理系统的定义是:“10工作流管理系统功能1建立功能:对工作流过程及其组成活动定义和建模3运行交互功能:指在工作流运行中,与用户(业务工作的参与者或控制者)及外部应用程序工具交互的功能2运行控制功能:在运行环境中管理工作流过程,对工作流过程中的活动进行调度工作流管理系统是定义、创建、执行工作流的系统。在最高层上,工作流管理系统应能提供以下三个方面的功能支持:工作流管理系统功能1建立功能:3运行交互功能:2运行控制功能11工作流管理系统分类根据用途和所实现的业务流程的特点的不同,可分为以下四种类型:协同型工作流:主要由参与者的交互参与刻画,参与者协作次数比较多,不像其他类型工作流总是向前流转,它还包括循环流和反向流,例如:协同编辑特定型工作流:由若干非自动化的任务组成,多用于处理异常或发生机会比较小的情况。工作流的执行要求在一个工作流任务执行的同时决定下一个执行的任务和执行者,能够提供合作协同功能,但不控制工作顺序。管理型工作流:由较为结构化和可预见的流程组成,用于执行简单协同规则的可重复和可预测的流程,它的执行步骤和规则是事先定义的,不要求控制复杂流程和访问多个信息系统,例如:学位申请、车辆登记等。生产型工作流:工作流的高级类型,实现重要业务流程的工作流,特别是与业务组织的功能直接相关的工作流,关系到组织的功能。与管理型工作流相比,生产型工作流一般应用在大规模、复杂的和异构的环境下,整个流程涉及许多不同的任务、人和组织。工作流管理系统分类根据用途和所实现的业务流程的特点的不同,可12工作流管理系统参考模型流程定义工具工作流机工作流客户应用工作流引擎直接调用的应用工作流管理工具工作流机接口1接口2接口3接口4接口5其他工作流执行任务工作流API与交换格式工作流执行任务工作流管理系统参考模型流程定义工具工作流机工作流客户应用工作13工作流技术中存在的问题不同的厂商所提供的工作流产品具有独立的一套工作流模型、工作流定义语言、API函数。但难于在不同系统之间进行交互,集成的效果不理想,不能方便地在不同系统间进行应用对象的重复利用和数据的方便交流。目前,大多数工作流产品的生产厂家己经意识到这个问题,他们加入了工作流管理联盟并提出了一套工作流管理系统的标准。工作流管理系统没有达到真正的集成,还是自己独立地运行,处理一些行政上简单的流程业务,不能很好将OA、ERP、CRM、SCM等具体事务处理系统紧密地联系在一起,达到数据录入一次即可有效的目的。实施一个完整的工作流管理系统,是一个复杂的过程,要了解其他应用系统的业务,进行流程处理分析、业务流程改造、管理规程和操作规范建立等,并且还必须有不同软件供应商的全力配合。系统中对于并发访问和异常错误缺乏正确和可靠的支持。一旦系统出现非正常退出,如何恢复数据并保证数据的一致性还需要解决。工作流管理系统必须建立在底层通信的基础上,才能实现分布计算,这要额外付出经费和精力进行构筑,这是企业所不希望的,从而限制了在企业中的广泛应用。工作流底层环境的建立系统的安全性实现的复杂性系统集成性不理想标准化程度差工作流技术中存在的问题不同的厂商所提供的工作流产品具有独立的14OSWorkflow简介OSWorkflow都不同于这些已有的工作流系统。最大不同在于OSWorkflow有要求图形化工具来开发工作流,而推荐手工编写xml格式的工作流程描述符。它能为应用的代码和数据库进行集成。这一切似乎给正在寻找快速“即插即用”工作流解决方案的人制造了麻烦,但研究发现,那些“即插即用”方案也不能在一个成熟的应用程序中提供足够的灵活性来实现所有需求。OSWorkflow基于有限状态机概念。每个state(状态)由stepID和status(状态)联合表现(可简单理解为step及其status表示有限状态机的state)。一个state到另一state的transition(过度)依赖于action的发生,在工作流生命期内有至少一个或多个活动的state。Osworkflow几乎提供了所有用户可能在实际流程定义中需要用到的工作流构成元素,如:环节(step)、条件(conditions)、循环(loops)、分支(spilts)、合并(joins)、角色(roles)等等OSWorkflow简介OSWorkflow都不同于这些已15所需JAR包OSWorkflow自身(%osworkflow解压包%\):
osworkflow-2.8.0.jarOSWorkflow核心引用包(%osworkflow解压包%\lib\core):
commons-logging.jar:必要,支持日志。
propertyset-1.4.jar:必要,支持propertyset的aggregate,cached,memory,jdbc,file,javabeans,map,xml接口实现,并不支持hibernate3,如果要支持hibernate3,要自己写代码。这个下面再谈。
oscore-2.2.5.jar:必要,提供了一些工具等。OSWorkflow可选包(%osworkflow解压包%\lib\optional):
bsf.jar:支持bsf,可选。
bsh-1.2b7.jar:支持beanshell,可选。
ehcache.jar:支持缓存,可选。
osuser-1.0-dev-2Feb05.jar:支持例子里面的用户和群组管理,在涉及到用户和群组的操作建议加上此包。spring2所需的包(%spring解压包%\dist):
spring.jar(version:2.05)Hibernate3所需的包(%hibernate解压包%\lib):
antlr.jar;cglib.jar;asm.jar;asm-attrs.jars;commons-collections.jar;hibernate3.jar;jta.jar;dom4j.jar;log4j.jar所需JAR包OSWorkflow自身(%osworkflow16OSWorkflow核心概念
一个工作流包含多个步骤。每一个步骤都有一个当前状态(例如,Underway(进行中)、Queued(等候处理中)、Finished(完成))。每一个步骤中都有一个或者多个动作可以被执行。每一个动作都可以设置执行条件(condition),也可以设置执行函数(pre-functionorpost-function)。动作产生结果(result),导致工作流的状态和当前步骤发生改变。OSWorkflow核心概念一个工作流包含多个17OSWorkflow核心概念step(步骤):
一个step是工作流所处的位置。可能从一个step流转到另外一个step(或者有时候还是停留在一样的step)。举例来说,一个OA系统的请假流程,它的step名称可能有“本部门审批阶段”,“办公室审批阶段”,“总经理审批阶段”等。
status(状态):
工作流status是一个用来描述工作流程中具体步骤状态的字符串。OSWorkflow的有Underway(进行中)、Queued(等候处理中)、Finished(完成)三种status。工作流Status是用来描述工作流程中具体Step(步骤)状态的字符串。一个实际State(状态)真正是由两部分组成:State=(Step+Status)。
action(动作):
action指定了可能发生在step内的转变,会导致step的变更。在OA系统中,“本部门审批阶段”可能有“拒绝”或“批准”两个action。action和step之间的关系是,step说明“在哪里”,action说明“可以去哪里”。一个action典型地由两部分组成:可以执行此动作的condition(条件),以及执行此动作的result(结果)。
OSWorkflow核心概念step(步骤):18OSWorkflow核心概念condition(条件):
类似于逻辑判断,可包含“AND”和“OR”逻辑。比如一个请假流程中的“本部门审批阶段”,该阶段利用“AND”逻辑,判断流程状态是否为等候处理中,以及审批者是否为本部门主管。
result(结果):
Result代表指向新的step及其stepstatus,也可能进入split或者join。Result分为两种,contidional-result(有条件结果),只有条件为真时才使用该结果,和unconditional-result(无条件结果),当条件不满足或没有条件时使用该结果。split/join(分离/连接):
流程的切分和融合。很简单的概念,split提供多个result;join则判断多个currentstep的状态,提供一个result。OSWorkflow核心概念condition(条件):
19工作流程描述一个工作流(workflow)由多个步骤(step)来表示流程(flow)。每个步骤有一个或者多个动作,一个动作可以被设置成为是否自动执行,或者通过与用户的交互来由程序选择执行。每一个动作至少有一个无条件结果(unconditionalresult)和零到多个有条件的结果(conditionalresult)如果定义了多个conditionalresult,第一个符合所有条件的result将会被执行,如果没有定义conditonalresults或者没有符合的conditions(条件),就会执行unconditionalresult。执行完当前步骤,它可能会停留在当前步骤,跳转到另一个新的步骤,或者是一个split,或者是一个join中去。以上所有的情况下,workflow的的状态可以随之改变(例如状态是Underway,Quened,Finished)。如果一个动作执行的result(结果)是一个分支(split),result中的split属性会指向splits元素中定义的一个split元素。工作流程描述一个工作流(workflow)由多个步骤(ste20工作流程描述一个分支可以有一个或者多个无条件结果,但不会有条件结果。这些结果指向来自于split里面的步骤。注册器(register)是一个全局变量,它在工作流运行时被解析,可以被每个function和condition使用propertyset是全局范围的持久数据集合(——译者注:如果用数据库存储,它为os_propertyentry表。)transientVars是一个保存临时数据的Map对象,它应用于所有的functions和conditons。这个transientVars里面包括所有的registers(全局变量),用户输入,以及当前工作流的上下文和状态。它仅在一次工作流调用的生命周期中存在。工作流程描述一个分支可以有一个或者多个无条件结果,但不会有条21OSWorkflow核心代码剖析osworkflow.xml加载过程WorkflowDescriptor对象加载过程、WorkflowStore对象加载过程Workflow接口中的核心方法OSWorkflow核心代码剖析osworkflow.xml22osworkflow.xml加载过程osworkflow.xml加载过程 1、在AbatractWorkflow中的getConfiguration()方法调用了Configuration中的load(null)方法 2、Configuration中的load(null)方法调用了getInputStream()方法。getInputStream()方法里面加载osworkflow.xmlosworkflow.xml加载过程osworkflow.x23WorkflowDescriptor对象加载过程WorkflowDescriptor对象加载过程
1、首先在Workflow接口中getWorkflowDescriptor(StringworkflowName)方法调用Configuration对象中的getWorkflow(workflowName)方法。 2、Configuration对象调用factory中的getWorkflow(name)方法。 3、factory中的getWorkflow(name)方法调用同类中的getWorkflow(name,true)方法。 4、getWorkflow(name,true)方法首先用name参数取得WorkflowConfig对象,这个WorkflowConfig对象在factory初始化的时候已经被生成了。紧接着调用loadWorkflow(c,validate)方法去解析XML并最终生成WorkflowDescriptor对象。WorkflowDescriptor对象加载过程Workfl24WorkflowStore对象加载过程WorkflowStore对象加载过程
1、首先AbatractWorkflow中的getPersistence()方法调用Configuration对象中的getWorkflowStore()方法。 2、如果store为空,从预先用load(URLurl)加载的persistenceClass中取得实现类,然后再创建新的实例并初始化参数,最后返回WorkflowStore对象WorkflowStore对象加载过程WorkflowSto25Workflow接口中的核心方法1、initialize方法
初始化方法主要完成了以下几个功能 得到WorkflowStore实现类,利用里面的createEntry方法创建一个WorkflowEntry对象。 执行populateTransientMap方法,将context(WorkflowContext),entry(WorkflowEntry),store(WorkflowStore),configuration(Configuration),descriptor(WorkflowDescriptor)装进transientVars;将当前要执行的actionId和currentSteps装进transientVars;将所有XML中配置的register装进transientVars。 根据restrict-to里面配置的条件来判断是否能初始化工作流,如果不能则回滚并抛出InvalidRoleException异常。 执行transitionWorkflow方法传递工作流,这个transitionWorkflow方法是Workflow中重中之重的方法,以下会进行详细讲解。 返回当前工作流程实例ID。Workflow接口中的核心方法1、initialize方法26Workflow接口中的核心方法transitionWorkflow方法
transitionWorkflow方法是工作流最最核心的方法,它主要是完成以下功能
�
利用getCurrentStep方法取得当前步骤:如果只有一个有效当前步骤,直接返回;如果有多个有效当前步骤,返回符合条件的第一个。
�
调用动作验证器来验证transientVars里面的变量。
�
执行当前步骤中的所有post-function。
执行当前动作中的所有pre-function。
检查当前动作中的所有有条件结果,如果有符合条件的,验证transientVars里面的变量并执行有条件结果里面的pre-function;如果动作里面没有一个有条件结果,执行无条件结果,验证transientVars里面的变量并执行无条件结果里面的pre-function。
如果程序进入到一个split中:
1)验证transientVars里面的变量;
2)执行split中的pre-functions;
3)如果动作中的finish不等于true,执行split中所有的result;
4)结束当前步骤并将其移至历史步骤中去,创建新的步骤并执行新步骤中的pre-function;
5)执行split中的post-function。Workflow接口中的核心方法transitionWork27Workflow接口中的核心方法如果程序进入到一个join中:
1)结束当前步骤并将其移至历史步骤中去;
2)将刚结束的步骤和在join中的当前步骤还有历史步骤加到joinSteps集合中并产生JoinNodes对象,将此对象put到transientVars里;
3)检查join条件;
4)执行join有条件结果中的validator;
5)执行join有条件结果中的pre-function;
6)如果当前步骤不在历史步骤里面,把它移到历史步骤里面去;
7)如果刚刚结束的当前动作中的finish不等于true,创建新的步骤并执行新步骤中的pre-function;
8)执行join中的post-function。如果程序进入到另一个step中:结束当前步骤并将其移至历史步骤中去,创建新的步骤并执行新步骤中的pre-function。如果动作里面有符合条件的有条件结果,执行有条件结果里面的post-function;如果动作里面没有一个有条件结果,则执行无条件结果里面的post-function。执行动作里面的post-function。如果动作一开始是一个初始状态,将设置ACTIVATED标识;如果动作在XML里面有完成状态的标识,将设置COMPLETED标识。执行有效的自动动作(autoaction)。最后返回流程是否完成的布尔值:如果流程实例已经完结,返回true;否则返回falseWorkflow接口中的核心方法如果程序进入到一个jo28Workflow接口中的核心方法doAction方法判断工作流程实例的状态,如果状态不为ACTIVATED(1),直接返回。利用findCurrentSteps方法得到当前所有步骤列表。执行populateTransientMap方法,将context(WorkflowContext),entry(WorkflowEntry),store(WorkflowStore),configuration(Configuration),descriptor(WorkflowDescriptor)装进transientVars;将当前要执行的actionId和currentSteps装进transientVars;将所有XML中配置的register装进transientVars。检查全局动作(GlobalAction)和当前步骤里面所有动作的有效性。如果有无效动作,直接抛出InvalidActionException异常。执行transitionWorkflow方法传递工作流,如果捕获到WorkflowException,抛出异常并回滚。如果动作中没有显式地标明finish的状态为true,那么这时要执行checkImplicitFinish方法,查找当前步骤中是否还有有效动作,如果没有一个有效动作,则直接调用completeEntry方法结束流程并将流程的状态设置成为COMPLETED(4)。Workflow接口中的核心方法doAction方法29主要配置文件osworkflow.xml
这个档案是设定流程是否存在资料库或存在记忆体workflows.xml 指定系统启动时要载入那些流程。example.xml 对工作流程进行是设计定义osuser.xml 对用户管理propertyset.xml 持久化到数据库需要用到该配置文件加载OS_PROPERTYENTRY表主要配置文件osworkflow.xml30osworkflow.xml<osworkflow> <persistenceclass="com.opensymphony.workflow.spi.jdbc.MySQLWorkflowStore"> <!--Forjdbcpersistence,allarerequired.--> <propertykey="datasource"value="java:comp/env/jdbc/oswf"/> <!--mysql--> <propertykey="entry.sequence"value="SELECTmax(ID)+1FROMOS_WFENTRY"/> <propertykey="step.sequence"value="SELECTmax(ID)+1FROMOS_STEPIDS"/> <propertykey="entry.table"value="OS_WFENTRY"/> <propertykey="entry.id"value="ID"/> <propertykey=""value="NAME"/> <propertykey="entry.state"value="STATE"/> <propertykey="history.table"value="OS_HISTORYSTEP"/> <propertykey="current.table"value="OS_CURRENTSTEP"/> <propertykey="historyPrev.table"value="OS_HISTORYSTEP_PREV"/> <propertykey="currentPrev.table"value="OS_CURRENTSTEP_PREV"/> <propertykey="step.id"value="ID"/> <propertykey="step.entryId"value="ENTRY_ID"/> <propertykey="step.stepId"value="STEP_ID"/> <propertykey="step.actionId"value="ACTION_ID"/> <propertykey="step.owner"value="OWNER"/> <propertykey="step.caller"value="CALLER"/> <propertykey="step.startDate"value="START_DATE"/> <propertykey="step.finishDate"value="FINISH_DATE"/> <propertykey="step.dueDate"value="DUE_DATE"/> <propertykey="step.status"value="STATUS"/> <propertykey="step.previousId"value="PREVIOUS_ID"/> <!--mysql特殊配置--> <propertykey="step.sequence.increment"value="INSERTINTOOS_STEPIDS(ID)values(null)"/> <propertykey="step.sequence.retrieve"value="SELECTmax(ID)FROMOS_STEPIDS"/> <propertykey="entry.sequence.increment"value="INSERTINTOOS_ENTRYIDS(ID)values(null)"/> <propertykey="entry.sequence.retrieve"value="SELECTmax(ID)FROMOS_ENTRYIDS"/> </persistence> <factoryclass="com.opensymphony.workflow.loader.XMLWorkflowFactory"> <propertykey="resource"value="workflows.xml"/> </factory></osworkflow>osworkflow.xml<osworkflow>31workflows.xml<workflows>
<workflowname="leave_apply"type="resource"location="example1.xml"/><workflowname="leave_apply"type="resource"location="example2.xml"/><workflowname="leave_apply"type="resource"location="example3.xml"/><workflowname="leave_apply"type="resource"location="example4.xml"/></workflows>workflows.xml<workflows>32example.xmlinitial-actions:每个流程都至少需定义一个initial-actions,这是流程的起点。action:导致流程变动的动作,每个action都有个编号,且不能重复。step:虽然它的名称是步骤,似乎它会有动作?其实将它视为流程位置可能比较恰当,osworkflow真正的动作在action发生。result:执行动作后的结果,result有两种conditional-result和unconditional-result,每个result一定有unconditional-result,当conditional-result的条件都不满足时,就执行unconditional-result。status:流程在某个action时的状态。old-status:流程执行某个action后的状态。caller:这是OSWorkflow的保留字,可取得呼叫此工作流的user,即Workflowworkflow=newBasicWorkflow(caller);example.xmlinitial-actions:每个流33一个完整的流程定义文件:example.xmlStep的定义步骤1【可以多次进行acction=1的操作,acction=1保持当前步骤不变,只是改变状态】<stepid="1"name="FirstDraft"> <actions> <actionid=“1”name=“开始撰写草稿"> <results> <unconditional-resultold-status="Finished"status="Underway"step="1"/></results></action><actionid=“2”name=“完成草稿"><results><unconditional-resultold-status="Finished"status="Queued"step="2"/></results></action></actions></step>步骤2<stepid="2"name="finished"/>一个完整的流程定义文件:example.xmlStep的定义34一个完整的流程定义文件:example.xml条件(Condition)的使用<actionid="1"name="StartFirstDraft"> <restrict-to> <conditionstype=“AND“>----type=“OR”就是”或“的关系 <conditiontype="class"> <argname=""> com.opensymphony.workflow.util.StatusCondition </arg><argname="status">Queued</arg></condition></conditions></restrict-to><results><unconditional-resultold-status="Finished"status="Underway"step="1"/></results></action>可以自己实现Condition类来做验证[继承com.opensymphon
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 山西中文专业素养试题及答案
- 检查员招聘岗位面试题及答案
- 2025年老年护理师职业考试题及答案
- java面试题及答案事务2025年
- 北京携宁科技java面试题及答案
- 福州兴业java面试题及答案
- 关键考点软件设计师考试试题及答案
- 药学专业知识与药品管理实践题库
- 经济学微观经济学概念与运用试题集
- 软件设计师考试实践试题及答案汇综
- 2024年湖南出版中南传媒招聘笔试真题
- 【初中地理】七年级地理下册全册期末总复习(课件)-2024-2025学年七年级地理课件(人教版2024年)
- 办公楼安全培训
- JT∕T 402-2016 公路货运站站级标准及建设要求
- 林芝工布书画院建筑及景观工程项目
- QC提高老年患者静脉留置针一次穿刺成功率
- GB/T 7233.1-2009铸钢件超声检测第1部分:一般用途铸钢件
- GB/T 545-1996海军锚
- GB/T 22080-2016信息技术安全技术信息安全管理体系要求
- 汤谷良全面预算整合企业管理
- iFIAE全自动多参数流动分析仪使用说明书-20201110doc
评论
0/150
提交评论