审批流程管理

对流程定义进行管理

crud的操作,显示流程定义列表的时候,显示的是最新版本的流程定义

审批流转数据库搭建

Form.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package cn.itcast.shoa.domain.workflow;

import java.io.Serializable;
import java.util.Date;
import java.util.Set;

public class Form implements Serializable{
private Long fid;
private String title;
private String applicator;//申请人
private Date applictetime;//申请日期
private String state;//状态
private String url;

private Set<Approve> approves;

public Set<Approve> getApproves() {
return approves;
}

public void setApproves(Set<Approve> approves) {
this.approves = approves;
}

public String getPiid() {
return piid;
}

public void setPiid(String piid) {
this.piid = piid;
}

/**
* 该字段是系统内部的表和jbpm的表连接的一个桥梁
*/
private String piid;//流程实例ID

private FormTemplate formTemplate;

public Long getFid() {
return fid;
}

public void setFid(Long fid) {
this.fid = fid;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getApplicator() {
return applicator;
}

public void setApplicator(String applicator) {
this.applicator = applicator;
}

public Date getApplictetime() {
return applictetime;
}

public void setApplictetime(Date applictetime) {
this.applictetime = applictetime;
}

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public FormTemplate getFormTemplate() {
return formTemplate;
}

public void setFormTemplate(FormTemplate formTemplate) {
this.formTemplate = formTemplate;
}
}

Form.hbm.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.itcast.shoa.domain.workflow.Form">
<id name="fid" length="5">
<generator class="increment"></generator>
</id>
<property name="applicator" length="20"></property>
<property name="applictetime"></property>
<property name="piid" length="20"></property>
<property name="state" length="10"></property>
<property name="title" length="50"></property>
<property name="url" length="300"></property>

<set name="approves">
<key>
<column name="fid"></column>
</key>
<one-to-many class="cn.itcast.shoa.domain.workflow.Approve"/>
</set>

<many-to-one name="formTemplate" class="cn.itcast.shoa.domain.workflow.FormTemplate" column="ftid"></many-to-one>
</class>
</hibernate-mapping>

FormTemplate.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package cn.itcast.shoa.domain.workflow;

import java.io.Serializable;
import java.util.Set;

public class FormTemplate implements Serializable{
private Long ftid;
private String name;
private String processKey;
private String url;

private Set<Form> forms;

public Long getFtid() {
return ftid;
}

public void setFtid(Long ftid) {
this.ftid = ftid;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getProcessKey() {
return processKey;
}

public void setProcessKey(String processKey) {
this.processKey = processKey;
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public Set<Form> getForms() {
return forms;
}

public void setForms(Set<Form> forms) {
this.forms = forms;
}
}

FormTemplate.hbm.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.itcast.shoa.domain.workflow.FormTemplate">
<id name="ftid" length="5">
<generator class="increment"></generator>
</id>
<property name="name" length="20"></property>
<property name="processKey" length="20"></property>
<property name="url" length="300"></property>

<set name="forms">
<key>
<column name="ftid"></column>
</key>
<one-to-many class="cn.itcast.shoa.domain.workflow.Form"/>
</set>
</class>
</hibernate-mapping>

Approve.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package cn.itcast.shoa.domain.workflow;

import java.io.Serializable;
import java.util.Date;

public class Approve implements Serializable{
private Long aid;
private String approvename;//审批人
private Date approvetime;//审批时间
private Boolean isapprove;//是否通过

private Form form;

public Long getAid() {
return aid;
}

public void setAid(Long aid) {
this.aid = aid;
}

public String getApprovename() {
return approvename;
}

public void setApprovename(String approvename) {
this.approvename = approvename;
}

public Date getApprovetime() {
return approvetime;
}

public void setApprovetime(Date approvetime) {
this.approvetime = approvetime;
}

public Boolean getIsapprove() {
return isapprove;
}

public void setIsapprove(Boolean isapprove) {
this.isapprove = isapprove;
}

public Form getForm() {
return form;
}

public void setForm(Form form) {
this.form = form;
}
}

Approve.hbm.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.itcast.shoa.domain.workflow.Approve">
<id name="aid" length="5">
<generator class="increment"></generator>
</id>
<property name="approvename" length="20"></property>
<property name="approvetime"></property>
<property name="isapprove"></property>
<many-to-one name="form" class="cn.itcast.shoa.domain.workflow.Form" column="fid"></many-to-one>
</class>
</hibernate-mapping>

pom.xml配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>shoa_maven</groupId>
<artifactId>shoa_maven</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>shoa_maven</name>
<description/>
<properties>
<webVersion>3.0</webVersion>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>


<!--
数据库连接池
-->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>

<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.3.1.2</version>
</dependency>


<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-json-plugin</artifactId>
<version>2.3.1.2</version>
</dependency>

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.10.Final</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>servlet-api</artifactId>
<version>6.0.33</version>
<type>jar</type>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
</dependency>

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.3</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.3</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>

<!--
关于jbpm的jar包
-->

<dependency>
<groupId>org.jbpm.jbpm4</groupId>
<artifactId>jbpm</artifactId>
<version>4.4</version>
</dependency>

<dependency>
<groupId>org.jbpm.jbpm4</groupId>
<artifactId>jbpm-api</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>org.jbpm.jbpm4</groupId>
<artifactId>jbpm-jpdl</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>org.jbpm.jbpm4</groupId>
<artifactId>jbpm-pvm</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>org.jbpm.jbpm4</groupId>
<artifactId>jbpm-log</artifactId>
<version>4.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>appfuse-snapshots</id>
<url>http://oss.sonatype.org/content/repositories/appfuse-snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>Jboss-JBPM-Repositories</id>
<name>JbossJBPM</name>
<url>http://repository.jboss.org/nexus/content/groups/public</url>
</repository>
</repositories>
</project>

hibernate.cfg.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!--
sessionFactory代表一个数据库的描述
-->
<session-factory>
<property name="connection.password">root</property>
<property name="connection.username">root</property>

<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>

<property name="hibernate.connection.url">
jdbc:mysql://localhost:3306/shoa
</property>
<!--
告诉hibernate链接的是什么数据库
-->
<property name="dialect">
org.hibernate.dialect.MySQLInnoDBDialect
</property>

<!--
validate 默认值
根据持久化类和映射文件检查表的结构
update
hibernate容器在启动的时候,会根据持久化类和映射文件检查表的结构
如果不存在,则创建,如果存在,则更新
create
每次启动hibernate容器,不管表是否存在,都会创建
create-drop
当启动hibernate容器时创建表,当hibernate容器销毁时,删除表
-->
<property name="hbm2ddl.auto">update</property>

<!--
引入映射文件
-->
<property name="show_sql">true</property>
<mapping resource="cn/itcast/shoa/domain/Person.hbm.xml" />
<mapping resource="cn/itcast/shoa/domain/system/Department.hbm.xml" />
<mapping resource="cn/itcast/shoa/domain/system/Role.hbm.xml" />
<mapping resource="cn/itcast/shoa/domain/system/User.hbm.xml" />
<mapping resource="cn/itcast/shoa/domain/system/Privilege.hbm.xml" />
<mapping resource="cn/itcast/shoa/domain/workflow/Approve.hbm.xml" />
<mapping resource="cn/itcast/shoa/domain/workflow/Form.hbm.xml" />
<mapping
resource="cn/itcast/shoa/domain/workflow/FormTemplate.hbm.xml" />
</session-factory>
</hibernate-configuration>

运行SessionFactoryTest测试生成表

审批流转流程定义

service下的PDManager.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package cn.itcast.shoa.service;

import java.io.File;
import java.io.InputStream;
import java.util.Collection;

import org.jbpm.api.ProcessDefinition;

/**
* 流程定义管理
* @author zd
*
*/
public interface PDManager {
public Collection<ProcessDefinition> getLasterVersion();

public void deploy(File resource) throws Exception;

public void deletePD(String key);

public InputStream showImage(String deploymentId);
}

PDManagerImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package cn.itcast.shoa.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipInputStream;

import javax.annotation.Resource;

import org.jbpm.api.ProcessDefinition;
import org.jbpm.api.ProcessDefinitionQuery;
import org.jbpm.api.ProcessEngine;
import org.springframework.stereotype.Service;

import antlr.collections.List;
import cn.itcast.shoa.service.PDManager;

@Service("pdManager")
public class PDManagerImpl implements PDManager{

@Resource(name="processEngine")
private ProcessEngine processEngine;
@Override
public Collection<ProcessDefinition> getLasterVersion() {
// TODO Auto-generated method stub
//把所有流程定义都查询出来,并且按照版本从低到高排列
Collection<ProcessDefinition> pdlist = this.processEngine.getRepositoryService()
.createProcessDefinitionQuery()
.orderAsc(ProcessDefinitionQuery.PROPERTY_VERSION)
.list();
// List<ProcessDefinition> ----> Map<String, List<ProcessDefinition>>把每一个key下的list提取出来
// 找到list下封装的所有的ProcessDefinition的最高版本的pdkey
// Map<String, List<ProcessDefinition>> map = new HashMap<String, List<ProcessDefinition>>();
// for (ProcessDefinition pd : pdlist) {
// if (map.containsKey(pd.getKey())) {
// List<ProcessDefinition> pd2 = map.get(pd.getKey());
// pd2.add(pd);
// }else {
// List<ProcessDefinition> pd3 = new ArrayList<ProcessDefinition>();
// pd3.add(pd);
// map.put(pd.getKey(),pd3);
// }
// }
//遍历每一个流程定义,如果存在相同的key值,后者覆盖前者,也就意味着高版本覆盖低版本。
Map<String, ProcessDefinition> map = new HashMap<String, ProcessDefinition>();
for (ProcessDefinition pd : pdlist) {
map.put(pd.getKey(), pd);
}
return map.values();
}
@Override
public void deploy(File resource) throws Exception {
// TODO Auto-generated method stub
InputStream inputStream = new FileInputStream(resource);
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
this.processEngine.getRepositoryService()
.createDeployment()
.addResourcesFromZipInputStream(zipInputStream)
.deploy();
}

@Override
public void deletePD(String key) {
// TODO Auto-generated method stub
List<ProcessDefinition> pdList = this.processEngine
.getRepositoryService()
.createProcessDefinitionQuery()
.processDefinitionKey(key)
.list();
for (ProcessDefinition pd : pdList) {
//根据每一个流程定义获取到deploymentID,然后进行删除
this.processEngine.getRepositoryService().deleteDeploymentCascade(pd.getDeploymentId());
}

}

@Override
public InputStream showImage(String deploymentId) {
// TODO Auto-generated method stub
//1. 根据deploymentID和图片路径把图片加载出来
//2. 把图片加载出来后,产生输入流
//3. 把输入流的内容输入到界面上

//根据id获取图片流程定义
ProcessDefinition pd = this.processEngine
.getRepositoryService().createProcessDefinitionQuery()
.deploymentId(deploymentId)
.uniqueResult();
//获取图片的 输入流

return this.processEngine.getRepositoryService().getResourceAsStream(deploymentId, pd.getImageResourceName());
}

}

PDManagerAction

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package cn.itcast.shoa.struts.action;

import java.io.File;
import java.io.InputStream;
import java.util.Collection;

import javax.annotation.Resource;

import org.jbpm.api.ProcessDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

import cn.itcast.shoa.service.PDManager;
import cn.itcast.shoa.struts.action.base.BaseAction;

@Controller("pdManagerAction")
@Scope("prototype")
public class PDManagerAction extends ActionSupport{
@Resource(name="pdManager")
private PDManager pdManager;

private String deploymentId;

public String getDeploymentId() {
return deploymentId;
}

public void setDeploymentId(String deploymentId) {
this.deploymentId = deploymentId;
}

private InputStream inputStream;

public InputStream getInputStream() {
return inputStream;
}

public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}

private File resource;

private String key;

public String getKey() {
return key;
}

public void setKey(String key) {
this.key = key;
}

public File getResource() {
return resource;
}

public void setResource(File resource) {
this.resource = resource;
}

public String showLasterVersions(){
Collection<ProcessDefinition> pdList = this.pdManager.getLasterVersion();
ActionContext.getContext().put("pdList", pdList);
return "pdList";
}

/**
* 跳转到流程定义的部署的页面
*/
public String deployUI(){
return "deployUI";
}

/**
* 部署
*/
public String deploy() throws Exception{
this.pdManager.deploy(this.resource);
return "action2action";
}

public String deletePD(){
this.pdManager.deletePD(key);
return "action2action";
}
//显示图片
public String showImage(){
this.inputStream = this.pdManager.showImage(deploymentId);
return SUCCESS;
}
}

显示图片的步骤

  1. 在service层,根据deploymentid和图片的路径获取到一个输入流,也就是说service层的该方法应该返回一个inputStream。
  2. 在action层,有一个属性:inputStream,service层的方法的返回值应该赋值给inputStream。
  3. 在页面上利用window.open打开一个窗口,让输出流流入这个窗口中。

struts-workflow.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
<package name="pdmanager" namespace="/" extends="struts-default">
<action name="pdManagerAction_*" method="{1}" class="pdManagerAction">
<result name="pdList">WEB-INF/jsp/workflow/pdmanager/list.jsp</result>
<result name="deployUI">WEB-INF/jsp/workflow/pdmanager/deployUI.jsp</result>
<result name="action2action" type="redirectAction">pdManagerAction_showLasterVersions.action</result>
<result type="stream"></result>
</action>
</package>

<package name="formTemplate" namespace="/" extends="struts-default">
<action name="formTemplateAction_*" method="{1}" class="formTemplateAction">
<result name="listAction">WEB-INF/jsp/workflow/formTemplate/list.jsp</result>
<result name="addUI">WEB-INF/jsp/workflow/formTemplate/addUI.jsp</result>
<result name="action2action" type="redirectAction">formTemplateAction_showAllFormTemplate.action</result>
<result name="download" type="stream">
<!--
输入流的名字
用来获取inputStream
-->
<param name="inputName">inputStream</param>
<!-- 名称的名字 -->
<param name="contentDisposition">
<!--
应用ognl表达式动态显示要下载的文件的名字
-->
attachment;filename="${#fileName}.doc"
</param>
</result>
</action>
</package>
</struts>

struts.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
<constant name="struts.devMode" value="true"/>
<constant name="struts.ui.theme" value="simple"/>

<include file="struts/struts-person.xml"></include>
<include file="struts/struts-department.xml"></include>
<include file="struts/struts-role.xml"></include>

<include file="struts/struts-user.xml"></include>
<include file="struts/struts-menuitem.xml"></include>

<include file="struts/struts-table.xml"></include>

<include file="struts/struts-privilege.xml"></include>

<include file="struts/struts-forward.xml"></include>

<include file="struts/struts-login.xml"></include>
<include file="struts/struts-workflow.xml"></include>

<package name="privilegeOA" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="privilegeInterceptor" class="cn.itcast.shoa.interceptor.privilege.PrivilegeInterceptor"></interceptor>
<interceptor-stack name="oaStack">
<interceptor-ref name="privilegeInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="oaStack"></default-interceptor-ref>
<global-results>
<result name="privilegeError">error.jsp</result>
</global-results>
</package>

<package name="struts-global" namespace="/" extends="struts-default">
<global-results>
<result name="errHandler" type="chain">
<param name="actionName">errorProcessor</param>
</result>
</global-results>

<global-exception-mappings>
<exception-mapping exception="java.lang.Exception"
result="errHandler" />
</global-exception-mappings>

<action name="errorProcessor" class="cn.itcast.shoa.exception.MyException">
<result name="error">WEB-INF/jsp/error.jsp</result>
</action>
</package>
</struts>

jsp包下的workflow包下的pdmanager包的jsp文件

list.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/jsp/common/common.jsp"%>
<html>
<head>
<title>审批流程列表</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
function showProcessImage( deploymentId ){
var url = "pdManagerAction_showImage.action?deploymentId="+deploymentId;
window.open(url,300,400);
}
</script>
</head>
<body>

<div id="Title_bar">
<div id="Title_bar_Head">
<div id="Title_Head"></div>
<div id="Title"><!--页面标题-->
<img border="0" width="13" height="13" src="${pageContext.request.contextPath}/css/images/title_arrow.gif"/> 审批流程管理
</div>
<div id="Title_End"></div>
</div>
</div>

<div id="MainArea">
<table cellspacing="0" cellpadding="0" class="TableStyle">

<!-- 表头-->
<thead>
<tr align=center valign=middle id=TableTitle>
<td width="200px">流程名称</td>
<td width="80px">最新版本</td>
<td>相关操作</td>
</tr>
</thead>

<!--显示数据列表-->
<tbody id="TableData" class="dataContainer" datakey="processDefList">
<s:iterator value="#pdList">
<tr class="TableDetail1 template">
<td><s:property value="key"/></td>
<td align="CENTER"><s:property value="version"/></td>
<td>
<s:a action="pdManagerAction_deletePD.action?key=%{key}">删除</s:a>
<a href="javascript: showProcessImage('${deploymentId}')">查看流程图</a>
</td>
</tr>
</s:iterator>
</tbody>
</table>

<!-- 其他功能超链接 -->
<div id="TableTail">
<div id="TableTail_inside">
<table border="0" cellspacing="0" cellpadding="10" align="left">
<tr>
<td><div class="FuncBtn">
<div class=FuncBtnHead></div>
<div class=FuncBtnMemo><a href="pdManagerAction_deployUI.action">部署流程定义文档</a></div>
<div class=FuncBtnTail></div>
</div></td>
</tr>
</table>
</div>
</div>
</div>

<div class="Description">
说明:<br />
1,列表显示的是所有流程定义(不同名称)的最新版本。<br />
2,删除流程定义时,此名称的所有版本的流程定义都会被删除。<br />
</div>

</body>
</html>

deployUI.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/jsp/common/common.jsp"%>
<html>
<head>
<title>部署流程定义</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>

<!-- 标题显示 -->
<div id="Title_bar">
<div id="Title_bar_Head">
<div id="Title_Head"></div>
<div id="Title"><!--页面标题-->
<img border="0" width="13" height="13" src="${pageContext.request.contextPath}/css/images/title_arrow.gif"/> 部署流程定义
</div>
<div id="Title_End"></div>
</div>
</div>

<!--显示表单内容-->
<div id=MainArea>
<s:form action="pdManagerAction_deploy.action" enctype="multipart/form-data">
<div class="ItemBlock_Title1"><!-- 信息说明<DIV CLASS="ItemBlock_Title1">
<IMG BORDER="0" WIDTH="4" HEIGHT="7" SRC="${pageContext.request.contextPath}/css/blue/images/item_point.gif" /> 部署流程定义 </DIV> -->
</div>

<!-- 表单内容显示 -->
<div class="ItemBlockBorder">
<div class="ItemBlock">
<table cellpadding="0" cellspacing="0" class="mainForm">
<tr>
<td>请选择流程定义文档(zip格式)</td>
<td><s:file name="resource" cssClass="InputStyle"></s:file></td>
</tr>
</table>
</div>
</div>

<!-- 表单操作 -->
<div id="InputDetailBar">
<input type="image" src="${pageContext.request.contextPath}/css/images/save.png"/>
<a href="javascript:history.go(-1);"><img src="${pageContext.request.contextPath}/css/images/goBack.png"/></a>
</div>
</s:form>
</div>

<div class="Description">
说明:只接受zip扩展名的文件。
</div>

</body>
</html>

表单模板管理

表单模板的列表

FormTemplateDao

1
2
3
4
5
6
7
8
package cn.itcast.shoa.dao;

import cn.itcast.shoa.dao.base.BaseDao;
import cn.itcast.shoa.domain.workflow.FormTemplate;

public interface FormTemplateDao extends BaseDao<FormTemplate>{

}

FormTemplateDaoImpl

1
2
3
4
5
6
7
8
9
10
11
12
package cn.itcast.shoa.dao.impl;

import org.springframework.stereotype.Repository;

import cn.itcast.shoa.dao.FormTemplateDao;
import cn.itcast.shoa.dao.base.impl.BaseDaoImpl;
import cn.itcast.shoa.domain.workflow.FormTemplate;

@Repository("formTemplateDao")
public class FormTemplateDaoImpl extends BaseDaoImpl<FormTemplate> implements FormTemplateDao{

}

FormTemplateService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package cn.itcast.shoa.service;

import java.io.InputStream;
import java.util.Collection;

import cn.itcast.shoa.domain.workflow.FormTemplate;

public interface FormTemplateService {
public Collection<FormTemplate> getAllFormTemplate();

public void saveFormTemplate(FormTemplate formTemplate);

public InputStream download(Long ftid) throws Exception;
}

FormTemplateServiceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package cn.itcast.shoa.service.impl;

import java.io.File;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Collection;

import javax.annotation.Resource;
import javax.imageio.stream.FileImageInputStream;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.opensymphony.xwork2.ActionContext;

import cn.itcast.shoa.dao.FormTemplateDao;
import cn.itcast.shoa.domain.workflow.FormTemplate;
import cn.itcast.shoa.service.FormTemplateService;
import javassist.tools.framedump;

@Service("formTemplate")
public class FormTemplateServiceImpl implements FormTemplateService{

@Resource(name="formTemplateDao")
private FormTemplateDao formTemplateDao;

@Override
public Collection<FormTemplate> getAllFormTemplate() {
// TODO Auto-generated method stub
return this.formTemplateDao.getAllEntry();
}

@Transactional(readOnly= false)
public void saveFormTemplate(FormTemplate formTemplate) {
// TODO Auto-generated method stub
this.formTemplateDao.saveEntry(formTemplate);
}

@Override
public InputStream download(Long ftid) throws Exception {
// TODO Auto-generated method stub
FormTemplate formTemplate = this.formTemplateDao.getEntryById(ftid);
String url = formTemplate.getUrl();
String fileName = formTemplate.getName();
fileName = URLEncoder.encode(fileName);
ActionContext.getContext().put("fileName", fileName);
return new FileInputStream(new File(url));
}

}

FormTemplateAction

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package cn.itcast.shoa.struts.action;

import java.io.File;
import java.io.InputStream;
import java.util.Collection;

import javax.annotation.Resource;

import org.apache.struts2.dispatcher.StreamResult;
import org.jbpm.api.ProcessDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionContext;

import cn.itcast.shoa.domain.workflow.FormTemplate;
import cn.itcast.shoa.service.FormTemplateService;
import cn.itcast.shoa.service.PDManager;
import cn.itcast.shoa.struts.action.base.BaseAction;
import cn.itcast.shoa.utils.UploadUtils;

@Controller("formTemplateAction")
@Scope("prototype")
public class FormTemplateAction extends BaseAction<FormTemplate>{

private File resource;

private InputStream inputStream;

public InputStream getInputStream() {
return inputStream;
}

public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}

public File getResource() {
return resource;
}

public void setResource(File resource) {
this.resource = resource;
}

@Resource(name="formTemplateService")
private FormTemplateService formTemplateService;

@Resource(name="pdManager")
private PDManager pdManager;

public String showAllFormTemplate(){
Collection<FormTemplate> ftList = this.formTemplateService.getAllFormTemplate();
ActionContext.getContext().put("ftList", ftList);
return "listAction";
}

/**
* 跳转到表单模板的添加页面
* @return
*/
public String addUI(){
Collection<ProcessDefinition> pdList = this.pdManager.getLasterVersion();
ActionContext.getContext().put("pdList", pdList);
return ADD_UI;
}

public String add(){
/**
* 1、把表单模板上传到服务器上
* 2、在表单模板中插入一行数据
*/
String url = UploadUtils.saveUploadFile(this.resource);
FormTemplate formTemplate = new FormTemplate();
formTemplate.setName(this.getModel().getName());
formTemplate.setProcessKey(this.getModel().getProcessKey());
formTemplate.setUrl(url);
this.formTemplateService.saveFormTemplate(formTemplate);
return action2action;
}

/**
* 下载
*/
public String download() throws Exception{
StreamResult
this.inputStream = this.formTemplateService.download(this.getModel().getFtid());
return "download";
}
}

workflow包下的formTemplate包下的list.jsp文件

list.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/jsp/common/common.jsp"%>
<html>
<head>
<title>表单模板列表</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>

<div id="Title_bar">
<div id="Title_bar_Head">
<div id="Title_Head"></div>
<div id="Title"><!--页面标题-->
<img border="0" width="13" height="13" src="${pageContext.request.contextPath}/css/images/title_arrow.gif"/> 模板管理
</div>
<div id="Title_End"></div>
</div>
</div>

<div id="MainArea">
<table cellspacing="0" cellpadding="0" class="TableStyle">

<!-- 表头-->
<thead>
<tr align=center valign=middle id=TableTitle>
<td width="250px">模板名称</td>
<td width="250px">所用流程</td>
<td>相关操作</td>
</tr>
</thead>

<!--显示数据列表-->
<tbody id="TableData" class="dataContainer" datakey="documentTemplateList">
<s:iterator value="#ftList">
<tr class="TableDetail1 template">
<td><s:property value="name"/></td>
<td><s:property value="processKey"/></td>
<td><a onClick="return delConfirm()" href="#">删除</a>
<a href="saveUI.html">修改</a>
<s:a action="formTemplateAction_download.action?ftid=%{ftid}">下载</s:a>
</td>
</tr>
</s:iterator>
</tbody>
</table>

<!-- 其他功能超链接 -->
<div id="TableTail">
<div id="TableTail_inside">
<a href="formTemplateAction_addUI.action"><img src="${pageContext.request.contextPath}/css/blue/images/button/addNew.PNG" /></a>
</div>
</div>

<div class="description">
说明:<br />
1,删除时,相应的文件也被删除。<br />
2,下载时,文件名默认为:{表单模板名称}.doc<br />
</div>

</div>
</body>
</html>

addUI.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/jsp/common/common.jsp"%>
<html>
<head>
<title>文档模板信息</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>

<!-- 标题显示 -->
<div id="Title_bar">
<div id="Title_bar_Head">
<div id="Title_Head"></div>
<div id="Title"><!--页面标题-->
<img border="0" width="13" height="13" src="${pageContext.request.contextPath}/css/images/title_arrow.gif"/> 文档模板信息
</div>
<div id="Title_End"></div>
</div>
</div>

<!--显示表单内容-->
<div id=MainArea>
<s:form action="formTemplateAction_add.action" enctype="multipart/form-data">
<div class="ItemBlock_Title1"><!-- 信息说明 --><div class="ItemBlock_Title1">
<img border="0" width="4" height="7" src="${pageContext.request.contextPath}/css/blue/images/item_point.gif" /> 模板基本信息 </div>
</div>

<!-- 表单内容显示 -->
<div class="ItemBlockBorder">
<div class="ItemBlock">
<table cellpadding="0" cellspacing="0" class="mainForm">
<tr>
<td>模板名称</td>
<td><s:textfield name="name" cssClass="InputStyle"></s:textfield></td>
</tr>
<tr>
<td>所用流程</td>

<td><s:select list="#pdList" listKey="key" listValue="key" name="processKey" cssClass="SelectStyle"></s:select>
</td>
</tr>
</table>
</div>
</div>

<div class="ItemBlock_Title1"><!-- 信息说明 --><div class="ItemBlock_Title1">
<img border="0" width="4" height="7" src="${pageContext.request.contextPath}/css/blue/images/item_point.gif" /> 模板文件 </div>
</div>

<!-- 表单内容显示 -->
<div class="ItemBlockBorder">
<div class="ItemBlock">
<table cellpadding="0" cellspacing="0" class="mainForm">
<tr>
<td width="120px;">请选择文件(doc格式)</td>
<td><input type="file" name="resource" class="InputStyle" style="width:450px;" /> </td>
</tr>
</table>
</div>
</div>

<!-- 表单操作 -->
<div id="InputDetailBar">
<input type="image" src="${pageContext.request.contextPath}/css/images/save.png"/>
<a href="javascript:history.go(-1);"><img src="${pageContext.request.contextPath}/css/images/goBack.png"/></a>
</div>
</s:form>
</div>

<div class="Description">
说明:<br />
1,模板文件是doc扩展名的文件(Word文档)。<br />
2,如果是添加:必须要选择模板文件。<br />
3,如果是修改:只是在 需要更新模板文件时 才选择一个文件。
</div>

</body>
</html>

下载模板经过的步骤

  1. 根据ftid查找到formTemplate对象
  2. 根据该对象查找到url
  3. 根据url创建一个FileInputStream
  4. 在action类中,有一个属性:inputStream,把上面步骤得到的返回值赋值给action的inputStream。
  5. 在struts2的配置文件中,结果集类型为”stream”,设置下载文件输入流参数,fileName来自map栈。

发起申请和审批处理的需求分析

当启动流程实例的时候 ,把form对象放入流程变量中。

审批处理中,该登录人正在审批处理的表单:

登录人—->当前登录人正在执行的任务—->遍历每一个任务—->task—->executionId,”form”—->从当前流程实例中把form提取出来。

步骤分析:

发起申请

表单模板的列表页面

提交申请页面

提交:

  1. 完成上传表单的功能

    需要一个参数:File 该参数从action中可以传递过来

  2. 在form表中插入一行数据

    applicator:申请人 从session中可以获取到 applicateTime:申请时间 就是当前时间

    state:审批中 ftid:表单模板id

    piid:该值只能在启动完流程实例才能赋

  3. 关于工作流

    1. 启动流程实例

      根据pdkey启动流程实例,在启动流程实例的时候可以返回一个pi—->piid

      当启动完流程实例以后可以重新给form对象的piid赋值

    2. 完成请假申请的任务

      需要一个”taskId”

      pi—->piid—->唯一的一个任务—->taskId

发起申请管理

WorkFlowAction

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package cn.itcast.shoa.struts.action;

import java.io.File;
import java.util.Collection;

import javax.annotation.Resource;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import cn.itcast.shoa.domain.workflow.FormTemplate;
import cn.itcast.shoa.service.FormTemplateService;
import cn.itcast.shoa.service.WorkFlowService;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

@Controller("workFlowAction")
@Scope("prototype")
public class WorkFlowAction extends ActionSupport{
@Resource(name="formTemplateService")
private FormTemplateService formTemplateService;

private File resource;

private Long ftid;

private String processKey;


public String getProcessKey() {
return processKey;
}

public void setProcessKey(String processKey) {
this.processKey = processKey;
}

public Long getFtid() {
return ftid;
}

public void setFtid(Long ftid) {
this.ftid = ftid;
}

public File getResource() {
return resource;
}

public void setResource(File resource) {
this.resource = resource;
}

@Resource(name="workFlowService")
private WorkFlowService workFlowService;
/**
* 跳转到表单模板的列表页面
* @return
*/
public String showFormTemplate(){
Collection<FormTemplate> ftList = this.formTemplateService.getAllFormTemplate();
ActionContext.getContext().put("ftList", ftList);
return "formTemplateList";
}

/*
* 跳转到提交申请的页面
*/
public String submitUI(){
return "submitUI";
}

public String submit(){
this.workFlowService.submit(resource, ftid, processKey);
return null;
}
}

strute-workflow.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
<package name="pdmanager" namespace="/" extends="struts-default">
<action name="pdManagerAction_*" method="{1}" class="pdManagerAction">
<result name="pdList">WEB-INF/jsp/workflow/pdmanager/list.jsp</result>
<result name="deployUI">WEB-INF/jsp/workflow/pdmanager/deployUI.jsp</result>
<result name="action2action" type="redirectAction">pdManagerAction_showLasterVersions.action</result>
<result type="stream"></result>
</action>
</package>

<package name="formTemplate" namespace="/" extends="struts-default">
<action name="formTemplateAction_*" method="{1}" class="formTemplateAction">
<result name="listAction">WEB-INF/jsp/workflow/formTemplate/list.jsp</result>
<result name="addUI">WEB-INF/jsp/workflow/formTemplate/addUI.jsp</result>
<result name="action2action" type="redirectAction">formTemplateAction_showAllFormTemplate.action</result>
<result name="download" type="stream">
<!--
输入流的名字
用来获取inputStream
-->
<param name="inputName">inputStream</param>
<!-- 名称的名字 -->
<param name="contentDisposition">
<!--
应用ognl表达式动态显示要下载的文件的名字
-->
attachment;filename="${#fileName}.doc"
</param>
</result>
</action>
</package>
<package name="workflow" namespace="/" extends="struts-default">
<action name="workFlowAction_*" method="{1}" class="workFlowAction">
<result name="formTemplateList">WEB-INF/jsp/workflow/workflow/formTemplateList.jsp</result>
<result name="submitUI">WEB-INF/jsp/workflow/workflow/submitUI.jsp</result>
</action>
</package>
</struts>

jsp下workflow/workflow包下jsp文件

formTemplateList.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/jsp/common/common.jsp"%>
<html>
<head>
<title>申请模板选择</title>
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/css/blue/select.css"/>
</head>
<body>

<div id="Title_bar" style="margin-bottom: 20px;">
<div id="Title_bar_Head">
<div id="Title_Head"></div>
<div id="Title"><!--页面标题-->
<img border="0" width="13" height="13" src="${pageContext.request.contextPath}/css/images/title_arrow.gif"/> 申请模板选择
</div>
<div id="Title_End"></div>
</div>
</div>

<table width="85%" cellspacing="0" cellpadding="1" border="0" class="TableBorder" style="margin-left: 15px;">
<tbody>
<tr>
<td>
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td class="HeadRight">
<table height="27" cellspacing="0" cellpadding="0" border="0">
<tr>
<td class="HeadLeft">请选择申请模板</td>
<td width="35" class="HeadMiddle"></td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td class="Detail dataContainer" datakey="formTemplateList">
<s:iterator value="#ftList">
<div id="DetailBlock" class="template">
<img width="16" height="16" src="${pageContext.request.contextPath}/css/images/FileType/doc.gif"/>
<s:a action="workFlowAction_submitUI.action?ftid=%{ftid}&processKey=%{processKey}"><s:property value="name"/></s:a>
</div>
</s:iterator>
</td>
</tr>
</tbody>
</table>

<div class="Description">
说明:此页面是列出所有的表单模板记录<br />
</div>

</body>
</html>

submitUI.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/jsp/common/common.jsp"%>
<html>
<head>
<title>提交申请</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>

<!-- 标题显示 -->
<div id="Title_bar">
<div id="Title_bar_Head">
<div id="Title_Head"></div>
<div id="Title"><!--页面标题-->
<img border="0" width="13" height="13" src="${pageContext.request.contextPath}/css/images/title_arrow.gif"/> 提交申请
</div>
<div id="Title_End"></div>
</div>
</div>

<!--显示表单内容-->
<div id=MainArea>
<s:form action="workFlowAction_submit.action" enctype="multipart/form-data">
<s:hidden name="ftid"></s:hidden>
<s:hidden name="processKey"></s:hidden>
<div class="ItemBlock_Title1"><!-- 信息说明 --><div class="ItemBlock_Title1">
<img border="0" width="4" height="7" src="${pageContext.request.contextPath}/css/blue/images/item_point.gif" /> 下载文档模板 </div>
</div>
<div class="ItemBlockBorder">
<div class="ItemBlock">
<table cellpadding="0" cellspacing="0" class="mainForm">
<tr>
<td><a href="javascript:void(0)" style="text-decoration: underline">[点击下载文档模板文件]</a></td>
</tr>
</table>
</div>
</div>

<div class="ItemBlock_Title1"><!-- 信息说明 --><div class="ItemBlock_Title1">
<img border="0" width="4" height="7" src="${pageContext.request.contextPath}/css/blue/images/item_point.gif" /> 申请信息 </div>
</div>
<div class="ItemBlockBorder">
<div class="ItemBlock">
<table cellpadding="0" cellspacing="0" class="mainForm">
<tr>
<td width="130">请选择填写好的文档</td>
<td><s:file name="resource" cssClass="InputStyle"></s:file></td>
</tr>
</table>
</div>
</div>

<!-- 表单操作 -->
<div id="InputDetailBar">
<input type="image" src="${pageContext.request.contextPath}/css/blue/images/button/submit.PNG"/>
<a href="javascript:history.go(-1);"><img src="${pageContext.request.contextPath}/css/images/goBack.png"/></a>
</div>
</s:form>
</div>

<div class="Description">
使用说明:<br />
1,下载模板文件。<br />
2,填写文档中的表单。<br />
3,选择这个填写好的文件进行提交。<br />
<br />
说明2:提交表单后,就会按照 模板对应的流程 开始流转。
</div>

</body>
</html>

WorkFlowService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package cn.itcast.shoa.service;

import java.io.File;
import java.util.Collection;

import cn.itcast.shoa.domain.workflow.Form;
import cn.itcast.shoa.domain.workflow.TaskView;

public interface WorkFlowService {
public void submit(File resource,Long ftid,String processKey);

public Collection<Form> myTaskList();

public Collection<TaskView> myTaskList2();

public void approve();
}

WorkFlowServiceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package cn.itcast.shoa.service.impl;

import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.jbpm.api.ProcessEngine;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.task.Task;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.itcast.shoa.dao.FormDao;
import cn.itcast.shoa.dao.FormTemplateDao;
import cn.itcast.shoa.domain.system.User;
import cn.itcast.shoa.domain.workflow.Form;
import cn.itcast.shoa.domain.workflow.FormTemplate;
import cn.itcast.shoa.service.WorkFlowService;
import cn.itcast.shoa.util.UploadUtils;
import javassist.tools.framedump;
import cn.itcast.shoa.util.OAUtils;

@Service("workFlowService")
public class WorkFlowServiceImpl implements WorkFlowService{

@Resource(name="formTemplateDao")
private FormTemplateDao formTemplateDao;

@Resource(name="processEngine")
private ProcessEngine processEngine;

@Resource(name="formDao")
private FormDao formDao;

@Transactional(readOnly=false)
public void submit(File resource,Long ftid,String processKey) {
/**
* 1、上传form表单
* 2、保存form表的数据
* 3、启动流程实例
* 4、完成任务
*/
//完成文件的上传
String url = UploadUtils.saveUploadFile(resource);

//form对象填充值
Form form = new Form();
User user = OAUtils.getUserFromSession();
form.setApplicator(user.getUsername());
Date time = new Date();
form.setApplictetime(time);
FormTemplate formTemplate = this.formTemplateDao.getEntryById(ftid);
form.setFormTemplate(formTemplate);
form.setState("申请中");
form.setTitle(formTemplate.getName()+"_"+user.getUsername()+"_"+time);
form.setUrl(url);

this.formDao.saveEntry(form);

//启动流程实例
//放在流程实例中的流程变量form必须是持久化数据
Map<String, Form> variables = new HashMap<String, Form>();
variables.put("form", form);
ProcessInstance pi = this.processEngine.getExecutionService()
.startProcessInstanceByKey(processKey, variables);

form.setPiid(pi.getId());

//完成任务
//根据piid获取该流程实例当前正在执行的任务
Task task = this.processEngine.getTaskService()
.createTaskQuery()
.executionId(pi.getId())
.uniqueResult();
this.processEngine.getTaskService()
.completeTask(task.getId());
}

}

FormDao

1
2
3
4
5
6
7
8
package cn.itcast.shoa.dao;

import cn.itcast.shoa.dao.base.BaseDao;
import cn.itcast.shoa.domain.workflow.Form;

public interface FormDao extends BaseDao<Form>{

}

FormDaoImpl

1
2
3
4
5
6
7
8
9
10
11
12
package cn.itcast.shoa.dao.impl;

import org.springframework.stereotype.Repository;

import cn.itcast.shoa.dao.FormDao;
import cn.itcast.shoa.dao.base.impl.BaseDaoImpl;
import cn.itcast.shoa.domain.workflow.Form;

@Repository("formDao")
public class FormDaoImpl extends BaseDaoImpl<Form> implements FormDao{

}

OAUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package cn.itcast.shoa.util;

import java.util.Collection;

import org.apache.struts2.ServletActionContext;

import cn.itcast.shoa.domain.system.Privilege;
import cn.itcast.shoa.domain.system.User;

public class OAUtils {
public static void putUserToSession(User user){
ServletActionContext.getRequest()
.getSession().setAttribute("user", user);
}

public static void putFunctionsToSession(Collection<Privilege> privileges){
ServletActionContext.getRequest()
.getSession().setAttribute("privileges", privileges);
}

public static User getUserFromSession(){
return (User)ServletActionContext.getRequest()
.getSession().getAttribute("user");
}
}