Flowable實(shí)戰(zhàn)(一)啟動(dòng)第一個(gè)完整流程

一失尖、前言:

發(fā)現(xiàn)網(wǎng)上關(guān)于Flowable的資料基本都是淺嘗輒止,對(duì)如何構(gòu)建一個(gè)企業(yè)級(jí)的流程應(yīng)用說明很少渐苏,所以寫個(gè)實(shí)戰(zhàn)系列掀潮,希望對(duì)大家和自己,都有所幫助整以。

二胧辽、認(rèn)識(shí)Flowable

Flowable是一個(gè)使用Java編寫的輕量級(jí)業(yè)務(wù)流程引擎。

Flowable流程引擎可用于部署B(yǎng)PMN 2.0流程定義公黑,創(chuàng)建這些流程定義的流程實(shí)例,進(jìn)行查詢人断,訪問運(yùn)行中或歷史的流程實(shí)例與相關(guān)數(shù)據(jù)恶迈。

Flowable是Activiti的fork步做,即Flowable源自Activiti全度。所以可以看到将鸵,F(xiàn)lowable很多設(shè)計(jì)與實(shí)現(xiàn)顶掉,與Activiti是相同的痒筒。

開源Flowable官網(wǎng):https://www.flowable.com/open-source/

三凸克、完整實(shí)例

Flowable官網(wǎng)教程已經(jīng)提供了一個(gè)很簡(jiǎn)單的流程運(yùn)行例子萎战,是英文版蚂维。

下面的例子內(nèi)容來源于官網(wǎng)教程虫啥,已經(jīng)看過的同學(xué)可以直接跳過到下一節(jié)內(nèi)容

我們將構(gòu)建的例子是一個(gè)簡(jiǎn)單的請(qǐng)假(holiday request)流程:

  • 雇員(employee)申請(qǐng)幾天的假期

  • 經(jīng)理(manager)批準(zhǔn)或駁回申請(qǐng)

  • 我們會(huì)模擬將申請(qǐng)注冊(cè)到某個(gè)外部系統(tǒng)砸抛,并給雇員發(fā)送結(jié)果郵件

1.創(chuàng)建項(xiàng)目

打開IDEA景东,通過File -> New -> Project... -> Maven 創(chuàng)建一個(gè)新的Maven項(xiàng)目

maven.png

在下一個(gè)界面斤吐,填入項(xiàng)目名Name庄呈,GroupId 和 ArtifactId 默認(rèn)即可

projectName.png

這樣就建立了空的Maven項(xiàng)目抒痒。

2.創(chuàng)建流程引擎

為項(xiàng)目添加3個(gè)依賴:

  • Flowable流程引擎。使我們可以創(chuàng)建一個(gè)ProcessEngine流程引擎對(duì)象傀广,并訪問Flowable API誓酒。

  • 一個(gè)內(nèi)存數(shù)據(jù)庫靠柑。本例中為H2歼冰,因?yàn)镕lowable引擎在運(yùn)行流程實(shí)例時(shí)隔嫡,需要使用數(shù)據(jù)庫來存儲(chǔ)執(zhí)行與歷史數(shù)據(jù)腮恩。

  • 日志框架秸滴。Flowable使用SLF4J作為內(nèi)部日志框架荡含。本例中内颗,我們使用log4j作為SLF4J的實(shí)現(xiàn)均澳。

pom.xml文件中添加下列行:

<dependencies>
 <dependency>
 <groupId>org.flowable</groupId>
 <artifactId>flowable-engine</artifactId>
 <version>6.7.2</version>
 </dependency>
 <dependency>
 <groupId>com.h2database</groupId>
 <artifactId>h2</artifactId>
 <version>1.3.176</version>
 </dependency>
 <dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-api</artifactId>
 <version>1.7.21</version>
 </dependency>
 <dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-log4j12</artifactId>
 <version>1.7.21</version>
 </dependency>
</dependencies>

Log4j需要一個(gè)配置文件糟袁。在src/main/resources文件夾下添加log4j.properties文件项戴,并寫入下列內(nèi)容:

log4j.rootLogger=INFO, CA

log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n

注意: 關(guān)于Log4j 的遠(yuǎn)程代碼執(zhí)行漏洞問題界斜,影響范圍是Apache Log4j 2.x <= 2.14.1 版本项贺,所以上面的日志版本是安全的开缎。

有時(shí)候奕删,依賴JAR無法自動(dòng)獲取急侥,可以右鍵點(diǎn)擊項(xiàng)目坏怪,并選擇 Maven ->Reload Project以強(qiáng)制手動(dòng)刷新铝宵。

創(chuàng)建一個(gè)新的Java類鹏秋,并添加標(biāo)準(zhǔn)的Java main方法:

public class HolidayRequest {

 public static void main(String[] args) {

 }

}

首先要做的是初始化ProcessEngine流程引擎實(shí)例侣夷。創(chuàng)建一個(gè)ProcessEngineConfiguration實(shí)例 琴锭,并配置數(shù)據(jù)庫JDBC連接决帖。然后由ProcessEngineConfiguration創(chuàng)建ProcessEngine實(shí)例地回。

import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;

public class HolidayRequest {

 public static void main(String[] args) {

 ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
 .setJdbcUrl("jdbc:h2:mem:flowable;DB_CLOSE_DELAY=-1")
 .setJdbcUsername("sa")
 .setJdbcPassword("")
 .setJdbcDriver("org.h2.Driver")
 .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);

 ProcessEngine processEngine = cfg.buildProcessEngine();
 }

}

注意:內(nèi)存H2數(shù)據(jù)庫在JVM重啟后會(huì)消失刻像。如果需要永久保存數(shù)據(jù)绎速,需要切換為持久化數(shù)據(jù)庫洒宝,并相應(yīng)切換連接參數(shù)雁歌。

這樣就可以運(yùn)行了比庄。在IDEA中最簡(jiǎn)單的方法是右鍵點(diǎn)擊類文件佳窑,選擇Run 'HolidayRequest.main()'

run.png

成功運(yùn)行,應(yīng)該可以看到關(guān)于引擎啟動(dòng)與創(chuàng)建數(shù)據(jù)庫表結(jié)構(gòu)的提示日志:

輸出1-1.png

這樣就得到了一個(gè)啟動(dòng)可用的流程引擎溉委。接下來為它提供一個(gè)流程瓣喊!

3.創(chuàng)建流程定義文件

我們要構(gòu)建的流程是一個(gè)非常簡(jiǎn)單的請(qǐng)假流程八匠。 在Flowable術(shù)語中梨树,我們將其稱為一個(gè)流程定義(process definition)。一個(gè)流程定義可以啟動(dòng)多個(gè)流程實(shí)例(process instance)仗谆。流程定義可以看做是重復(fù)執(zhí)行流程的藍(lán)圖藻雪。 在這個(gè)例子中勉耀,流程定義定義了請(qǐng)假的各個(gè)步驟便斥,而一個(gè)流程實(shí)例對(duì)應(yīng)某個(gè)雇員提出的一個(gè)請(qǐng)假申請(qǐng)。

我們要使用的流程定義為:

請(qǐng)假流程.png

為了明確起見晋渺,說明一下幾個(gè)要點(diǎn):

  • 啟動(dòng)流程需要提供一些信息,例如雇員名字俭厚、請(qǐng)假時(shí)長(zhǎng)以及說明叼丑。鸠信。

  • 左側(cè)的圓圈叫做啟動(dòng)事件(start event)星立。這是一個(gè)流程實(shí)例的起點(diǎn)室奏。

  • 第一個(gè)矩形是一個(gè)用戶任務(wù)(user task)胧沫。這是流程中人類用戶操作的步驟绒怨。在這個(gè)例子中,經(jīng)理需要批準(zhǔn)或駁回申請(qǐng)六剥。

  • 取決于經(jīng)理的決定仗考,排他網(wǎng)關(guān)(exclusive gateway) (帶叉的菱形)會(huì)將流程實(shí)例路由至批準(zhǔn)或駁回路徑。

  • 如果批準(zhǔn)顿膨,則需要將申請(qǐng)注冊(cè)至某個(gè)外部系統(tǒng),并跟著另一個(gè)用戶任務(wù)囊咏,將經(jīng)理的決定通知給申請(qǐng)人梅割。

  • 如果駁回户辞,則為雇員發(fā)送一封郵件通知他刃榨。

注意:一般來說枢希,這樣的流程定義使用可視化建模工具建立苞轿,如Flowable Designer(Eclipse)或Flowable Web Modeler(Web應(yīng)用)。IDEA沒有官方提供的可視化插件秀睛,可選插件為Flowable BPMN visualizer蹂安。

將下面的XML保存在src/main/resources文件夾下名為holiday-request.bpmn20.xml的文件中田盈。

<?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: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"
 xmlns:flowable="http://flowable.org/bpmn"
 typeLanguage="http://www.w3.org/2001/XMLSchema"
 expressionLanguage="http://www.w3.org/1999/XPath"
 targetNamespace="http://www.flowable.org/processdef">

 <process id="holidayRequest" name="Holiday Request" isExecutable="true">

 <startEvent id="startEvent"/>
 <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>

 <userTask id="approveTask" name="Approve or reject request"/>
 <sequenceFlow sourceRef="approveTask" targetRef="decision"/>

 <exclusiveGateway id="decision"/>
 <sequenceFlow sourceRef="decision" targetRef="externalSystemCall">
 <conditionExpression xsi:type="tFormalExpression">
 <![CDATA[
 ${approved}
 ]]>
 </conditionExpression>
 </sequenceFlow>
 <sequenceFlow  sourceRef="decision" targetRef="sendRejectionMail">
 <conditionExpression xsi:type="tFormalExpression">
 <![CDATA[
 ${!approved}
 ]]>
 </conditionExpression>
 </sequenceFlow>

 <serviceTask id="externalSystemCall" name="Enter holidays in external system"
 flowable:class="CallExternalSystemDelegate"/>
 <sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/>

 <userTask id="holidayApprovedTask" name="Holiday approved"/>
 <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>

 <serviceTask id="sendRejectionMail" name="Send out rejection email"
 flowable:class="SendRejectionMail"/>
 <sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>

 <endEvent id="approveEnd"/>

 <endEvent id="rejectEnd"/>

 </process>

</definitions>

每一個(gè)步驟(在BPMN 2.0術(shù)語中稱作活動(dòng)(activity))都有一個(gè)id屬性述暂,為其提供一個(gè)在XML文件中唯一的標(biāo)識(shí)符畦韭。所有的活動(dòng)都可以設(shè)置一個(gè)名字艺配,以提高流程圖的可讀性酝掩。

活動(dòng)之間通過順序流(sequence flow)連接期虾,在流程圖中是一個(gè)有向箭頭喳坠。在執(zhí)行流程實(shí)例時(shí)壕鹉,執(zhí)行(execution)會(huì)從啟動(dòng)事件沿著順序流流向下一個(gè)活動(dòng)晾浴。

離開排他網(wǎng)關(guān)(帶有X的菱形)順序流很特別:都以表達(dá)式(expression)的形式定義了條件(condition) 。當(dāng)流程實(shí)例的執(zhí)行到達(dá)這個(gè)網(wǎng)關(guān)時(shí)狸涌,會(huì)計(jì)算條件帕胆,并使用第一個(gè)計(jì)算為true的順序流懒豹。這就是排他的含義:只選擇一個(gè)。

這里用作條件的表達(dá)式為"{approved}",這是{approved == true}的簡(jiǎn)寫淘这。變量’approved’被稱作流程變量(process variable)铝穷。

現(xiàn)在我們已經(jīng)有了流程BPMN 2.0 XML文件曙聂,下來需要將它'部署(deploy)'到引擎中断国。

4.部署流程定義

將流程定義部署至Flowable引擎稳衬,需要使用RepositoryService薄疚,其可以從ProcessEngine對(duì)象獲取街夭。使用RepositoryService,可以通過XML文件的路徑創(chuàng)建一個(gè)新的部署(Deployment)檐什,并調(diào)用deploy()方法實(shí)際執(zhí)行:

RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
 .addClasspathResource("holiday-request.bpmn20.xml")
 .deploy();

我們現(xiàn)在可以通過API查詢驗(yàn)證流程定義已經(jīng)部署在引擎中乃正。通過RepositoryService創(chuàng)建的ProcessDefinitionQuery對(duì)象實(shí)現(xiàn)。

ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
 .deploymentId(deployment.getId())
 .singleResult();
System.out.println("Found process definition : " + processDefinition.getName());

5.啟動(dòng)流程實(shí)例

現(xiàn)在已經(jīng)在流程引擎中部署了流程定義名党,因此可以使用這個(gè)流程定義作為“藍(lán)圖”啟動(dòng)流程實(shí)例传睹。

要啟動(dòng)流程實(shí)例欧啤,需要提供一些初始化流程變量。一般來說倒慧,可以通過呈現(xiàn)給用戶的表單纫谅,或者在流程由其他系統(tǒng)自動(dòng)觸發(fā)時(shí)通過REST API照激,來獲取這些變量俩垃。在這個(gè)例子里口柳,我們簡(jiǎn)化為使用java.util.Scanner類在命令行輸入一些數(shù)據(jù):

Scanner scanner= new Scanner(System.in);

System.out.println("Who are you?");
String employee = scanner.nextLine();

System.out.println("How many holidays do you want to request?");
Integer nrOfHolidays = Integer.valueOf(scanner.nextLine());

System.out.println("Why do you need them?");
String description = scanner.nextLine();

接下來,我們使用RuntimeService啟動(dòng)一個(gè)流程實(shí)例望艺。收集的數(shù)據(jù)作為一個(gè)java.util.Map實(shí)例傳遞找默,其中的鍵就是之后用于獲取變量的標(biāo)識(shí)符惩激。這個(gè)流程實(shí)例使用key啟動(dòng)。這個(gè)key就是BPMN 2.0 XML文件中設(shè)置的id屬性骡技,在這個(gè)例子里是holidayRequest哮兰。

<process id="holidayRequest" name="Holiday Request" isExecutable="true"></pre>

<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="java" cid="n194" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">RuntimeService runtimeService = processEngine.getRuntimeService();

Map<String, Object> variables = new HashMap<String, Object>();
variables.put("employee", employee);
variables.put("nrOfHolidays", nrOfHolidays);
variables.put("description", description);
ProcessInstance processInstance =
 runtimeService.startProcessInstanceByKey("holidayRequest", variables);

在流程實(shí)例啟動(dòng)后膏秫,會(huì)創(chuàng)建一個(gè)執(zhí)行(execution)窘哈,并將其放在啟動(dòng)事件上滚婉。從這里開始,這個(gè)執(zhí)行沿著順序流移動(dòng)到經(jīng)理審批的用戶任務(wù)帅刀,并執(zhí)行用戶任務(wù)行為让腹。這個(gè)行為將在數(shù)據(jù)庫中創(chuàng)建一個(gè)任務(wù),該任務(wù)可以之后使用查詢找到扣溺。用戶任務(wù)是一個(gè)等待狀態(tài)(wait state)骇窍,引擎會(huì)停止執(zhí)行,返回API調(diào)用處锥余。

6.查詢與完成任務(wù)

我們還沒有為用戶任務(wù)配置辦理人腹纳。我們想將第一個(gè)任務(wù)指派給"經(jīng)理(managers)"組,而第二個(gè)用戶任務(wù)指派給請(qǐng)假申請(qǐng)的提交人驱犹。因此需要為第一個(gè)任務(wù)添加candidateGroups屬性嘲恍,修改流程xml配置文件:

<userTask id="approveTask" name="Approve or reject request" flowable:candidateGroups="managers"/>

并如下所示為第二個(gè)任務(wù)添加assignee屬性。請(qǐng)注意我們沒有像上面的’managers’一樣使用靜態(tài)值雄驹,而是使用一個(gè)流程變量動(dòng)態(tài)指派佃牛。這個(gè)流程變量是在流程實(shí)例啟動(dòng)時(shí)傳遞的:

<userTask id="holidayApprovedTask" name="Holiday approved" flowable:assignee="${employee}"/>

要獲得實(shí)際的任務(wù)列表,需要通過TaskService創(chuàng)建一個(gè)TaskQuery荠医。我們配置這個(gè)查詢只返回’managers’組的任務(wù):

TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("managers").list();
System.out.println("You have " + tasks.size() + " tasks:");
for (int i=0; i<tasks.size(); i++) {
 System.out.println((i+1) + ") " + tasks.get(i).getName());
}

可以使用任務(wù)Id獲取特定流程實(shí)例的變量吁脱,并在屏幕上顯示實(shí)際的申請(qǐng):

System.out.println("Which task would you like to complete?");
int taskIndex = Integer.valueOf(scanner.nextLine());
Task task = tasks.get(taskIndex - 1);
Map<String, Object> processVariables = taskService.getVariables(task.getId());
System.out.println(processVariables.get("employee") + " wants " +
 processVariables.get("nrOfHolidays") + " of holidays. Do you approve this?");

運(yùn)行結(jié)果像下面這樣:

輸出1-2.png

經(jīng)理現(xiàn)在就可以完成任務(wù)了。在現(xiàn)實(shí)中彬向,這通常意味著由用戶提交一個(gè)表單兼贡。表單中的數(shù)據(jù)作為流程變量傳遞。在這里娃胆,我們?cè)谕瓿扇蝿?wù)時(shí)傳遞帶有’approved’變量(這個(gè)名字很重要废封,因?yàn)橹髸?huì)在順序流的條件中使用F蟆)的map來模擬:

boolean approved = scanner.nextLine().toLowerCase().equals("y");
variables = new HashMap<String, Object>();
variables.put("approved", approved);
taskService.complete(task.getId(), variables);

現(xiàn)在任務(wù)完成窟她,并會(huì)在離開排他網(wǎng)關(guān)的兩條路徑中穿剖,基于’approved’流程變量選擇一條昏苏。

7.實(shí)現(xiàn)JavaDelegate

代碼還缺了一塊:我們還沒有實(shí)現(xiàn)申請(qǐng)通過后執(zhí)行的自動(dòng)邏輯。在BPMN 2.0 XML中威沫,這是一個(gè)服務(wù)任務(wù)(service task)

<serviceTask id="externalSystemCall" name="Enter holidays in external system"
 flowable:class="org.flowable.CallExternalSystemDelegate"/>

在現(xiàn)實(shí)中贤惯,這個(gè)邏輯可以做任何事情:向某個(gè)系統(tǒng)發(fā)起一個(gè)HTTP REST服務(wù)調(diào)用,或調(diào)用某個(gè)使用了好幾十年的系統(tǒng)中的遺留代碼棒掠。我們不會(huì)在這里實(shí)現(xiàn)實(shí)際的邏輯孵构,而只是簡(jiǎn)單的日志記錄流程

創(chuàng)建一個(gè)新的JAVA類烟很,CallExternalSystemDelegate作為類名浦译。讓這個(gè)類實(shí)現(xiàn)org.flowable.engine.delegate.JavaDelegate接口棒假,并實(shí)現(xiàn)execute方法:

import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;

public class CallExternalSystemDelegate implements JavaDelegate {
 public void execute(DelegateExecution execution) {
 System.out.println("Calling the external system for employee "
 + execution.getVariable("employee"));
 }
}

當(dāng)執(zhí)行到達(dá)服務(wù)任務(wù)時(shí),會(huì)初始化并調(diào)用BPMN 2.0 XML中所引用的類精盅。

現(xiàn)在執(zhí)行這個(gè)例子的時(shí)候,就會(huì)顯示出日志信息谜酒,說明已經(jīng)執(zhí)行了自定義邏輯:

輸出1-3.png

注意:如果出現(xiàn)“org.flowable.common.engine.api.FlowableException: couldn't instantiate class CallExternalSystemDelegate”的報(bào)錯(cuò)叹俏,說明包路徑未指定正確,在xml文件中僻族,根據(jù)自己CallExternalSystemDelegate類的實(shí)際路徑修改:

<serviceTask id="externalSystemCall" name="Enter holidays in external system"
 flowable:class="CallExternalSystemDelegate"/>

8.使用歷史數(shù)據(jù)

Flowable可以自動(dòng)存儲(chǔ)所有流程實(shí)例的數(shù)據(jù)粘驰。

例如,如果希望顯示流程實(shí)例已經(jīng)執(zhí)行的時(shí)間述么,就可以從ProcessEngine獲取HistoryService蝌数,并創(chuàng)建歷史活動(dòng)(historical activities)的查詢。在下面的代碼片段中度秘,可以看到我們添加了一些額外的過濾條件:

  • 只選擇一個(gè)特定流程實(shí)例的活動(dòng)

  • 只選擇已完成的活動(dòng)

結(jié)果按照結(jié)束時(shí)間排序顶伞,代表其執(zhí)行順序。

HistoryService historyService = processEngine.getHistoryService();
List<HistoricActivityInstance> activities =
 historyService.createHistoricActivityInstanceQuery()
 .processInstanceId(processInstance.getId())
 .finished()
 .orderByHistoricActivityInstanceEndTime().asc()
 .list();

for (HistoricActivityInstance activity : activities) {
 System.out.println(activity.getActivityId() + " took "
 + activity.getDurationInMillis() + " milliseconds");
}

再次運(yùn)行例子剑梳,可以看到控制臺(tái)中顯示:

輸出1-4.png

9.小結(jié)

這個(gè)教程介紹了很多Flowable與BPMN 2.0的概念與術(shù)語唆貌,也展示了如何編程使用Flowable API。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末垢乙,一起剝皮案震驚了整個(gè)濱河市锨咙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌追逮,老刑警劉巖酪刀,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異钮孵,居然都是意外死亡骂倘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門油猫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來稠茂,“玉大人,你說我怎么就攤上這事情妖〔枪兀” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵毡证,是天一觀的道長(zhǎng)电爹。 經(jīng)常有香客問我,道長(zhǎng)料睛,這世上最難降的妖魔是什么丐箩? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任摇邦,我火速辦了婚禮,結(jié)果婚禮上屎勘,老公的妹妹穿的比我還像新娘施籍。我一直安慰自己,他們只是感情好概漱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布丑慎。 她就那樣靜靜地躺著,像睡著了一般瓤摧。 火紅的嫁衣襯著肌膚如雪竿裂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天照弥,我揣著相機(jī)與錄音腻异,去河邊找鬼。 笑死这揣,一個(gè)胖子當(dāng)著我的面吹牛悔常,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播曾沈,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼这嚣,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了塞俱?” 一聲冷哼從身側(cè)響起姐帚,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎障涯,沒想到半個(gè)月后罐旗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡唯蝶,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年九秀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粘我。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鼓蜒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出征字,到底是詐尸還是另有隱情都弹,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布匙姜,位于F島的核電站畅厢,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏氮昧。R本人自食惡果不足惜框杜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一浦楣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧咪辱,春花似錦振劳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至选调,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間灵份,已是汗流浹背仁堪。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留填渠,地道東北人弦聂。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像氛什,于是被迫代替她去往敵國(guó)和親莺葫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容