基于事件的网关 Event­based Gateway

作者:Jesai

时间:2018年4月21日 21:19:30

什么是事件网关?

基于事件的网关,允许基于事件做选择。

事件网关的执行原理?

网关的每一条出口顺序流,都需要连接至一个捕获中间事件。当流程执行到达基于事件的网关时,网关类似等待状态地动作:执行被暂停。并且,为每一条出口顺序流,创建一个事件订阅。流程的走向完全是由于中间事件的选择。而由哪一个事件来决定流程的走向则是由最先触发的事件来决定的。

事件网关和其他网关的区别

请注意基于事件的网关,其出口顺序流与一般的顺序流不同。这些顺序流从不实际被执行。相反,它们允许流程引擎决定,当执行到达一个基于事件的网关时,需要订阅什么事件。

约束:

1)一个基于事件的网关,必须有两条或更多的出口顺序流。
2)基于事件的网关,只能连接至 intermediateCatchEvent(捕获中间事件) 类型的元素(Activiti不支持基于事件的网关后,连接接收任务,Receive Task)。
3)连接至基于事件的网关的 intermediateCatchEvent ,必须只有一个入口顺序流。

图标:

基于事件的网关,用内部带有特殊图标的网关(菱形)表示。

定义:

用于定义基于事件的网关的XML元素为

 eventBasedGateway 。

流程设计

我们设计一个有三个走向(分支)的事件网关。后面紧接着定时器事件、信号事件和消息事件。然后在分别跟着三个task任务。三个task任务可以告知我们流程是怎么走的。Task任务上面的监听器可以更加详细的让我们知道整个流程的执行过程。

流程配置

时间事件的CRON表达式配置

R4/2018-05-27T14:42/PT1M

这个表达式的意思是从2018-05-27日的14点42分开始,每分钟执行一次,一共执行4次。

设计流程表达式的时候设置CRON表达式。

在流程里面定义新增一个信号引用,并在信号事件里面引用。

在流程定义里面定义一个消息事件,并在消息事件里面去引用。

给时间事件增加一个执行监听器和任务监听器

给信号事件增加一个执行监听器和任务监听器

给消息事件增加一个执行监听器和任务监听器

在上面所示,每一个任务我们都配置了执行监听器和任务执行器。你会发现,我配置的类都是同一个类。你就往下看,你会发现,我这三个任务里面的执行监听器和任务监听器执行的代码都是一样的。唯一不同的是任务监听器实现的是TaskListener,执行监听器实现的是ExecutionListener。细心的就会发现,监听器实现的事件也不一样。任务监听器的事件是Create···,执行监听器的事件是:start···。后面我将会有一个环节专门介绍这两者的区别。

流程定义:

 <?xml version='1.0' encoding='UTF-8'?>

 <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://activiti.org/test">

   <signal id="Singal" name="Singal" />

   <message id="Message" name="Message" />

   <process id="EventGateWay" name="事件网关" isExecutable="true">

     <startEvent id="sid-23B0551D-A771-4EE7-84D5-2FDE120C597F" />

     <endEvent id="sid-CFDD8A12-89F8-4114-8781-5506EC5F74D6" />

     <exclusiveGateway id="sid-5474F8B6-BDE6-4BCD-9792-9B06B283519C" />

     <intermediateCatchEvent id="sid-4F686F4E-C053-47EC-8FBF-028C8561B63B" name="定时器事件">

       <timerEventDefinition>

         <timeCycle>R4/2018-05-28T15:13/PT1M</timeCycle>

       </timerEventDefinition>

     </intermediateCatchEvent>

     <eventBasedGateway id="sid-3C4E8072-F03C-45B0-BF54-0842204B5984" />

     <intermediateCatchEvent id="Singals" name="信号事件">

       <signalEventDefinition signalRef="Singal" />

     </intermediateCatchEvent>

     <sequenceFlow id="sid-ADE687E7-F6C2-491D-A9DD-3A4274C2E67F" sourceRef="sid-3C4E8072-F03C-45B0-BF54-0842204B5984" targetRef="Singals" />

     <sequenceFlow id="sid-398D02FE-4E17-4683-A2AD-DFC2B834A674" sourceRef="sid-23B0551D-A771-4EE7-84D5-2FDE120C597F" targetRef="sid-3C4E8072-F03C-45B0-BF54-0842204B5984" />

     <intermediateCatchEvent id="Messages" name="消息事件">

       <messageEventDefinition messageRef="Message" />

     </intermediateCatchEvent>

     <userTask id="sid-C3D1F9C5-C11D-4A09-9EEC-F28FA2759449" name="定时器事件触发了" activiti:assignee="admin">

       <extensionElements>

         <activiti:executionListener event="start" class="light.mvc.workflow.taskListener.TimerListenerImpl" />

         <activiti:taskListener event="create" class="light.mvc.workflow.taskListener.TimerListenerImpl" />

       </extensionElements>

     </userTask>

     <userTask id="sid-88AF77E1-D75B-4085-A244-1A772C42893E" name="信号事件触发了" activiti:assignee="admin">

       <extensionElements>

         <activiti:executionListener event="start" class="light.mvc.workflow.taskListener.SingalListenerImpl" />

         <activiti:taskListener event="create" class="light.mvc.workflow.taskListener.SingalListenerImpl" />

       </extensionElements>

     </userTask>

     <userTask id="sid-881FDB4C-571D-4330-A753-7C1BC87C3130" name="消息事件触发了" activiti:assignee="admin">

       <extensionElements>

         <activiti:executionListener event="start" class="light.mvc.workflow.taskListener.MessageListenerImpl" />

         <activiti:taskListener event="create" class="light.mvc.workflow.taskListener.MessageListenerImpl" />

       </extensionElements>

     </userTask>

     <sequenceFlow id="sid-A96EE6F9-F2E8-4B0B-8128-0808651C69AC" sourceRef="sid-5474F8B6-BDE6-4BCD-9792-9B06B283519C" targetRef="sid-CFDD8A12-89F8-4114-8781-5506EC5F74D6" />

     <sequenceFlow id="sid-C4CD2E72-679C-4AB4-87EA-F364B033A8B6" sourceRef="sid-4F686F4E-C053-47EC-8FBF-028C8561B63B" targetRef="sid-C3D1F9C5-C11D-4A09-9EEC-F28FA2759449" />

     <sequenceFlow id="sid-F4CA6F5B-B634-4D59-9824-B4F98634C6A1" sourceRef="Singals" targetRef="sid-88AF77E1-D75B-4085-A244-1A772C42893E" />

     <sequenceFlow id="sid-2B33C971-D5F7-4CF9-85FF-F8264BA62600" sourceRef="sid-88AF77E1-D75B-4085-A244-1A772C42893E" targetRef="sid-5474F8B6-BDE6-4BCD-9792-9B06B283519C" />

     <sequenceFlow id="sid-6B3C1D12-6792-476E-ABFA-2EC780C20B5F" sourceRef="Messages" targetRef="sid-881FDB4C-571D-4330-A753-7C1BC87C3130" />

     <sequenceFlow id="sid-DDCEBFC5-7E85-4738-94D7-7D0E6A678C8C" sourceRef="sid-3C4E8072-F03C-45B0-BF54-0842204B5984" targetRef="sid-4F686F4E-C053-47EC-8FBF-028C8561B63B" />

     <sequenceFlow id="sid-ED0B6AA2-8677-4791-AD6B-637553A690F1" sourceRef="sid-3C4E8072-F03C-45B0-BF54-0842204B5984" targetRef="Messages" />

     <sequenceFlow id="sid-308B7959-1F2B-43A9-8237-893103EB7B7D" sourceRef="sid-C3D1F9C5-C11D-4A09-9EEC-F28FA2759449" targetRef="sid-5474F8B6-BDE6-4BCD-9792-9B06B283519C" />

     <sequenceFlow id="sid-E9416900-EBFC-4DB2-8A49-495BBE0C5B96" sourceRef="sid-881FDB4C-571D-4330-A753-7C1BC87C3130" targetRef="sid-5474F8B6-BDE6-4BCD-9792-9B06B283519C" />

   </process>

   <bpmndi:BPMNDiagram id="BPMNDiagram_EventGateWay">

     <bpmndi:BPMNPlane bpmnElement="EventGateWay" id="BPMNPlane_EventGateWay">

       <bpmndi:BPMNShape bpmnElement="sid-23B0551D-A771-4EE7-84D5-2FDE120C597F" id="BPMNShape_sid-23B0551D-A771-4EE7-84D5-2FDE120C597F">

         <omgdc:Bounds height="30.0" width="30.0" x="135.0" y="195.0" />

       </bpmndi:BPMNShape>

       <bpmndi:BPMNShape bpmnElement="sid-CFDD8A12-89F8-4114-8781-5506EC5F74D6" id="BPMNShape_sid-CFDD8A12-89F8-4114-8781-5506EC5F74D6">

         <omgdc:Bounds height="28.0" width="28.0" x="870.0" y="196.0" />

       </bpmndi:BPMNShape>

       <bpmndi:BPMNShape bpmnElement="sid-5474F8B6-BDE6-4BCD-9792-9B06B283519C" id="BPMNShape_sid-5474F8B6-BDE6-4BCD-9792-9B06B283519C">

         <omgdc:Bounds height="40.0" width="40.0" x="750.0" y="190.00000487674356" />

       </bpmndi:BPMNShape>

       <bpmndi:BPMNShape bpmnElement="sid-4F686F4E-C053-47EC-8FBF-028C8561B63B" id="BPMNShape_sid-4F686F4E-C053-47EC-8FBF-028C8561B63B">

         <omgdc:Bounds height="31.0" width="31.0" x="390.0" y="90.0" />

       </bpmndi:BPMNShape>

       <bpmndi:BPMNShape bpmnElement="sid-3C4E8072-F03C-45B0-BF54-0842204B5984" id="BPMNShape_sid-3C4E8072-F03C-45B0-BF54-0842204B5984">

         <omgdc:Bounds height="40.0" width="40.0" x="240.0" y="190.0" />

       </bpmndi:BPMNShape>

       <bpmndi:BPMNShape bpmnElement="Singals" id="BPMNShape_Singals">

         <omgdc:Bounds height="30.0" width="30.0" x="390.0" y="195.0" />

       </bpmndi:BPMNShape>

       <bpmndi:BPMNShape bpmnElement="Messages" id="BPMNShape_Messages">

         <omgdc:Bounds height="30.0" width="30.0" x="390.5" y="295.0" />

       </bpmndi:BPMNShape>

       <bpmndi:BPMNShape bpmnElement="sid-C3D1F9C5-C11D-4A09-9EEC-F28FA2759449" id="BPMNShape_sid-C3D1F9C5-C11D-4A09-9EEC-F28FA2759449">

         <omgdc:Bounds height="80.0" width="100.0" x="555.0" y="65.5" />

       </bpmndi:BPMNShape>

       <bpmndi:BPMNShape bpmnElement="sid-88AF77E1-D75B-4085-A244-1A772C42893E" id="BPMNShape_sid-88AF77E1-D75B-4085-A244-1A772C42893E">

         <omgdc:Bounds height="80.0" width="100.0" x="555.0" y="170.0" />

       </bpmndi:BPMNShape>

       <bpmndi:BPMNShape bpmnElement="sid-881FDB4C-571D-4330-A753-7C1BC87C3130" id="BPMNShape_sid-881FDB4C-571D-4330-A753-7C1BC87C3130">

         <omgdc:Bounds height="80.0" width="100.0" x="555.0" y="270.0" />

       </bpmndi:BPMNShape>

       <bpmndi:BPMNEdge bpmnElement="sid-398D02FE-4E17-4683-A2AD-DFC2B834A674" id="BPMNEdge_sid-398D02FE-4E17-4683-A2AD-DFC2B834A674">

         <omgdi:waypoint x="165.0" y="210.0000003694503" />

         <omgdi:waypoint x="240.0000022167019" y="210.0000022167019" />

       </bpmndi:BPMNEdge>

       <bpmndi:BPMNEdge bpmnElement="sid-2B33C971-D5F7-4CF9-85FF-F8264BA62600" id="BPMNEdge_sid-2B33C971-D5F7-4CF9-85FF-F8264BA62600">

         <omgdi:waypoint x="655.0" y="210.00000147780108" />

         <omgdi:waypoint x="750.0000005911204" y="210.00000428562313" />

       </bpmndi:BPMNEdge>

       <bpmndi:BPMNEdge bpmnElement="sid-A96EE6F9-F2E8-4B0B-8128-0808651C69AC" id="BPMNEdge_sid-A96EE6F9-F2E8-4B0B-8128-0808651C69AC">

         <omgdi:waypoint x="789.5840716200719" y="210.41593325667168" />

         <omgdi:waypoint x="870.0001358465071" y="210.06167401189862" />

       </bpmndi:BPMNEdge>

       <bpmndi:BPMNEdge bpmnElement="sid-F4CA6F5B-B634-4D59-9824-B4F98634C6A1" id="BPMNEdge_sid-F4CA6F5B-B634-4D59-9824-B4F98634C6A1">

         <omgdi:waypoint x="420.0" y="210.0" />

         <omgdi:waypoint x="555.0" y="210.0" />

       </bpmndi:BPMNEdge>

       <bpmndi:BPMNEdge bpmnElement="sid-ED0B6AA2-8677-4791-AD6B-637553A690F1" id="BPMNEdge_sid-ED0B6AA2-8677-4791-AD6B-637553A690F1">

         <omgdi:waypoint x="260.5" y="229.5" />

         <omgdi:waypoint x="260.5" y="310.0" />

         <omgdi:waypoint x="390.5" y="310.0" />

       </bpmndi:BPMNEdge>

       <bpmndi:BPMNEdge bpmnElement="sid-308B7959-1F2B-43A9-8237-893103EB7B7D" id="BPMNEdge_sid-308B7959-1F2B-43A9-8237-893103EB7B7D">

         <omgdi:waypoint x="655.0" y="105.5" />

         <omgdi:waypoint x="770.0" y="105.5" />

         <omgdi:waypoint x="770.0" y="190.00000487674356" />

       </bpmndi:BPMNEdge>

       <bpmndi:BPMNEdge bpmnElement="sid-ADE687E7-F6C2-491D-A9DD-3A4274C2E67F" id="BPMNEdge_sid-ADE687E7-F6C2-491D-A9DD-3A4274C2E67F">

         <omgdi:waypoint x="279.56597222222223" y="210.43402777777777" />

         <omgdi:waypoint x="390.00008979696906" y="210.0519028034707" />

       </bpmndi:BPMNEdge>

       <bpmndi:BPMNEdge bpmnElement="sid-DDCEBFC5-7E85-4738-94D7-7D0E6A678C8C" id="BPMNEdge_sid-DDCEBFC5-7E85-4738-94D7-7D0E6A678C8C">

         <omgdi:waypoint x="260.5" y="190.5" />

         <omgdi:waypoint x="260.5" y="106.0" />

         <omgdi:waypoint x="390.0" y="106.0" />

       </bpmndi:BPMNEdge>

       <bpmndi:BPMNEdge bpmnElement="sid-C4CD2E72-679C-4AB4-87EA-F364B033A8B6" id="BPMNEdge_sid-C4CD2E72-679C-4AB4-87EA-F364B033A8B6">

         <omgdi:waypoint x="421.99994949646396" y="105.95979912186817" />

         <omgdi:waypoint x="555.0" y="105.62562814070353" />

       </bpmndi:BPMNEdge>

       <bpmndi:BPMNEdge bpmnElement="sid-E9416900-EBFC-4DB2-8A49-495BBE0C5B96" id="BPMNEdge_sid-E9416900-EBFC-4DB2-8A49-495BBE0C5B96">

         <omgdi:waypoint x="655.0" y="310.0" />

         <omgdi:waypoint x="770.0" y="310.0" />

         <omgdi:waypoint x="770.0" y="230.00000487674356" />

       </bpmndi:BPMNEdge>

       <bpmndi:BPMNEdge bpmnElement="sid-6B3C1D12-6792-476E-ABFA-2EC780C20B5F" id="BPMNEdge_sid-6B3C1D12-6792-476E-ABFA-2EC780C20B5F">

         <omgdi:waypoint x="420.5" y="310.0" />

         <omgdi:waypoint x="555.0" y="310.0" />

       </bpmndi:BPMNEdge>

     </bpmndi:BPMNPlane>

   </bpmndi:BPMNDiagram>

 </definitions>

流程监听类

1.  MessageListenerImpl

 package light.mvc.workflow.taskListener;

 import org.activiti.engine.delegate.DelegateExecution;

 import org.activiti.engine.delegate.DelegateTask;

 import org.activiti.engine.delegate.ExecutionListener;

 import org.activiti.engine.delegate.JavaDelegate;

 import org.activiti.engine.delegate.TaskListener;

 public class MessageListenerImpl implements TaskListener,ExecutionListener {

 @Override

 public void notify(DelegateTask arg0) {

      System.out.println("Message Event Task Is Running");

 }

 @Override

 public void notify(DelegateExecution arg0) throws Exception {

      // TODO Auto-generated method stub

      System.out.println("Message Event Execution Is Running");

 }

 }

2.  SingalListenerImpl

 package light.mvc.workflow.taskListener;

 import org.activiti.engine.delegate.DelegateExecution;

 import org.activiti.engine.delegate.DelegateTask;

 import org.activiti.engine.delegate.ExecutionListener;

 import org.activiti.engine.delegate.JavaDelegate;

 import org.activiti.engine.delegate.TaskListener;

 public class SingalListenerImpl implements  TaskListener,ExecutionListener  {

     @Override

     public void notify(DelegateTask arg0) {

         System.out.println("Singal Event Task Is Running");

     }

     @Override

     public void notify(DelegateExecution arg0) throws Exception {

         // TODO Auto-generated method stub

         System.out.println("Singal Event Execution Is Running");

     }

 }

3.  TimerListenerImpl

 package light.mvc.workflow.taskListener;

 import org.activiti.engine.delegate.DelegateExecution;

 import org.activiti.engine.delegate.DelegateTask;

 import org.activiti.engine.delegate.ExecutionListener;

 import org.activiti.engine.delegate.JavaDelegate;

 import org.activiti.engine.delegate.TaskListener;

 public class TimerListenerImpl implements TaskListener,ExecutionListener {

 @Override

 public void notify(DelegateTask arg0) {

      System.out.println("Timer Event Task Is Running");

 }

 @Override

 public void notify(DelegateExecution arg0) throws Exception {

      // TODO Auto-generated method stub

      System.out.println("Timer Event Execution Is Running");

 }

 }

通过以上代码,我们会发现,其实代码都很简单,只是往控制台打印一句话,告诉我们,这个网关事件是怎么走的。

我们启动流程,稍微等待时间,就会发现流程自动往下执行了。此时,定时事件已经触发。

通过执行的顺序,你会发现是先执行Execution ,再执行Task。由此可见。执行监听器比任务监听器更早触发。

执行结果:

1.定时器(时间)事件触发

待办任务告诉我们,定时器事件触发了。

流程跟踪图也告诉我们定时器事件触发。

这时,完成定时器事件触发了的任务,该流程实例就全部结束。

2信号事件触发(需要重新启动流程,因为上一个流程已经结束)

我们通过一个单元测试模拟信号,让信号事件触发。

 /**触发信号事件*/

     @Test

     public void completeSingal(){

         ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

         List<Execution> executions =  processEngine.getRuntimeService().createExecutionQuery()

            .signalEventSubscriptionName("Singal")

            .list();

         for(Execution e:executions){

             processEngine.getRuntimeService().signalEventReceived("Singal", e.getId());

         }

     }

通过控制台打印消息,告诉我们信号事件已经触发。

待办任务告诉我们信号事件触发了。

流程跟踪图告诉我们信号事件触发了。

3.  消息事件触发

单元测试模拟消息事件触发。

   /**触发消息事件*/

     @Test

     public void completeMessage(){

         ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

         List<Execution> executions =  processEngine.getRuntimeService().createExecutionQuery()

            .messageEventSubscriptionName("Message")

            .list();

         for(Execution e:executions){

             processEngine.getRuntimeService().messageEventReceived("Message", e.getId());

         }

 }

控制台打印的消息告诉我们消息事件已经触发了。

待办任务告诉我们消息事件已经触发

流程跟踪图告诉我们消息事件已经触发

Activiti交流QQ群:634320089

基于事件的网关 Event­based Gateway的更多相关文章

  1. 微服务中的 API 网关(API Gateway)

    API 网关(API Gateway)提供高性能.高可用的 API 托管服务,帮助用户对外开放其部署在 ECS.容器服务等云产品上的应用,提供完整的 API 发布.管理.维护生命周期管理.用户只需进行 ...

  2. 基于“事件”驱动的领域驱动设计(DDD)框架分析

    摘抄自 从去年10月份开始,学了几个月的领域驱动设计(Domain Driven Design,简称DDD).主要是学习领域驱动设计之父Eric Evans的名著:<Domain-driven ...

  3. 一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库 RxJava,相当好

    https://github.com/ReactiveX/RxJava https://github.com/ReactiveX/RxAndroid RX (Reactive Extensions,响 ...

  4. Event-based Asynchronous Pattern Overview基于事件的异步模式概览

    https://msdn.microsoft.com/zh-cn/library/wewwczdw(v=vs.110).aspx Applications that perform many task ...

  5. 第一章、C#委托和事件(Delegate、Event、EventHandler、EventArgs)

    第一章.C#委托和事件(Delegate.Event.EventHandler.EventArgs) 分类: 学习笔记-C#网络编程2012-12-08 14:10 7417人阅读 评论(3) 收藏  ...

  6. ORACLE调度之基于事件的调度(二)【weber出品】

    一.回顾 调度分基于时间的调度和基于事件的调度. 稍微复习一下前面的只是请浏览:<ORACLE调度之基于时间的调度(一)[weber出品]> 二.知识补充 1.队列:一种数据结构,就像一根 ...

  7. 深入理解JavaScript的事件循环(Event Loop)

    一.什么是事件循环 JS的代码执行是基于一种事件循环的机制,之所以称作事件循环,MDN给出的解释为 因为它经常被用于类似如下的方式来实现 while (queue.waitForMessage()) ...

  8. C#中的异步调用及异步设计模式(三)——基于事件的异步模式

    四.基于事件的异步模式(设计层面) 基于事件的C#异步编程模式是比IAsyncResult模式更高级的一种异步编程模式,也被用在更多的场合.该异步模式具有以下优点: ·                 ...

  9. 【温故知新】C#基于事件的异步模式(EAP)

    在开发winform和调用asp.net的web service引用的时候,会出现许多命名为 MethodNameAsync 的方法. 例如: winform的按钮点击 this.button1.Cl ...

随机推荐

  1. java UDP传输

    ①:只要是网络传输,必须有socket . ②:数据一定要封装到数据包中,数据包中包括目的地址.端口.数据等信息. 直接操作udp不可能,对于java语言应该将udp封装成对象,易于我们的使用,这个对 ...

  2. H3C FTP双TCP连接方式

  3. Linux 内核硬件抽象

    我们结束 PCI 的讨论, 通过快速看一下系统如何处理在市场上的多种 PCI 控制器. 这只 是一个信息性的小节, 打算来展示给好奇的读者, 内核的面向对象分布如何向下扩展到最 低层. 用来实现硬件抽 ...

  4. WPF实现软键盘

    wpf 实现一个软键盘, 先发个图: 工作有需要实现一个软键盘,本来想用windows自带的软键盘凑合凑合得了,又觉得那个软键盘太大了,所以自己实现了一个. 说一下实现的思路,其实没什么思路 界面就是 ...

  5. Flask学习-Virtualenv

    http://www.pythondoc.com/ VirtualEnv Virtualenv用于同一台机器上创建多个独立的Python虚拟运行环境,多个Python环境相互独立,互不影响,它能够: ...

  6. 新书《iOS编程(第6版)》抢鲜试读

    我最近翻译了Big Nerd Ranch的<iOS编程(第6版)>.我用了大半年时间,尽可能做到通顺易懂.不足之处请大家多多指正.感谢辛苦审校的丁道骏同学. 这本书得过Jolt大奖,原书在 ...

  7. spring boot 多数据源加载原理

    git代码:https://gitee.com/wwj912790488/multiple-data-sources DynamicDataSourceAspect切面 必须定义@Order(-10) ...

  8. UE4 C++ 代码编译方式

    Unreal 有一个非常酷的特性 —> 不必关闭编辑器就可以编译 C++ 更改! 有两种方法可以达到这个目的: 1.直接点击编辑器主工具栏中的 编译(Compile) 按钮. 2.在编辑器继续运 ...

  9. 使用struts2进行登录功能的开发

    使用struts2进行登录功能的开发 一. 设计需求 使用idea和maven开发具有登录功能的web应用,java语言,使用struts2框架. 二. 设计步骤 1.使用idea创建maven应用, ...

  10. Memcahced 缓存过期时间问题

    转载:https://help.aliyun.com/knowledge_detail/38654.html 关于设置缓存数据的过期时间,可以参考以下Memcached官方说明: An expirat ...