宅急送 项目第十二天 项目总结

重点:
1、 复习 JBPM 工作流开发流程
2、 完成 中转配送流程
3、 流程实例监控 模块
4、 异常处理
5、 二级缓存

1. JBPM开发流程回顾

1.1. 在项目整合工作流框架 (第九天)

导入jar包 (使用 maven坐标导入 )

配置文件 jbpm.cfg.xml 核心配置文件, 默认引入 hibernate 配置文件 jbpm.hibernate.cfg.xml , 如果整合Spring ,引入
将hibernate 配置权力,交给Spring
引入hbm

jbpm.repository.hbm.xml
jbpm.execution.hbm.xml
jbpm.history.hbm.xml
jbpm.task.hbm.xml
jbpm.identity.hbm.xml

Spring 整合 JBPM ,需要通过 SpringHelper 工厂类,创建 ProcessEngine 流程引擎


<bean id="springHelper" class="org.jbpm.pvm.internal.processengine.SpringHelper">
    <property name="jbpmCfg" value="jbpm.cfg.xml">property>
bean>
<bean id="processEngine" factory-bean="springHelper"
    factory-method="createProcessEngine" />

注意问题 :
1、 MySQ整合,需要使用
org.hibernate.dialect.MySQL5InnoDBDialect 方言
2、 JBPM 依赖 juel jar包, 会和 tomcat发布/lib/el-api.jar 冲突, 解决将三个jar放入tomcat/lib,不要放入项目WEB-INF/lib

1.2. 流程定义管理 (与业务无关)

1.2.1. 可以通过模块,将业务流程部署到项目中 ,上传zip压缩包

宅急送 项目第十二天 项目总结_第1张图片

1.2.2. 流程设计

在线设计器 和 线下设计器 ,通过设计 生成 jpdl.xml 和 png ,在线设计器直接部署,线下设计器,需要上传zip压缩包!

宅急送 项目第十二天 项目总结_第2张图片

1.2.3. 流程定义查看

宅急送 项目第十二天 项目总结_第3张图片

1.2.4. 流程图查看

宅急送 项目第十二天 项目总结_第4张图片

1.3. 如何启动流程 ?

不同业务流程,启动时,方式不同

中转配送流程,通过 工作单审批 功能, 审批工作单,启动中转流程

这里写图片描述

通过 key 启动 ,默认启动相同 key 最高版本的流程
在流程实例,关联流程变量 ZhongZhuanInfo , 关联流程中 所有任务节点对应 数据

1.4. 任务节点,谁来办理

任务节点,使用 candidate-groups 组任务办理方式 (要根据业务使用 swimlanes)
将系统用户角色管理 和 JBPM用户和组关联 起来!

添加系统用户,添加JBPM的用户
添加系统角色,添加JBPM的用户组
为用户授予角色, 完成JBPM 用户 和 组关系建立

1.5. 任务办理

组任务查看 —- 拾取组任务查看 — 个人任务 — 个人任务 办理

1.5.1. 如何将页面中显示,流程实例变量信息

服务器查询任务列表 List ,但是Task接口没有获取流程变量方法,使用 TaskImpl 实现类 API ,显示流程业务数据 !

1.5.2. 在任务列表,显示所有流程对应任务,如果跳转到不同的页面办理?

通过 节点 form 属性,执行任务办理表单(页面), 通过 Task对象获得form页面, 点击办理时,跳转到不同页面办理

1.5.3. 办理任务时,服务器如何操作

将业务数据,关联PO对象,进行持久化
将业务数据,关联流程实例上
办理任务,流转自动流转

在办理中转环节任务时,使用自由流转技术(动态Transition), 通过当前节点,流向任何节点

面试题 : 如果流程已经写好了,需要在流程中 新增一个节点,如何做 ?
方案一: 修改 流程图,重新发布,版本+1 ,再次启动该流程 使用新流程定义 (问题, 原来流程 无法使用 新流程定义 )
方案二 : 修改已经发布的流程定义 ,数据保存 jbpm4_lob 表,是二进制blob ,先通过数据 读取blob,成为 InputStream , 使用 dom4j 加载到内存 ,使用dom4j 为流程添加新节点 ,将内存数据回显 lob表,流程被修改

2. 完成中转配送流程 剩余节点任务

入库、出库、配送签收 三个任务节点 办理

宅急送 项目第十二天 项目总结_第5张图片

当办理入库任务,跳转 instore_complete.jsp
当办理出库任务,跳转 outstore_complete.jsp
当办理配送签收任务时,跳转 receiveinfo_complete.jsp

编写 三个任务节点 办理的业务代码
入库, TaskAction 提供 instorecomplete 方法
出库: TaskAction 提供 outstorecomplete 方法
配送签收 : TaskAction 提供 receiveinfocomplete 方法

在 BaseService 注入 inStoreDAO、outStoreDAO、receiveGoodsInfoDAO

办理入库任务示例代码:

宅急送 项目第十二天 项目总结_第6张图片

配置结果集

<result name="instorecompleteSUCCESS" type="redirectAction">task_findpersonaltaskresult>
<result name="outstorecompleteSUCCESS" type="redirectAction">task_findpersonaltaskresult>
<result name="receiveinfocompleteSUCCESS" type="redirectAction">task_findpersonaltaskresult>

3. 流程实例管理模块

问题: 如何查看正在的运行实例? 如何查看已经完成流程? 如何查看流程实例变量? 如何流程实例运行到了哪个节点 ?
查看正在运行流程实例信息,jbpm4_execution 表 —- ExecutionService

这里写图片描述

查看已经完成流程实例信息,jbpm4_hist_procinst表 — HistoryService

这里写图片描述

3.1. 查看正在运行流程实例信息

/WEB-INF/pages/workflow/processinstance.jsp 流程实例列表页面

修改 admin.jsp 系统菜单

{ "id":"1005", "pId":"100", "name":"查看正在运行的任务", 
"t":"","page":"processinstance_list.action"}

编写服务器代码 ProcessInstanceAction

public class ProcessInstanceAction extends BaseAction {
}

编写list方法,查看所有正在运行流程实例信息

// 获得ExecutionService
ExecutionService executionService = processEngine.getExecutionService();
ProcessInstanceQuery query = executionService.createProcessInstanceQuery();
List processInstances = query.list();

配置结果集


<action name="processinstance_*" class="processInstanceAction" method="{1}">
    <result name="listSUCCESS">/WEB-INF/pages/workflow/processinstance.jspresult>
action>

问题: 在显示流程实例列表时,能否显示业务数据呢?
ProcessInstance 接口并没有提供 业务数据显示方法, 可以看 ExecutionImpl 实现类 API

宅急送 项目第十二天 项目总结_第7张图片

显示业务数据时,控制datagrid 自动换行

这里写图片描述

3.2. 实例流程图查看

除了显示流程图之外,绘制红色标记框,标记当前节点

3.2.1. 弹出窗口,显示页面

function show(processInstacneId){
    // 弹出页面 
window.showModalDialog("${pageContext.request.contextPath}/processinstance_showpng.action?processInstacneId="+processInstacneId);
}

先根据 实例id ,查询 发布id 和图片name

在 ProcessInstanceAction 添加 showpng 方法

宅急送 项目第十二天 项目总结_第8张图片

跳转 viewpng.jsp

<result name="showpngSUCCESS">/WEB-INF/pages/workflow/viewpng.jspresult> 

3.2.2. 通过 img 标签,引用流程图

"${pageContext.request.contextPath }/processdefinition_viewpng.action
    ?deploymentId=${deploymentId}&imageResourceName=${imageResourceName}" />

3.2.3. 绘制红色标记框

从 JBPM中获得当前任务节点坐标,绘制红框
RepositoryService 提供

宅急送 项目第十二天 项目总结_第9张图片

问题: 一个流程有几个当前活动节点 ?
不一定是一个 ,因为 fork/join

获得活动名称

这里写图片描述

宅急送 项目第十二天 项目总结_第10张图片

4. 项目开发中异常处理策略

4.1. 异常可以配置友好错误页面

4.1.1. 配置 web.xml

<error-page>
    <error-code>404error-code>
    <location>/404.jsplocation>
 error-page>

4.1.2. 在struts.xml 配置错误页面

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

<global-results>
    <result name="error">/error.jspresult>
global-results>

问题: 只是使用 友好页面,控制用户感受,进行异常处理,不够灵活和细粒度

4.2. 使用代理机制,struts2定义拦截器控制异常

public class MyExceptionInterceptor extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        String result = null;
        try {
            result = invocation.invoke();
        } catch (Exception e) {
            // 进行异常的捕获和处理
            result = "error";
        }
        return result;
    }
}
<interceptor-stack name="privilegeStack">
    <interceptor-ref name="myexception">interceptor-ref> 
    <interceptor-ref name="defaultStack">interceptor-ref>
    <interceptor-ref name="login">interceptor-ref>
    <interceptor-ref name="privilege">interceptor-ref>
interceptor-stack>

在异常拦截器,发生异常后,进行细节处理 (记录日志、发送邮件)

4.3. 在企业开发中,如果 Service 层 和 DAO层 ,发生异常,是 catch 和 throws ?

能够解决异常,进行捕获解决
如果异常无法解决,是否直接抛出? 否定

举例 DAO层发生SQL异常, 抛给Service 层,Service层根本无能力解决
企业会 先catch 这个异常, 转换为一个业务运行异常 抛出

MoneyNotEnoughException 余额不足异常

当抛出具体业务异常, 上层更知道如何处理 !

4.4. 服务器对于ajax和非ajax 请求,处理方式不同

非ajax请求 ,返回 错误页面
ajax 请求,返回 json 异常信息

根据 请求头信息

这里写图片描述

来分辨是否为 ajax 请求

// 判断是否为ajax请求
if (ServletActionContext.getRequest().getHeader("X-Requested-With") != null) {
    // ajax 请求
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("result", "failure");
    map.put("msg", "修改密码失败," + e.getMessage());
    ActionContext.getContext().put("map", map);
    result = "errorjson";
} else {
    result = "error";
}

配置 json 结果页面

<result name="errorjson" type="json">
    <param name="root">mapparam>
result>

5. 二级缓存在项目中的应用

5.1. 分析二级缓存应用

问题: 什么是二级缓存 ? 二级缓存是如何存储的? 二级缓存如何使用 ?
Hibernate 提供一级缓存(Session 范围)和二级缓存(SessionFactory 范围), 一级缓存内置,

SessionFactory 缓存两部分内容 ,一部分 cfg文件、hbm文件配置内容 (命名查询) , 另一部分 数据缓存 (需要配置,引用外部框架 )

二级缓存, 支持 EhCache 、OSCache 、JBOSS Cache

Session 的缓存,只能在一个线程中使用 ,在开发中,将Session与线程绑定, 一个线程对应一个Session ,

Session 中数据不能在多次用户请求,不同用户请求 不能共享, 使用SessionFactory 缓存,实现多个用户,多次请求之间 共享数据 。

二级缓存,存储以对象散装数据 存储的,访问二级缓存的数据,查询条件 是 id !

查询缓存 和 二级缓存区别? 二级缓存缓存整个对象属性数据,查询条件是id, 查询缓存可以缓存任何查询结果,查询条件 是 SQL语句

二级缓存使用 :
1、 引入 jar包
2、引入配置文件
3、 在hibernate开启二级缓存
4、 配置二级缓存提供商
5、配置缓存策略

BOS项目 应用场景: 每个用户登录,需要将用户具有角色和权限查询出,保存到Session中 ,用户具有角色信息会重复, 角色对应权限信息 也会重复

5.2. 在项目中使用二级缓存

以EhCache 为例

5.2.1. 导入 jar 包

这里写图片描述

使用 maven 导入 ehcache的jar 包



        <dependency>
       <groupId>net.sf.ehcachegroupId>
       <artifactId>ehcacheartifactId>
       <version>1.5.0version>
        dependency>

        <dependency>
    <groupId>org.hibernategroupId>
    <artifactId>hibernate-ehcacheartifactId>
    <version>3.6.10.Finalversion>
dependency>

5.2.2. 引入EhCache配置文件

从 jar 包中找
将 jar 中 ehcache-failsafe.xml 复制 项目 resources 目录, 改名 ehcache.xml

5.2.3. 开启二级缓存

配置 applicationContext-common.xml


<prop key="hibernate.cache.use_second_level_cache">trueprop>

5.2.4. 配置二级缓存提供商


<prop key="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
prop>

5.2.5. 配置对哪些数据缓存?

配置数据 缓存并发策略
可以在 cfg文件统一配置,可以在hbm文件配置

缓存分为类级别和集合级别的缓存
配置 Role.hbm.xml


<set name="functions" table="role_function">
    <cache usage="read-write"/>
    <key column="role_id">key>
    <many-to-many class="cn.itcast.bos.domain.auth.Function" column="function_id">many-to-many>
set>

集合级别的缓存,依赖类级别的缓存

配置Function.hbm.xml

<class name="cn.itcast.bos.domain.auth.Function" table="auth_function">
    <cache usage="read-write"/>

5.3. 准备测试数据

两个角色 role1 role2 ,三个用户 aaa bbb ccc
aaa 和 bbb 属于 role1,ccc 属于role2
role1 和 role2 权限由交叉

5.4. 配置log4j 只打开二级缓存日志,关闭其他日志

log4j.rootLogger=OFF, stdout
log4j.logger.org.hibernate.cache=debug

5.5. 二级缓存的性能监控


<prop key="hibernate.generate_statistics">trueprop>

通过SessionFactory API 获得 监控参数

// 统计对象
Statistics statistics = sessionFactory.getStatistics();

System.out.println("命中次数:" + statistics.getSecondLevelCacheHitCount() + ", 丢失次数:" + statistics.getSecondLevelCacheMissCount());

其它

课前资料

这里写图片描述

里面有大量相关技术的资料

补充资料

宅急送 项目第十二天 项目总结_第11张图片

ExtJS前端

这里写图片描述

FCKEditor在线HTML编辑器

这里写图片描述

jfreechart报表图表

宅急送 项目第十二天 项目总结_第12张图片

maven

宅急送 项目第十二天 项目总结_第13张图片

quartz定时任务快速入门

这里写图片描述

服务器负载性能

这里写图片描述

索引

这里写图片描述

课后资料

宅急送 项目第十二天 项目总结_第14张图片

实例流程图查看原理

宅急送 项目第十二天 项目总结_第15张图片

二级缓存使用分析

宅急送 项目第十二天 项目总结_第16张图片

二级缓存存储结构

宅急送 项目第十二天 项目总结_第17张图片

课程视频内容

宅急送 项目第十二天 项目总结_第18张图片

宅急送 项目第十二天 项目总结_第19张图片

你可能感兴趣的:(宅急送项目)