public abstract class AbstractMessenger extends Object
Messenger通过继承AbstractMessenger,重载事件的处理方法来提供对相应事件的响应。
限定符和类型 | 字段和说明 |
---|---|
protected InfoPlusApplication |
application
注册Messenger的
InfoPlusApplication 对象。 |
protected edu.sjtu.utils.cache.DataCache<String,List<CodeItemImpl>> |
codeTables
非共享外部代码表缓存。
|
protected boolean |
preloadCodeTables
是否预加载非共享的外部代码表。
|
protected boolean |
requireVerification
已过时。
|
protected String |
secret
流程密钥。
|
protected long |
timeout
非共享的外部代码表缓存超时时间。
|
protected String |
workflow
流程代码。
|
构造器和说明 |
---|
AbstractMessenger() |
protected edu.sjtu.utils.cache.DataCache<String,List<CodeItemImpl>> codeTables
DataCache
protected boolean requireVerification
protected String workflow
setWorkflow(String)
protected String secret
setSecret(String)
protected long timeout
默认为3600000毫秒,即1小时。一个Messenger的所有非共享外部代码表,具有相同的缓存超时时间。
setTimeout(long)
protected InfoPlusApplication application
InfoPlusApplication
对象。
此属性在Messenger注册到InfoPlusApplication
时由SDK自动设置。
protected boolean preloadCodeTables
public void setRequireVerification(boolean requireVerification)
无论设置值,此版本的SDK总是验证事件请求的认证头
requireVerification
- true - 是,false - 否public void setWorkflow(String workflow)
事件请求根据流程代码来匹配处理的Messenger,因此必须设置。
workflow
- 流程代码public void setSecret(String secret)
事件请求根据流程代码和密钥来匹配处理的Messenger,并验证事情请求的认证头是否合法,因此必须设置。
secret
- 流程密钥public void setTimeout(long timeout)
时间单位为毫秒。默认为3600000毫秒,即1小时。设置此值影响该Messenger中所有的非共享外部代码表。
timeout
- 缓存超时时间毫秒值getSuggestionData(String)
,
invalidateCodeTable(String)
public void setCodeTables(List<String> codeTables)
Messenger支持的非共享外部代码表必须先通过此方法声明,并实现getSuggestionData(String)
方法来提供数据。
非共享外部代码表优先于共享外部代码表,一个外部代码表如果在非共享外部代码表中没有找到,才会进一步在共享外部代码表中查找。
codeTables
- 非共享外部代码表代码的ListgetSuggestionData(String)
,
InfoPlusApplication.setSharedCodeTableBuilders(List)
,
InfoPlusApplication.registerSharedCodeTableBuilder(CachableDataBuilder)
public void setPreloadCodeTables(boolean preloadCodeTables)
通常非共享的外部代码表在首次表单suggest操作时才会通过调用getSuggestionData(String)
加载数据。
可以通过设置预加载把加载数据提前到Messenger初始化后立即进行,这样可以改善首次表单suggest操作时的响应速度。
preloadCodeTables
- true - 预加载,false - 不预加载。默认为false。public void registerCodeTable(String codeTable)
setCodeTables(List)
方法内部使用本方法来逐个声明非共享的外部代码表。
codeTable
- 非共享的外部代码表的代码setCodeTables(List)
protected void invalidateCodeTable(String codeTable)
此方法仅可失效非共享外部代码表缓存。
如果是共享外部代码表,可在InfoPlusApplication.getSharedCodeTables()
返回的对象上调用DataCache.invalidate(Object)
,使缓存失效。
codeTable
- 外部代码表的代码getSuggestionData(String)
protected javax.servlet.http.HttpServletRequest getRequest()
public InfoPlusResponse onInstanceStarting(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理INSTANCE_STARTING事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象public InfoPlusResponse onInstanceStarted(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理INSTANCE_STARTED事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象public InfoPlusResponse onInstanceCompleting(InfoPlusEvent e)
默认方法仅返回null。流程平台不支持此事件,所以永远不会调用。
e
- InfoPlusEvent
对象InfoPlusResponse
对象public InfoPlusResponse onInstanceCompleted(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理INSTANCE_COMPLETED事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象public InfoPlusResponse onInstanceSaving(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理INSTANCE_SAVING事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象public InfoPlusResponse onInstanceSaved(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理INSTANCE_SAVED事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象public InfoPlusResponse onInstancePrinting(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理INSTANCE_PRINTING事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象public InfoPlusResponse onInstanceExporting(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理INSTANCE_EXPORTING事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象public InfoPlusResponse onInstanceKilling(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理INSTANCE_KILLING事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象public InfoPlusResponse onInstanceKilled(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理INSTANCE_KILLED事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象public InfoPlusResponse onInstanceCompensation(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理INSTANCE_COMPENSATION事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象public InfoPlusResponse onInstanceRendering(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理INSTANCE_RENDERING事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象public final InfoPlusResponse onActionClicking(InfoPlusEvent e)
此方法不可重载,SDK提供了特殊的规则来重新分发ACTION_CLICKING事件,请参考dispatchAction(InfoPlusEvent, String)
e
- InfoPlusEvent
对象InfoPlusResponse
对象dispatchAction(InfoPlusEvent, String)
public final InfoPlusResponse onActionDoing(InfoPlusEvent e)
此方法不可重载,SDK提供了特殊的规则来重新分发ACTION_DOING事件,请参考dispatchAction(InfoPlusEvent, String)
e
- InfoPlusEvent
对象InfoPlusResponse
对象dispatchAction(InfoPlusEvent, String)
public final InfoPlusResponse onActionDone(InfoPlusEvent e)
此方法不可重载,SDK提供了特殊的规则来重新分发ACTION_DONE事件,请参考dispatchAction(InfoPlusEvent, String)
e
- InfoPlusEvent
对象InfoPlusResponse
对象dispatchAction(InfoPlusEvent, String)
public final InfoPlusResponse onStepRendering(InfoPlusEvent e)
此方法不可重载,SDK提供了特殊的规则来重新分发STEP_RENDERING事件,请参考dispatchAction(InfoPlusEvent, String)
e
- InfoPlusEvent
对象InfoPlusResponse
对象dispatchAction(InfoPlusEvent, String)
public final InfoPlusResponse onStepReviewing(InfoPlusEvent e)
此方法不可重载,SDK提供了特殊的规则来重新分发STEP_REVIEWING事件,请参考dispatchAction(InfoPlusEvent, String)
e
- InfoPlusEvent
对象InfoPlusResponse
对象dispatchAction(InfoPlusEvent, String)
public final InfoPlusResponse onStepPrinting(InfoPlusEvent e)
此方法不可重载,SDK提供了特殊的规则来重新分发STEP_PRINTING事件,请参考dispatchAction(InfoPlusEvent, String)
e
- InfoPlusEvent
对象InfoPlusResponse
对象dispatchAction(InfoPlusEvent, String)
public final InfoPlusResponse onStepExporting(InfoPlusEvent e)
此方法不可重载,SDK提供了特殊的规则来重新分发STEP_EXPORTING事件,请参考dispatchAction(InfoPlusEvent, String)
e
- InfoPlusEvent
对象InfoPlusResponse
对象dispatchAction(InfoPlusEvent, String)
public final InfoPlusResponse onStepWithdrawing(InfoPlusEvent e)
此方法不可重载,SDK提供了特殊的规则来重新分发STEP_WITHDRAWING事件,请参考dispatchAction(InfoPlusEvent, String)
e
- InfoPlusEvent
对象InfoPlusResponse
对象dispatchAction(InfoPlusEvent, String)
public final InfoPlusResponse onStepWithdrawn(InfoPlusEvent e)
此方法不可重载,SDK提供了特殊的规则来重新分发STEP_WITHDRAWN事件,请参考dispatchAction(InfoPlusEvent, String)
e
- InfoPlusEvent
对象InfoPlusResponse
对象dispatchAction(InfoPlusEvent, String)
public InfoPlusResponse onActionSaving(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理ACTION_SAVING事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象public InfoPlusResponse onActionSaved(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理ACTION_SAVED事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象protected final InfoPlusResponse dispatchAction(InfoPlusEvent e, String action)
不同于其他事件处理采用的重载对应方法来提供处理的做法,SDK对步骤级事件采用约定命名规则,并通过反射进行调用的方法。
下表列出了使用这种方法的事件以及命名规则:
事件 | 命名规则 |
---|---|
STEP_RENDERING | onStep{StepCode}Rendering |
STEP_REVIEWING | onStep{StepCode}Reviewing |
STEP_PRINTING | onStep{StepCode}Printing |
STEP_EXPORTING | onStep{StepCode}Exporting |
STEP_EXPIRING | onStep{StepCode}Expiring |
STEP_WITHDRAWING | onStep{StepCode}Action{ActionCode}Withdrawing |
STEP_WITHDRAWN | onStep{StepCode}Action{ActionCode}Withdrawn |
ACTION_CLICKING | onStep{StepCode}Action{ActionCode}Clicking |
ACTION_DOING | onStep{StepCode}Action{ActionCode}Doing |
ACTION_DONE |
onStep{StepCode}Action{ActionCode}Done toStep{TargetStepCode}Done |
StepCode为步骤的代码,在方法名中使用时首字母转为大写,其余部分保持不变。
ActionCode为动作代码,在方法名中使用时首字母转为大写,其余部分保持不变。
所有方法都应该只接受一个InfoPlusEvent
对象作为入参,并返回InfoPlusResponse
对象作为返回值。
如果对应的步骤或者动作不需要处理,对应方法名的方法可以不提供。
onStep开头的方法名中的StepCode均指事件发生的步骤,而对于ACTION_DONE事件,SDK支持调用以动作执行后到达的节点命名的方法,即toStep开头的方法名。
TargetStepCode为到达节点的代码,使用这种方法来提供事件处理需要注意:
1、ACTION_DONE事件实际由动作起始节点触发,同一个到达节点可能来自不同的起始节点,因此需要注意在所有可能的起始节点上都勾选Done事件才能保证事件处理不会遗漏。
2、一个动作的到达节点可能是多个(触发并行的情况),因此多个处理方法可能被调用,SDK不保证调用的顺序,并且仅返回最后一个处理方法的返回结果。
3、如果同时提供了onStep方法和toStep方法都能匹配ACTION_DONE事件,将先调用onStep方法,再调用toStep方法
e
- InfoPlusEvent
对象action
- 操作名称,Rendering、Doing、Done、Printing等InfoPlusResponse
对象public final InfoPlusResponse onStepExpiring(InfoPlusEvent e)
此方法不可重载,SDK提供了特殊的规则来重新分发STEP_EXPIRING事件,请参考dispatchAction(InfoPlusEvent, String)
e
- InfoPlusEvent
对象InfoPlusResponse
对象dispatchAction(InfoPlusEvent, String)
,
InfoPlusResponse.setTimer(Timer)
public final InfoPlusResponse onStepExpired(InfoPlusEvent e)
此方法不可重载,SDK提供了特殊的规则来重新分发STEP_EXPIRED事件,请参考dispatchAction(InfoPlusEvent, String)
流程平台实际不支持此事件,因此此事件不可能发生。
e
- InfoPlusEvent
对象InfoPlusResponse
对象dispatchAction(InfoPlusEvent, String)
,
InfoPlusResponse.setTimer(Timer)
public InfoPlusResponse onInstanceExpiring(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理INSTANCE_EXPIRING事件时,应该重载此方法。
e
- InfoPlusEvent
对象InfoPlusResponse
对象InfoPlusResponse.setTimer(Timer)
public InfoPlusResponse onInstanceExpired(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理INSTANCE_EXPIRED事件时,应该重载此方法。
流程平台实际不支持此事件,因此此事件不可能发生。
e
- InfoPlusEvent
对象InfoPlusResponse
对象InfoPlusResponse.setTimer(Timer)
public InfoPlusResponse onFieldChanging(InfoPlusEvent e)
默认方法仅返回null。Messenger需要处理FIELD_CHANGING事件时,应该重载此方法。
FIELD_CHANGING事件的处理中需要特别关注两点:
1、获取变化的字段。参考InfoPlusEvent.getChangingField()
、InfoPlusEvent.getChangingObject(Object)
、InfoPlusEvent.getChangingObject(Object, Class)
获取更多信息。
2、仅可以使用InfoPlusEvent.toBean(Class)
返回的表单数据实例对象,或者InfoPlusEvent.getChangingObject(Object)
、InfoPlusEvent.getChangingObject(Object, Class)
方法基于该对象获取到的对象来构造返回结果。
参考如下示例:
表单数据结构:
purchaseRequest ---- 采购申请主表单 fieldTitle ---- String, 申请标题 fieldTotalAmount ---- Double, 采购总价 groupItems ---- 重复结构,采购明细 fieldItem ---- String, 采购物品名称 fieldPrice ---- Double, 采购物品单价 fieldQuantity ---- Int, 采购物品数量Java对象定义:
//采购申请主表单 class PurchaseRequest { private String title; //申请标题 private BigDecimal totalAmount; //采购总价 private List<PurchaseItem> items; //采购明细 ... //setter & getter } //采购明细 class PurchaseItem { String itemName; //采购物品名称 BigDecimal itemPrice; //采购物品单价 Integer itemQuantity; //采购物品数量 BigDecimal itemAmount; //采购物品单项金额 ... //setter & getter }当前表单数据,Bean格式(json表达):
{ "title": "采购办公用品", "totalAmount": 65, "items": [{ "itemName": "记号笔", "itemPrice": 3, "itemQuantity": 20, "itemAmount": 50 }, { "itemName": "白板擦", "itemPrice": 5, "itemQuantity": 3, "itemAmount": 15 }] }当将"记号笔"的采购数量改变时:
public InfoPlusResponse onFieldChanging(InfoPlusEvent e) { PurchaseRequest form = e.toBean(PurchaseRequest.class); Object changedObject = null; //构造返回值的对象 if ("fieldItemQuantity".equals(e.getChangingField())) { //采购物品数量字段发生改变 //1. 重新计算单项金额(改变变化的重复字段同层其他字段) PurchaseItem item = e.getChangingObject(form); item.setItemAmount(item.getItemPrice().multiply(new item.getItemQuantity())); changedObject = item; //正确(合计金额totalAmount由前端公式计算) //2. 重新计算金额合计(改变变化的重复字段上层的字段) form.setTotalAmount(form.getItems().stream().map(PurchaseItem::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add)); changedObject = form; //正确(返回数据中包含了totalAmount字段,则该字段必须由后端计算) //3. 追加行 PurchaseItem item = new PurchaseItem(); item.setItemName("复印纸"); form.getItems().add(item); changedObject = form; //正确 changedObject = item; //错误。不能仅返回新创建的对象 //4. 删除本行 PurchaseItem item = e.getChangingObject(form); form.getItems().remove(item); changedObject = form; //正确 changedObject = item; //错误。不能仅返回删除的对象 //5. 改变其他行的字段 PurchaseItem item = form.getItems().get(0); item1.setItemName("记号笔*"); changedObject = item; //正确 changedObject = form; //也正确,但是返回数据较大,效率低 } if (changedObject == null) return null; return new InfoPlusResponse(e, changedObject); }
public InfoPlusResponse onFieldSuggesting(InfoPlusEvent e)
此方法提供对表单suggest操作的默认支持,为外部代码表提供数据。
一般Messenger不需要重载此方法来支持外部代码表,而应该根据外部代码表的使用范围决定作为非共享外部代码表还是共享外部代码表来支持。
对于非共享外部代码表,需要调用setCodeTables(List)
或registerCodeTable(String)
进行注册,并重载getSuggestionData(String)
来提供数据;
对于共享外部代码表,需要实现CachableDataBuilder
,并调用InfoPlusApplication.setSharedCodeTableBuilders(List)
或者InfoPlusApplication.registerSharedCodeTableBuilder(CachableDataBuilder)
进行注册。
如果存在特殊的需求需要完全控制对FIELD_SUGGESTING的响应,Messenger也可以重载此方法提供自定义的处理逻辑。
重载此方法后上述的非共享外部代码表和共享外部代码表支持机制将失效,开发者需自行处理InfoPlusEvent
,构造返回的InfoPlusResponse
对象。
开发者应了解FIELD_SUGGESTING事件对应了表单中suggest字段的每一次键盘输入操作,用户期待及时的响应,因此需要很高的性能要求。
流程平台对FIELD_SUGGESTING事件的响应最低时间要求是30秒,通常用户期望的响应时间应该小于2秒。
e
- InfoPlusEvent
对象InfoPlusResponse
对象InfoPlusEvent.getSuggestion()
,
InfoPlusResponse.setCodes(List)
protected List<CodeItemImpl> search(List<CodeItemImpl> list, String prefix, String parent, int pageNo, int pageSize)
list
- 检索的源数据。仅支持SDK内部实现的CodeItemImpl类的实例。prefix
- 检索的关键词。parent
- 父级代码值。如果传入null,表示不限制匹配的代码项的父级代码,否则仅当代码项的父级代码和传入值相同时,该代码项才符合检索条件。pageNo
- 返回数据的页号。pageSize
- 返回数据的分页大小。protected List<? extends CodeItem> getSuggestionData(String codeTable)
AbstractMessenger使用了特别的设计来简化外部代码表的实现。
一般情况下Messenger不需要重新实现onFieldSuggesting(InfoPlusEvent)
方法来响应FIELD_SUGGESTING事件,
而仅需要重新实现本方法来提供完整的代码表数据全集即可完成对外部代码表的支持。
AbstractMessenger的默认onFieldSuggesting(InfoPlusEvent)
实现会调用本方法来获取数据,
自动完成索引建立、数据缓存,改善表单suggest操作的性能和使用体验。
此方法返回数据的缓存时间由timeout
属性指定,缓存到期后的suggest调用会触发再次调用此方法来重新获取数据。
如果希望主动使缓存过期,可以调用invalidateCodeTable(String)
方法。
索引是指用来匹配用户的输入的数据,如果表单中suggest字段的用户输入值匹配代码项索引的前缀,则该代码项被返回供用户选择。
如果返回的代码项仅实现了CodeItem
接口,则CodeItem.getCodeId()
、CodeItem.getCodeName()
和CodeItem.getCodeDescription()
的返回值、返回值中的中文字符的全拼、返回值中的中文字符的拼音首字符均作为索引。
比如CodeItem.getCodeId()
返回"40100",CodeItem.getCodeName()
返回"网络信息中心",则索引包括: 40100,网络信息中心,wangluoxinxizhongxin,wlxxzx
如果希望自定义索引,返回的代码项可以实现CodeItemEx
接口,
通过CodeItemEx.getCodeIndexes()
方法来直接提供自定义的索引。
codeTable
- 外部代码表的代码CodeItem
的ListonFieldSuggesting(InfoPlusEvent)
,
getCachedCodeItems(String)
protected List<? extends CodeItem> getCachedCodeItems(String codeTable)
如果调用此方法时,代码表的缓存尚未建立,则触发缓存的建立。
codeTable
- 外部代码表的代码CodeItem
的Listprotected InfoPlusService getInfoPlusService()
protected String buildEAN13Code()
物品码的构造一般在表单操作时由前端代码构造,如果流程中存在不需要用户关心的物品,Messenger可以使用此方法构造新的物品码,并给物品字段赋值。
Copyright © 2024. All rights reserved.