- 浏览: 206730 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
小月峰:
AppInitServlet 26行,取到的值为null,提示 ...
完整工作流JBPM项目实战全过程教程2---项目详细讲解 -
电竞杀神张无忌:
楼主可以留个联系方式?有问题要问你。
完整工作流JBPM项目实战全过程教程2---项目详细讲解 -
lvjingtao2005:
挺好学习了,继续关注
完整工作流JBPM项目实战全过程教程3----项目后续DIY -
lvjingtao2005:
...
完整工作流JBPM项目实战全过程教程3----项目后续DIY -
hello-world-1314:
折腾了两天 终于跑通了
完整工作流JBPM项目实战全过程教程2---项目详细讲解
继续上一篇。
当数据库建立完成后,下载源代码,部署到服务器后,即可以开始体验完整的JBPM+SSH应用了。
项目采用的是ssh+jbpm开发模式,而且,项目功能比较齐全,代码量比较大,所以,本教程就不介绍开发过程了。
如果你对SSH整合开发应用已经够熟悉了的话,相信本项目对你来说将并不会有多大难度 。
下面我们把重点放在JBPM上。当然你得先把项目部署成功,才好边做边理解jbpm是怎么在项目中管理流程的。
ok,假定你已经把项目跑起来了吧。
先以管理员manager登录系统,管理员具有添加新文章类型的权限。当你添加一个文章类型后,需要指定该类型的文章到时候是按哪个流程来进行审批的。你需要上传一个zip格式的流程定义文件文件(其中压缩了gpd.xml,processdifinition.xml,和processimage.jpg)。点击发布,系统转到articletypeaddsub.do,执行ArticleTypeAddSubAction.java
......
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
........
/**
*
* 增加文章类型操作Action类
*
* @struts.action path="/articletypeaddsub" scope="request" validate="false"
*/
public class ArticleTypeAddSubAction extends Action {
private static final Log log = LogFactory.getLog(MainAction.class);
/**
* JBPM服务接口实现对象
*/
private JbpmConfiguration jbpmConfiguration; //参见spring的配置文件applicationContext.xml
/**
* 文章类型服务接口实现对象
*/
private ArticleTypeService articleTypeService;
/**
* Method execute
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
*/
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
log.debug("MainAction.execute()");
UploadDeployForm theForm = (UploadDeployForm) form;
FormFile file = theForm.getFiles();// 取得上传的文件
//得到JBPM环境
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
//解压zip文件流
ZipInputStream zipInputStream = new ZipInputStream(file
.getInputStream());
ProcessDefinition processDefinition = ProcessDefinition
.parseParZipInputStream(zipInputStream);
//发布流程文件
jbpmContext.deployProcessDefinition(processDefinition);
jbpmContext.close();
zipInputStream.close();
//增加文章类型
ArticleType articleType = new ArticleType();
articleType.setPdName(processDefinition.getName());
articleType.setTypeName(theForm.getTypeName());
articleTypeService.addArticleType(articleType);
} catch (IOException e) {
log.error("exception", e);
}
request.setAttribute("success","发布成功");
return mapping.findForward("success");
}
/**
* 得到JBPM服务接口实现对象
* @return jbpmConfiguration
*/
public JbpmConfiguration getJbpmConfiguration() {
return jbpmConfiguration;
}
/**
* 设置JBPM服务接口实现对象
* @param jbpmConfiguration
* 要设置的 jbpmConfiguration
*/
public void setJbpmConfiguration(JbpmConfiguration jbpmConfiguration) {
this.jbpmConfiguration = jbpmConfiguration;
}
/**
* 得到文章类型服务接口实现对象
* @return articleTypeService
*/
public ArticleTypeService getArticleTypeService() {
return articleTypeService;
}
/**
* 设置文章类型服务接口实现对象
* @param articleTypeService 要设置的 articleTypeService
*/
public void setArticleTypeService(ArticleTypeService articleTypeService) {
this.articleTypeService = articleTypeService;
}
}
执行到这步后,你可以去查看下数据库中表jbpm_processdifinition,你会发现表中多出里一条记录,并且名字就是你上传的压缩文件中processdifinition.xml中的name属性的值。其他的表也会有相应的变化,具体看字段的定义就会大概明白了。
好了,流程已经发布到了系统中了。当然你还可以增加其他的文章类型并且指定不同的流程定义。
我们退出系统,以guest用户登录系统,然后编写文章,这里需要说明的是,当你选择不同的文章类型后,该文章的审批过程就会与你刚才定义的执行流程相关了。
点击保存,
系统调用的ACTION为:
MyArticleAddSubAction.java
.........
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
........
/**
*
* 撰写文章操作Action类
* @struts.action path="/myarticleaddsub" scope="request" validate="false"
*/
public class MyArticleAddSubAction extends Action{
private static final Log log = LogFactory.getLog(MyArticleAddSubAction.class);
/**
* 文章服务接口实现对象
*/
private ArticleService articleService;
/**
* 文章类型服务接口实现对象
*/
private ArticleTypeService articleTypeService;
/**
* JBPM服务接口实现对象
*/
private JbpmConfiguration jbpmConfiguration;
/**
* Method execute
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
*/
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
log.debug("MyArticleAction.execute()");
UserSession userSesssion = UserSession.getSession(request, response);
//得到文章信息
String stypeNo = request.getParameter("typeNo");
int typeNo = ConvertUtil.convertInt(stypeNo);
String articleName = request.getParameter("articleName");
String content = request.getParameter("content");
Article article = new Article();
article.setArticleName(articleName);
article.setContent(content);
article.setState(Article.EDITED);
article.setTypeNo(new Integer(typeNo));
article.setUserNo(new Integer(userSesssion.getUserNo()));
//得到相应的文章类型
ArticleType articleType = articleTypeService.getArticleType(article.getTypeNo().intValue());
//得到相应的流程定义,启动流程实例
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
ProcessDefinition processDefinition = jbpmContext.getGraphSession().findLatestProcessDefinition(articleType.getPdName());
ProcessInstance processInstance = new ProcessInstance(processDefinition);
//让流程往下进行一步
Token token = processInstance.getRootToken();
token.signal();
//保存流程实例与状态
jbpmContext.save(processInstance);
jbpmContext.save(token);
jbpmContext.close();
article.setPiId(processInstance.getId());
//增加文章
articleService.addArticle(article);
return mapping.findForward("success");
}
/**
* 得到文章服务接口实现对象
* @return articleService
*/
public ArticleService getArticleService() {
return articleService;
}
/**
* 设置文章服务接口实现对象
* @param articleService 要设置的 articleService
*/
public void setArticleService(ArticleService articleService) {
this.articleService = articleService;
}
/**
* 得到文章类型服务接口实现对象
* @return articleTypeService
*/
public ArticleTypeService getArticleTypeService() {
return articleTypeService;
}
/**
* 设置文章类型服务接口实现对象
* @param articleTypeService 要设置的 articleTypeService
*/
public void setArticleTypeService(ArticleTypeService articleTypeService) {
this.articleTypeService = articleTypeService;
}
/**
* 得到JBPM服务接口实现对象
* @return jbpmConfiguration
*/
public JbpmConfiguration getJbpmConfiguration() {
return jbpmConfiguration;
}
/**
* 设置JBPM服务接口实现对象
* @param jbpmConfiguration 要设置的 jbpmConfiguration
*/
public void setJbpmConfiguration(JbpmConfiguration jbpmConfiguration) {
this.jbpmConfiguration = jbpmConfiguration;
}
}
执行该action后,则就创建了一个与之匹配的流程实例。
查看数据库中article表的变化。可以发现
PiId记录了一个数字编号,同时jbpm_processinstance表中最大的一个id号与之匹配,这说明当保存文章时,系统后台创建了一个流程实例,该流程实例就是记录该文章的审批过程的JBPM实例。(你可以运行一个文章的审批全过程来跟踪与之匹配的流程实例变化情况)。
下一步就是发布该文章了。
到你的文章列表中点击“发布”。
系统调用ACTION:MyArticlePubAction.java继而转到MyArticlePubSubAction.java
.......
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.Transition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
.........
/**
*
* 发布文章操作Action类
* @struts.action path="/myarticle" scope="request" validate="false"
*/
public class MyArticlePubAction extends Action{
private static final Log log = LogFactory.getLog(MyArticlePubAction.class);
private ArticleService articleService;
private ArticleTypeService articleTypeService;
private JbpmConfiguration jbpmConfiguration;
/**
* Method execute
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
*/
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
log.debug("MyArticleAction.execute()");
UserSession userSesssion = UserSession.getSession(request, response);
//得到文章信息
//得到文章号
String sarticleNo = request.getParameter("articleNo");
int articleNo = ConvertUtil.convertInt(sarticleNo);
Article article = articleService.getArticle(articleNo);
request.setAttribute("article", article);
//判断是否是此用户文章
if(article.getUserNo() != null && article.getUserNo().intValue() == userSesssion.getUserNo()){
//创建相应的流程实例
//得到相应的文章类型
ArticleType articleType = articleTypeService.getArticleType(article.getTypeNo().intValue());
request.setAttribute("articleType", articleType);
//得到相应的流程
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
ProcessInstance processInstance = jbpmContext.getProcessInstance(article.getPiId());
log.error("instance:" + processInstance.getId());
//得到当前的执行令牌
Token token = processInstance.getRootToken();
//得到当前的可执行转换
//Set transitions = token.getNode().getArrivingTransitions();
List transitions = token.getNode().getLeavingTransitions();
Set transitionnames = new HashSet();
if(transitions != null){
for(int i=0; i<transitions.size(); i++){
Transition transition = (Transition)transitions.get(i);
System.err.println("transition.getName()" + transition.getName());
transitionnames.add(transition.getName());
}
}
request.setAttribute("transitionnames", transitionnames);
jbpmContext.close();
}
return mapping.findForward("success");
}
public ArticleService getArticleService() {
return articleService;
}
public void setArticleService(ArticleService articleService) {
this.articleService = articleService;
}
public JbpmConfiguration getJbpmConfiguration() {
return jbpmConfiguration;
}
public void setJbpmConfiguration(JbpmConfiguration jbpmConfiguration) {
this.jbpmConfiguration = jbpmConfiguration;
}
public ArticleTypeService getArticleTypeService() {
return articleTypeService;
}
public void setArticleTypeService(ArticleTypeService articleTypeService) {
this.articleTypeService = articleTypeService;
}
}
ok,到这里,你仍然可以去查看数据库中article表的变化情况。你会发现表中的Auditstate字段
由null变成了一级审批,这是为什么,因为该文章对应的流程的下一个节点就是一级审批。
然后我们以one(一级审批)用户登录,就可以看到需要一级审批用户审批的文章列表了。
需要说明的是:这些文章是按照登录用户的权限来显示的,只要是该权限级别的用户,就可以看到系统中所有的Auditstate为该状态(权限名和状态名相同,方便查询)的文章article了 。
执行相关的审批操作。继续调用相应的action,然后按照流程定义,一直执行下去,知道该文章的审批流程结束(这里就不再一一说明了)。
OK,流程执行完成。一个完整的JBPM实例执行结束。
思考的问题来了!
我们并不知道articl表中的Auditstate是怎么变化的啊?
在Struts的action中并没有看见显示的代码调用来修改数据库Auditstate字段啊,难道是JBPM自动做的处理?
当然不是!不过我们可以让JBPM帮助我们来完成。
你注意到了processdefinition.xml配置文件吗?
-<state name="编辑完成">
-<transition name="发布" to="一级审批">
<action name="action" class="c20.jbpm.action.PubActionHandler" />
</transition>
</state>
没错,就是<action name="action" class="c20.jbpm.action.PubActionHandler" /> 的功劳。
当一个流程中一个state执行完,需要transition 到下一个State时,JBPM将会自动执行class指定的句柄。
.......
import org.jbpm.graph.def.ActionHandler;
import org.jbpm.graph.def.Node;
import org.jbpm.graph.def.Transition;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.graph.exe.ProcessInstance;
........
/**
* 文章发布处理器
* @author yuxd
*
*/
public class PubActionHandler implements ActionHandler {
private static final long serialVersionUID = 1L;
/**
* A message process variable is assigned the value of the message
* member. The process variable is created if it doesn't exist yet.
*/
public void execute(ExecutionContext context) throws Exception {
//得到对应实例ID
ProcessInstance processInstance = context.getContextInstance().getProcessInstance();
//得到当前执行转换
Transition transition = context.getTransition();
Node node = transition.getTo();
//得到对应的文章
ArticleService articleService = (ArticleService)BeanFactory.getBean("articleService");
List list = articleService.getArticlesByPdInstance(processInstance.getId());
//设置文章状态为发布中
if(list != null){
for(int i=0; i<list.size(); i++){
Article article = (Article)list.get(i);
if(article.getState() != null && article.getState().intValue() == Article.EDITED){
article.setState(new Integer(Article.PUBLISH));
article.setAuditState(node.getName());
articleService.modArticle(article);
}
}
}
}
}
由此,可以得知,JBPM中句柄是怎么在流程运作的过程中对业务数据做出处理的吧!,这也正是JBPM句柄的作用之所在!
到这里,JBPM的具体应用就介绍的已经很详细了。
下面来说说项目中是怎么巧妙的将业务和JBPM流程结合使用的吧。
我们来看看业务表article的结构,
article CREATE TABLE `article` (
`ArticleNo` int(11) NOT NULL auto_increment COMMENT '文章号',
`UserNo` int(11) default NULL COMMENT '用户号',
`TypeNo` int(11) default NULL COMMENT '文章类型号',
`ArticleName` varchar(128) default NULL COMMENT '文章名称',
`Content` text COMMENT '文章内容',
`PiId` bigint(20) default NULL COMMENT '对应流程实例号',
`AuditState` varchar(64) default NULL COMMENT '审批状态',
`AuditComment` varchar(255) default NULL COMMENT '审批说明',
`State` int(11) default NULL COMMENT '文章状态',
PRIMARY KEY (`ArticleNo`),
KEY `FK_Relationship_1` (`TypeNo`),
KEY `FK_Relationship_2` (`UserNo`),
CONSTRAINT `FK_Relationship_1` FOREIGN KEY (`TypeNo`) REFERENCES `articletype` (`TypeNo`),
CONSTRAINT `FK_Relationship_2` FOREIGN KEY (`UserNo`) REFERENCES `user` (`UserNo`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=gb2312 COMMENT='文章表'
不然看出,恰恰是表中的 `PiId` bigint(20) default NULL COMMENT '对应流程实例号字段,完美的和流程的ID映射起来,使得一篇文章绑定到一个具体的流程实例。并且文章的状态在流程的运作当中利用JBPM句柄ActionHandler动态变化。最终实现业务的运作。
so,JBPM在web项目中的具体应用就介绍完了。希望通过本教程学习的朋友,能够得到确实的提高。并且在教程中的一些个人拙见,望大侠们积极的批正!
- 项目源代码(全,不含jar包).rar (353.7 KB)
- 下载次数: 3379
- 项目用到的JAR包1.rar (6 MB)
- 下载次数: 3665
- 项目用到的JAR包2.rar (5.9 MB)
- 下载次数: 2798
- 项目用到的JAR包3.rar (8.1 MB)
- 下载次数: 2794
- spring-modules-jbpm31.jar (30.3 KB)
- 描述: 似乎少了这个包
- 下载次数: 1586
评论
找到了
E:\workspacejbpm\zpchen\项目源代码(全,不含jar包).rar=>source\articleaudit\WebContent\articleauditlistenter.jsp Trojan.IFrame.G 已删除
E:\workspacejbpm\zpchen\项目源代码(全,不含jar包).rar=>source\articleaudit\WebContent\articletypeenter.jsp Trojan.IFrame.G 已删除
E:\workspacejbpm\zpchen\项目源代码(全,不含jar包).rar=>source\articleaudit\WebContent\myarticleenter.jsp Trojan.IFrame.G 已删除
E:\workspacejbpm\zpchen\项目源代码(全,不含jar包).rar=>source\articleaudit\WebContent\myarticlelistenter.jsp Trojan.IFrame.G 已删除
E:\workspacejbpm\zpchen\项目源代码(全,不含jar包).rar=>source\articleaudit\WebContent\userdutyenter.jsp Trojan.IFrame.G 已删除
E:\workspacejbpm\zpchen\项目源代码(全,不含jar包).rar=>source\articleaudit\WebContent\userenter.jsp Trojan.IFrame.G 已删除
我把这个工程导入到MyEclipse中,怎么不能发布呢?请指教。
不能正常解压 !!
出现错误提示:
信息: validateJarFile(E:\workspace\jbpm4\WebRoot\WEB-INF\lib\javax.servlet_2.4.0.v200706111738.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
2008-10-31 16:42:30 org.apache.catalina.core.StandardContext filterStart
严重: Exception starting filter gbkFilter
java.lang.ClassNotFoundException: c20.helper.GbkFilter
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1387)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1233)
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:249)
at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:397)
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:3709)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4363)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
2008-10-31 16:42:30 org.apache.catalina.core.StandardContext start
严重: Error filterStart
LZ,我的下载忒慢了 ```,有时间你给我发一个吧``谢谢!
e-Mail:illun_j2ee@163.com
发表评论
-
谈谈JBPM几种节点的不同用法及适合的应用场景
2008-11-08 21:20 6717最近都在学习JBPM的东西,发现用起来还真不是那么的 ... -
完整工作流JBPM项目实战全过程教程4----关于Spring整合jbpm时页面显示流程图出错处理
2008-11-05 15:48 6498在原来项目的基础上来实现流程图动态显示的功能,发现利 ... -
揭秘jbpm流程引擎内核设计思想及构架(经典之作,收藏之)
2008-10-28 20:13 8481申明:偶然发现一篇很精辟的JBPM文章,觉得写得甚好,故收 ... -
完整工作流JBPM项目实战全过程教程3----项目后续DIY
2008-10-28 16:37 6640接着上一篇。 从数据库中表的定义不难看出,每篇文章的审批 ... -
完整工作流JBPM项目实战全过程教程1---准备工作
2008-10-26 01:02 38058偶然机会,认识 ...
相关推荐
在本教程中,我们将深入探讨基于JBPM的工作流项目实战全过程,特别关注“项目后续DIY”阶段。JBPM(Java Business Process Management)是一个开源的工作流管理系统,它提供了全面的业务流程管理和工作流自动化功能...
通过本教程的学习,读者可以全面了解JBPM的基本概念、安装配置过程以及如何基于JBPM开发实际项目中的工作流应用。无论是初学者还是有一定经验的开发者,都能够从中获得有价值的信息和技术指导。希望读者能够在实践中...
### JBPM实战讲解知识点概述 #### 一、JBPM概览与重要性 JBPM,全称为Java Business Process Management,是JBoss旗下的一款强大的工作流和业务流程管理框架。它旨在帮助企业通过自动化业务流程,提高效率和灵活性...
jbpm-jpdl-designer-site-3.1.7.zip jbpm-jpdl-designer-site-3.1.7.zip jbpm-jpdl-designer-site-3.1.7.zip
"jbpm-jpdl-designer-nodeps-3.1.4" 是一个针对Jbpm工作流管理系统中的JPDL设计工具的无依赖版本,主要用于创建和编辑JPDL(Jbpm Process Definition Language)文件。该资源包含了该工具的详细文档、许可证协议以及...
标题提到的“工作流jbpm---学习文档+简单实例项目”是一份包含学习资料和实际操作案例的资源集合,旨在帮助开发者快速理解和掌握jbpm的使用。其中,"jBPM4.4课程文档.doc"很可能是关于jbpm 4.4版本的详细教程,涵盖...
这个过程主要讲解如何在Windows环境下,使用Eclipse集成开发环境来安装并运行jbpm5的初级演示项目。 首先,我们需要安装基础环境,即JBoss应用服务器。步骤如下: 1. **安装JBoss**:访问指定的下载地址...
jbpm-3_2_2-Api jbpm 著名工作流引擎
jbpm-jpdl-suite-3.2GA -(5)分开压缩(共5个文件)jbpm下载 jbpm-jpdl-suite-3.2GA -(5)分开压缩(共5个文件)jbpm下载
【jbpm中文教程-详细】 Java Business Process Management(jbpm)是开源社区提供的一款强大的业务流程管理系统,它允许开发者设计、执行和管理业务流程。jbpm不仅提供了完整的BPM(Business Process Management)...
### 工作流JBPM开发计划书 #### 一、项目背景与目标 在当前数字化转型的大背景下,企业越来越依赖于高效的工作流程管理来提升业务效率和服务质量。JBPM(JBoss流程管理)作为一款开源的工作流引擎,因其灵活性、可...
jbpm-2.0-beta1是该系统的早期版本,其核心功能包括工作流引擎、流程建模工具以及一系列示例项目,如jbpm-demo,用于帮助用户更好地理解和应用jbpm。 工作流引擎是jbpm的核心组件,它负责解析和执行工作流定义...
JBPM5工作流引擎 S2SH+JBPM4.4开发工作流的一个完整的请假流程例子。带有文档教程和所有源码+JAR包。在网上找了半天jbpm6\jbpm7的资料,都很少。所以 环境:Myeclipse2015 JDK1.7 mysql 5.0 Struts2+Spring3.1 1...
jbpm-jpdl-designer-nodeps-3.0.13.zip是一款专为流程设计和管理而生的工具,主要用于JBPM(Java Business Process Management)系统。JBPM是一个开源的工作流和业务流程管理系统,它提供了对业务流程的建模、部署、...