ssh2+jbpm3集成开发示范(二)
准备工作已经做好了,现在就可以开始进行代码的编写了。ssh框架集成的开始模式其实比较简单,各层的对象由spring负责管理,各层对象的依赖由spring负责注入。一般我们推荐采用面向接口的编程方式,理由很简单,大家都这么做。系统主要由数据访问层,业务层,控制层,显示层组成,当然根据具体情况可能会稍有不同,但只有能解决问题就可以了。其中由spring管理业务层的事务。
1.DAO
package org.qhit.jbpm;
import java.util.List;
import java.util.Map;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.springframework.transaction.annotation.Transactional;
/**
* 关于流程的数据访问接口
*
* @author 健坤IT教育
*
*/
public interface MonthDaoI {
/**
* 发布流程[流程定义的打包文件的路径]
*/
public abstract void publish(final String path);
/**
* 删除流程
* @param pfid[流程定义ID]
*/
public void deleteDefinition(final long pfid);
/**
* 完成任务
* @param tasker
* @param taskName
* @param params
* @param pid
* @param tranName
*/
public void finishTask(final String tasker, final String taskName,
final Map params, final long pid, final String tranName);
/**
* 启动流程
* @param pfid
* @param params
* @return
*/
public long start(final long pfid, final Map params);
/**
* 查找未完成的任务列表
* @param actorId
* @return
*/
public List<TaskInstance> getAllTaskByActorId(final String actorId);
}
实现类
package org.qhit.jbpm;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;
import org.jbpm.JbpmContext;
import org.jbpm.JbpmException;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.springframework.transaction.annotation.Transactional;
import org.springmodules.workflow.jbpm31.JbpmCallback;
import org.springmodules.workflow.jbpm31.support.JbpmDaoSupport;
/**
* spring注入jbpmtmplate或jbpmconfiguration对象
*
* @author 峰哥
*
*/
public class MonthDao extends JbpmDaoSupport implements MonthDaoI {
// 发布----
/*
* (non-Javadoc)
*
* @see org.qhit.jbpm.MonthDaoI#publish(java.lang.String)
*/
public void publish(final String path) {
super.getTemplate().execute(new JbpmCallback() {
public Object doInJbpm(JbpmContext context) throws JbpmException {
ZipInputStream in = new ZipInputStream(MonthDao.class
.getResourceAsStream(path));
ProcessDefinition pd = ProcessDefinition
.parseParZipInputStream(in);
context.deployProcessDefinition(pd);
return null;
}
});
}
// 删除
public void deleteDefinition(final long pfid) {
super.getTemplate().execute(new JbpmCallback() {
public Object doInJbpm(JbpmContext context) throws JbpmException {
context.getGraphSession().deleteProcessDefinition(pfid);
return null;
}
});
}
// 查找任务人所有未完成的任务
public List<TaskInstance> getAllTaskByActorId(final String actorId) {
return super.getTemplate().findTaskInstances(actorId);
}
// 启动流程[带流程变量]
public long start(final long pfid, final Map params) {
return (Long) super.getTemplate().execute(new JbpmCallback() {
public Object doInJbpm(JbpmContext context) throws JbpmException {
ProcessDefinition df = context.getGraphSession()
.loadProcessDefinition(pfid);
ProcessInstance pi = df.createProcessInstance(params);
// 发信号
pi.signal();
return pi.getId();
}
});
}
// 完成任务----[任务人,任务名,数据,流程实例编号 转向名]
public void finishTask(final String tasker, final String taskName,
final Map params, final long pid, final String tranName) {
super.getTemplate().execute(new JbpmCallback() {
public Object doInJbpm(JbpmContext context) throws JbpmException {
ProcessInstance pi = context.loadProcessInstance(pid);
Collection<TaskInstance> taskes = pi.getTaskMgmtInstance()
.getTaskInstances();
if (taskes != null) {
for (TaskInstance t : taskes) {
if (!t.hasEnded() && t.getActorId().equals(tasker)
&& t.getName().equals(taskName)) {
t.end(tranName);// 结束任务
break;
}
}
}
return null;
}
});
}
}
2.BIZ[业务层]
package org.qhit.jbpm.biz;
import java.util.List;
import java.util.Map;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.qhit.jbpm.MonthDaoI;
import org.springframework.transaction.annotation.Transactional;
@Transactional(readOnly=false)
/**
* 流程处理的业务类
*/
public class MonthJbpmBiz {
private MonthDaoI monthDao;
public void setMonthDao(MonthDaoI monthDao) {
this.monthDao = monthDao;
}
//发布
public void publish(String path)
{
this.monthDao.publish(path);
}
//启动
public long start(long pfid,Map<String, Object> params)
{
return this.monthDao.start(pfid, params);
}
//完成任务
public void finishTask(final String tasker,final String taskName,final Map params,final long pid,final String tranName)
{
this.monthDao.finishTask(tasker, taskName, params, pid, tranName);
}
//查找任务
public List<TaskInstance> getAllTaskByActorId(final String actorId){
return this.monthDao.getAllTaskByActorId(actorId);
}
}
这里的业务比较简单,所以代码应该很容易弄懂,这里没有使用接口也是可以的,但代理方式就不是基于接口了,而是基于cglib方式。注意在业务方法中的异常处理,如果有异常,一定要把异常抛出来。否则spring可能无法知道是否发生异常,但从当发生异常里不rollback事务。
3.ACTION[控制层]
一般的项目开发中,很少让控制层直接处理由业务层抛出的异常,所有我们一般会在业务层与控制层加一层比如wrapper之类的,处理业务层可以出现的异常,然后返回友好的结果给控制层。但这仅仅是个简单的示例。我们就直接将业务层对象注入给控制层的action了。
package org.qhit.web.actions;
import java.util.List;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.qhit.jbpm.biz.MonthJbpmBiz;
import com.opensymphony.xwork2.util.ValueStack;
/**
* 关于月度报表流程的控制类
* 1.发布流程
* 2.启动流程
* 3.完成任务....
* @author 峰哥 健坤教育---快乐学习
*
*/
public class MonthAction {
//spring di
private MonthJbpmBiz monthJbpmBiz;
private List<TaskInstance> taskes;//提供getter setter方法
//spring注入业务对象
public void setMonthJbpmBiz(MonthJbpmBiz monthJbpmBiz) {
this.monthJbpmBiz = monthJbpmBiz;
}
private String actorId;//保存登陆后的用户名
public List<TaskInstance> getTaskes() {
return taskes;
}
public void setTaskes(List<TaskInstance> taskes) {
this.taskes = taskes;
}
public String getActorId() {
return actorId;
}
public void setActorId(String actorId) {
this.actorId = actorId;
}
//查询
public String findAll(){
//ValueStack 【这里的任务参与人是硬编码的....】
List<TaskInstance> taskes = this.monthJbpmBiz.getAllTaskByActorId("清华小帅哥");//这里是硬编码
this.taskes = taskes;
System.out.println("在action中取得任务列表:\t"+taskes);
return "ok";
}
}
4.jsp等[显示层]
ok.jsp 作用是遍历保存于作用域中的taskes变量,显示当前用户的所有任务列表。
<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:forEach items="${taskes}" var="task">
<div><a href="show.jsp?tid=${task.id }">${task.name }</a></div>
</c:forEach>
show.jsp 利用jbpm图形标记,显示当前流程实例的图形信息。
<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@page import="org.jbpm.JbpmContext"%>
<%@page import="org.jbpm.JbpmConfiguration"%>
<%@ taglib prefix="jbpm" uri="/WEB-INF/jbpm.tld"%>
<jbpm:processimage task="${param.tid}"/>
基本的代码就是这些,下面的就是配置文件的编写与修改了。【未完待续】