转:传智播客--Jbpm(四)
1. 完成职务的修改;
2. 完成人员的管理:
-- UserForm
-- 所属部门使用int deptId;
-- 职务使用int [] roleIds;
-- 使用BeanUtils复制两个不同对象的相同的属性;
修改部分:
BeanUtils.copyProperties(userForm, user);
userForm.setDeptId(user.getDepartment()==null ? 0 : user.getDepartment().getId());
int[] roleIds = new int[user.getRoles().size()];
int index = 0;
for (Role role : user.getRoles()){
roleIds[index++] = role.getId();
}
userForm.setRoleIds(roleIds);
添加部分:
BeanUtils.copyProperties(user, userForm);
Department dept = null;
user.setDepartment(dept);
if ( roleIds != null ) {
for (int roleId : roles) {
Role role = null;
user.getRoles().add(role);
}
}
-- 通过这个3个模块的增删改查,发现他们的Service可以共享;
所以使用BaseAction extends DispatchAction,这个BaseAction管理所有的
Service,并把它们作为protected,专供子类使用;
这和论坛中的处理方法一致;
-- 出错:
-- 没有非空约束:但是报了roleId不能为空;
中间表,user_role中userId, roleId一起作为主键;
roleIds是一个数组,需要单独处理
-- 有事务控制;
-- 返回到.do的请求,尽量用重定向;
-- User页面save.jsp中增加选择部门:
-- 页面显示部门名称,增加隐藏字段:部门id
-- js代码;
-- UserForm代码,增加deptName字段;
-- User页面save.jsp中增加选择职务:
-- fieldset, legend, html:multibox
<c:forEach items="${roles}" var="role">
<html:multibox property="roleIds" value="${role.id}"></html:multibox>${role.name}<br>
</c:forEach>
-- checkbox与multibox
checkbox -- boolean
multibox -- 集合
-- 修改职务时,如果一个都不选择,就不能保存;
原因分析:
解决: user.getRoles().clear();
== 复习
需求: Department的模块,每次修改或删除一个部门后,不能转向当前的部门级别,
而是显示总公司的部门列表;
解决:
因为Struts的forward的配置不能修改,要想在这个forward后面追加参数,使用下面的方法:
af = mapping.findForward("list");
new ActionForward(af.getPath()) + "&parentId=" + deptForm.getParentId(), );
注意: 这种用法在论坛中也使用过;可以查看源码复习;
3. 分析流程定义;
(1) 为什么流程定义不能删除?
笔记有解释;
查询历史记录时会有问题;删除流程定义时,导致下面的级联删除;
流程定义->流程实例->任务实例;
jbpm的解决方法是使用版本控制;每次都启动新的流程定义;
(2) 项目中如何实现流程定义的删除?
只有管理员可以删除;
(3) 功能:
流程定义列表;
部署(par包);
流程定义查看;
4. 根据上述分析,写出程序框架,属于详细设计
(1) 写出PdAction的框架基本方法:
list(), deploy(), viewPdFile(), viewPdImage(), download(), delete();
deployUI()
(2) Service->ServiceImpl;
-- 统一管理jbpmContext; 把管理的方法放在BaseService;
JbpmContextMangaer.getInstance().getJbpmContext();
-- 所有与jbpm有关的操作,一定要使用jbpm API;
最常用的就是jbpmContext;
来源:(http://blog.sina.com.cn/s/blog_5ecfe46a0100doco.html) - 传智播客--Jbpm(四)_hhl_bj_新浪博客
-- PdForm
id, resource(FormFile,部署流程定义文件的par包)
(3) jsp页面:
(4) 部署流程定义:
-- 包装输入流
new ZipInputStream(pdForm.getResource().getInputStream);
-- 流的关闭:
在调用的方法中关闭,被调用的方法只管用;
(5) 下载
-- 如何将文件打包?
File file = new File("c:/test/a.txt");
FileInputStream in = new FileInputStream(file);
byte[] fiel1 = new byte[(int)file.length()];
in.read(file1);
in.close();
File file = new File("c:/test/b.txt");
FileInputStream in = new FileInputStream(file);
byte[] fiel2 = new byte[(int)file.length()];
in.read(file2);
in.close();
FileOutputStream fos = new FileOutputStream("c:/text/xx.zip");
zipOutputStream zipos = new ZipOutputStream(fos);
zipOutputStream.putNextEntry(ZipEntry("a.txt")));
zipOutputStream.write(file1));
zipOutputStream.close();
zipOutputStream.putNextEntry(ZipEntry("b.txt")));
zipOutputStream.write(file2));
zipOutputStream.closeEntry();
zipOutputStream.close();
== 出现文件结构如何修改
指定的名字就是相对压缩包的相对路径;"c/c.txt"
== 空文件夹
"emptyDir/"
**************** 关于流程定义的处理方法,整理一下
(1) 显示流程定义文件内容;
使用response直接在浏览器上显示;
-- 设置response的contentType="text/xml;charset=utf-8";
-- 获取xml文件的内容:FileDefinition.getBytes();
-- 使用response将内容输出:response.write();
-- 不需要再返回jsp页面:return null;
-- jsp页面使用 href="#";
(2) 显示图片
-- response.setContentType("image/jpeg");
-- 修改文件名为流程定义的jpg文件;
-- 其他操作同上;
(3) 备份到本地:
-- 将所有的文件打包;
Map<String, byte[]> files = pd.getFileDefinition().getBytesMap();
ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream());
for ( String fileName : files.keySet() ) {
byte[] content = file.get(fileName);
zipOutputStream.putNextEntry(new ZipEntry(fileName));
zipOutputStream.write(content);
zipOutputStream.closeEntry();
}
zipOutputStream.close(); // 必须,否则下载的文件不完整;
return null;
-- 让下载后的文件名改变;
流程定义名_版本.zip
zipName = pd.getName() + "_" + pd.getVersion() + ".zip";
zipName = URLEncoder.encode(zipName, "utf-8");
response.addHeader("Content-Disposition", "attachment;filename=""+zipName);
response.setContentType("application/zip");
-- 下载带空文件夹,多层文件夹的流程定义文件:
zipOutputStream.write(content);
改为
if ( content != null )
zipOutputStream.write(content);
-- 删除
所有jbpm的操作尽量使用jbpmContext来操作;
5. 页面框架:Outlook Like Bar Version 1.7
6. 请假流程
(1) 经理审批:
Handler方式分配任务的角色,不使用actor,这是分配任务的第二种方式:
AssignmentHandler
assign(Assignable , ExecutionContext);
//申请人; 做审批工作的职务; 查询:申请人所在部门的做审批工作的职务的那个人(可能多个);
// 1,只有一个人审批;
assignable.setActorId();
// 2, 多个人;
assignable.setPooledActors();
(2) 总经理审批
代码内容与部门经理的代码内容相似;
重用代码;
-- 将局部变量roleName作为成员变量
privateString roleName;
-- Config Info:
Assignment的配置里面可以设置成员变量的初始值;
这样就可以将部门经理和总经理的这个变量的初始值
分别设为部门经理和总经理;
-- Config Type
field,bean,construtor ; 参考Spring;
assign
-- 所有的操作应该和executionContext有关;
-- 获取变量
executionContext.getVariable();
-- 获取JbpmContext;从而获取session,获取数据库中的值
executionContext.getJbpmContext();
-- 组任务查询语句:Hibernate
from User u where and ? in elementes(u.roles);
流程定义中设置了actorId的初始值,它表示的是职务名称;
在assign中需要通过它获取担任该职务的人员名称;
要实现这些,需要2步:
1. 通过actorId获取Role对象;
2. 通过Role对象获取User列表;