Spring事務(wù)傳播行為

1. 什么是事務(wù)傳播行為段化?

事務(wù)傳播行為用來描述由某一個(gè)事務(wù)傳播行為修飾的方法被嵌套進(jìn)另一個(gè)方法的時(shí)事務(wù)如何傳播。

用偽代碼說明:


public void methodA(){

    methodB();

    //doSomething

}

@Transaction(Propagation=XXX)

public void methodB(){

    //doSomething

}

代碼中methodA()方法嵌套調(diào)用了methodB()方法萎河,methodB()的事務(wù)傳播行為由@Transaction(Propagation=XXX)設(shè)置決定随抠。這里需要注意的是methodA()并沒有開啟事務(wù)禁筏,某一個(gè)事務(wù)傳播行為修飾的方法并不是必須要在開啟事務(wù)的外圍方法中調(diào)用尽楔。

2. Spring中七種事務(wù)傳播行為

事務(wù)傳播行為類型 說明
PROPAGATION_REQUIRED 如果當(dāng)前沒有事務(wù)投储,就新建一個(gè)事務(wù),如果已經(jīng)存在一個(gè)事務(wù)中阔馋,加入到這個(gè)事務(wù)中玛荞。這是最常見的選擇。
PROPAGATION_SUPPORTS 支持當(dāng)前事務(wù)呕寝,如果當(dāng)前沒有事務(wù)勋眯,就以非事務(wù)方式執(zhí)行。
PROPAGATION_MANDATORY 使用當(dāng)前的事務(wù),如果當(dāng)前沒有事務(wù)客蹋,就拋出異常塞蹭。
PROPAGATION_REQUIRES_NEW 新建事務(wù),如果當(dāng)前存在事務(wù)嚼酝,把當(dāng)前事務(wù)掛起浮还。
PROPAGATION_NOT_SUPPORTED 以非事務(wù)方式執(zhí)行操作竟坛,如果當(dāng)前存在事務(wù)闽巩,就把當(dāng)前事務(wù)掛起。
PROPAGATION_NEVER 以非事務(wù)方式執(zhí)行担汤,如果當(dāng)前存在事務(wù)涎跨,則拋出異常。
PROPAGATION_NESTED 如果當(dāng)前存在事務(wù)崭歧,則在嵌套事務(wù)內(nèi)執(zhí)行隅很。如果當(dāng)前沒有事務(wù),則執(zhí)行與PROPAGATION_REQUIRED類似的操作率碾。

定義非常簡單叔营,也很好理解,下面我們就進(jìn)入代碼測試部分所宰,驗(yàn)證我們的理解是否正確

代碼驗(yàn)證

文中代碼以傳統(tǒng)三層結(jié)構(gòu)中兩層呈現(xiàn)绒尊,即Service和Dao層,由Spring負(fù)責(zé)依賴注入和注解式事務(wù)管理仔粥,DAO層由Mybatis實(shí)現(xiàn)婴谱,你也可以使用任何喜歡的方式,例如躯泰,Hibernate,JPA,JDBCTemplate等谭羔。數(shù)據(jù)庫使用的是MySQL數(shù)據(jù)庫,你也可以使用任何支持事務(wù)的數(shù)據(jù)庫麦向,并不會(huì)影響驗(yàn)證結(jié)果瘟裸。
首先我們?cè)跀?shù)據(jù)庫中創(chuàng)建兩張表:
user1

CREATE TABLE `user1` (
  `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NOT NULL DEFAULT '',
  PRIMARY KEY(`id`)
)
ENGINE = InnoDB;

user2

CREATE TABLE `user2` (
  `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NOT NULL DEFAULT '',
  PRIMARY KEY(`id`)
)
ENGINE = InnoDB;

然后編寫相應(yīng)的Bean和DAO層代碼:
User1

public class User1 {
    private Integer id;
    private String name;
   //get和set方法省略...
}

User2

public class User1 {
    private Integer id;
    private String name;
   //get和set方法省略...
}

User1Mapper

public interface User1Mapper {
    int insert(User1 record);
    User1 selectByPrimaryKey(Integer id);
    //其他方法省略...
}

User2Mapper

public interface User2Mapper {
    int insert(User2 record);
    User2 selectByPrimaryKey(Integer id);
    //其他方法省略...
}

最后也是具體驗(yàn)證的代碼由service層實(shí)現(xiàn),下面我們分情況列舉诵竭。

1.PROPAGATION_REQUIRED

我們?yōu)閁ser1Service和User2Service相應(yīng)方法加上Propagation.REQUIRED屬性话告。
User1Service方法:

@Service
public class User1ServiceImpl implements User1Service {
    //省略其他...
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addRequired(User1 user){
        user1Mapper.insert(user);
    }
}

User2Service方法:

@Service
public class User2ServiceImpl implements User2Service {
    //省略其他...
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addRequired(User2 user){
        user2Mapper.insert(user);
    }
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addRequiredException(User2 user){
        user2Mapper.insert(user);
        throw new RuntimeException();
    }
    
}
1.1 模擬場景一

此場景外圍方法沒有開啟事務(wù)
驗(yàn)證方法1:

  @Override
    public void notransaction_exception_required_required(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequired(user2);
        
        throw new RuntimeException();
    }

驗(yàn)證方法2:

  @Override
    public void notransaction_required_required_exception(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiredException(user2);
    }

分別執(zhí)行驗(yàn)證方法,結(jié)果:

驗(yàn)證方法序號(hào) 數(shù)據(jù)庫結(jié)果 結(jié)果分析
1 “張三”秀撇、“李四”均插入超棺。 外圍方法未開啟事務(wù),插入“張三”呵燕、“李四”方法在自己的事務(wù)中獨(dú)立運(yùn)行棠绘,外圍方法異常不影響內(nèi)部插入“張三”、“李四”方法獨(dú)立的事務(wù)。
2 “張三”插入氧苍,“李四”未插入夜矗。 外圍方法沒有事務(wù),插入“張三”让虐、“李四”方法都在自己的事務(wù)中獨(dú)立運(yùn)行,所以插入“李四”方法拋出異常只會(huì)回滾插入“李四”方法紊撕,插入“張三”方法不受影響。

結(jié)論:通過這兩個(gè)方法我們證明了在外圍方法未開啟事務(wù)的情況下Propagation.REQUIRED修飾的內(nèi)部方法會(huì)新開啟自己的事務(wù)赡突,且開啟的事務(wù)相互獨(dú)立对扶,互不干擾。

1.2 模擬場景二

外圍方法開啟事務(wù)惭缰,這個(gè)是使用率比較高的場景浪南。
驗(yàn)證方法1:

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void transaction_exception_required_required(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequired(user2);
        
        throw new RuntimeException();
    }

驗(yàn)證方法2:

  @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void transaction_required_required_exception(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiredException(user2);
    }

驗(yàn)證方法3:

   @Transactional
    @Override
    public void transaction_required_required_exception_try(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        try {
            user2Service.addRequiredException(user2);
        } catch (Exception e) {
            System.out.println("方法回滾");
        }
    }

分別執(zhí)行驗(yàn)證方法,結(jié)果:

驗(yàn)證方法序號(hào) 數(shù)據(jù)庫結(jié)果 結(jié)果分析
1 “張三”漱受、“李四”均未插入络凿。 外圍方法開啟事務(wù),內(nèi)部方法加入外圍方法事務(wù)昂羡,外圍方法回滾絮记,內(nèi)部方法也要回滾。
2 “張三”虐先、“李四”均未插入怨愤。 外圍方法開啟事務(wù),內(nèi)部方法加入外圍方法事務(wù)赴穗,內(nèi)部方法拋出異炽舅模回滾,外圍方法感知異常致使整體事務(wù)回滾般眉。
3 “張三”了赵、“李四”均未插入。 外圍方法開啟事務(wù)甸赃,內(nèi)部方法加入外圍方法事務(wù)柿汛,內(nèi)部方法拋出異常回滾埠对,即使方法被catch不被外圍方法感知络断,整個(gè)事務(wù)依然回滾。

結(jié)論:以上試驗(yàn)結(jié)果我們證明在外圍方法開啟事務(wù)的情況下Propagation.REQUIRED修飾的內(nèi)部方法會(huì)加入到外圍方法的事務(wù)中项玛,所有Propagation.REQUIRED修飾的內(nèi)部方法和外圍方法均屬于同一事務(wù)貌笨,只要一個(gè)方法回滾,整個(gè)事務(wù)均回滾襟沮。

2.PROPAGATION_REQUIRES_NEW

我們?yōu)閁ser1Service和User2Service相應(yīng)方法加上Propagation.REQUIRES_NEW屬性
User1Service方法:

@Service
public class User1ServiceImpl implements User1Service {
    //省略其他...
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addRequiresNew(User1 user){
        user1Mapper.insert(user);
    }
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addRequired(User1 user){
        user1Mapper.insert(user);
    }
}

User2Service方法:

@Service
public class User2ServiceImpl implements User2Service {
    //省略其他...
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addRequiresNew(User2 user){
        user2Mapper.insert(user);
    }
    
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addRequiresNewException(User2 user){
        user2Mapper.insert(user);
        throw new RuntimeException();
    }
}
2.1 模擬場景一

外圍方法沒有開啟事務(wù)
驗(yàn)證方法1:

  @Override
    public void notransaction_exception_requiresNew_requiresNew(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addRequiresNew(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiresNew(user2);
        throw new RuntimeException();  
    }

驗(yàn)證方法2:

  @Override
    public void notransaction_requiresNew_requiresNew_exception(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addRequiresNew(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiresNewException(user2);
    }

分別執(zhí)行驗(yàn)證方法锥惋,結(jié)果:

驗(yàn)證方法序號(hào) 數(shù)據(jù)庫結(jié)果 結(jié)果分析
1 “張三”插入昌腰,“李四”插入。 外圍方法沒有事務(wù)膀跌,插入“張三”遭商、“李四”方法都在自己的事務(wù)中獨(dú)立運(yùn)行,外圍方法拋出異常回滾不會(huì)影響內(nèi)部方法捅伤。
2 張三”插入劫流,“李四”未插入 外圍方法沒有開啟事務(wù),插入“張三”方法和插入“李四”方法分別開啟自己的事務(wù)丛忆,插入“李四”方法拋出異踌艋悖回滾,其他事務(wù)不受影響蘸际。

結(jié)論:通過這兩個(gè)方法我們證明了在外圍方法未開啟事務(wù)的情況下Propagation.REQUIRES_NEW修飾的內(nèi)部方法會(huì)新開啟自己的事務(wù)座哩,且開啟的事務(wù)相互獨(dú)立徒扶,互不干擾粮彤。

2.2 模擬場景二

外圍方法開啟事務(wù)。
驗(yàn)證方法1:

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void transaction_exception_required_requiresNew_requiresNew(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiresNew(user2);
        
        User2 user3=new User2();
        user3.setName("王五");
        user2Service.addRequiresNew(user3);
        throw new RuntimeException();
    }

驗(yàn)證方法2:

  @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void transaction_required_requiresNew_requiresNew_exception(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiresNew(user2);
        
        User2 user3=new User2();
        user3.setName("王五");
        user2Service.addRequiresNewException(user3);
    }

驗(yàn)證方法3:

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void transaction_required_requiresNew_requiresNew_exception_try(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addRequired(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addRequiresNew(user2);
        User2 user3=new User2();
        user3.setName("王五");
        try {
            user2Service.addRequiresNewException(user3);
        } catch (Exception e) {
            System.out.println("回滾");
        }
    }

分別執(zhí)行驗(yàn)證方法姜骡,結(jié)果:

驗(yàn)證方法序號(hào) 數(shù)據(jù)庫結(jié)果 結(jié)果分析
1 “張三”未插入导坟,“李四”插入,“王五”插入圈澈。 外圍方法開啟事務(wù)惫周,插入“張三”方法和外圍方法一個(gè)事務(wù),插入“李四”方法康栈、插入“王五”方法分別在獨(dú)立的新建事務(wù)中递递,外圍方法拋出異常只回滾和外圍方法同一事務(wù)的方法,故插入“張三”的方法回滾啥么。
2 “張三”未插入登舞,“李四”插入,“王五”未插入悬荣。 外圍方法開啟事務(wù)菠秒,插入“張三”方法和外圍方法一個(gè)事務(wù),插入“李四”方法氯迂、插入“王五”方法分別在獨(dú)立的新建事務(wù)中践叠。插入“王五”方法拋出異常,首先插入 “王五”方法的事務(wù)被回滾嚼蚀,異常繼續(xù)拋出被外圍方法感知禁灼,外圍方法事務(wù)亦被回滾,故插入“張三”方法也被回滾轿曙。
3 “張三”插入弄捕,“李四”插入哮独,“王五”未插入。 外圍方法開啟事務(wù)察藐,插入“張三”方法和外圍方法一個(gè)事務(wù)皮璧,插入“李四”方法、插入“王五”方法分別在獨(dú)立的新建事務(wù)中分飞。插入“王五”方法拋出異常悴务,首先插入“王五”方法的事務(wù)被回滾,異常被catch不會(huì)被外圍方法感知譬猫,外圍方法事務(wù)不回滾讯檐,故插入“張三”方法插入成功。

結(jié)論:在外圍方法開啟事務(wù)的情況下Propagation.REQUIRES_NEW修飾的內(nèi)部方法依然會(huì)單獨(dú)開啟獨(dú)立事務(wù)染服,且與外部方法事務(wù)也獨(dú)立别洪,內(nèi)部方法之間、內(nèi)部方法和外部方法事務(wù)均相互獨(dú)立柳刮,互不干擾挖垛。

3.PROPAGATION_NESTED

我們?yōu)閁ser1Service和User2Service相應(yīng)方法加上Propagation.NESTED屬性。
User1Service方法:

@Service
public class User1ServiceImpl implements User1Service {
    //省略其他...
    @Override
    @Transactional(propagation = Propagation.NESTED)
    public void addNested(User1 user){
        user1Mapper.insert(user);
    }
}

User2Service方法:

@Service
public class User2ServiceImpl implements User2Service {
    //省略其他...
    @Override
    @Transactional(propagation = Propagation.NESTED)
    public void addNested(User2 user){
        user2Mapper.insert(user);
    }
    
    @Override
    @Transactional(propagation = Propagation.NESTED)
    public void addNestedException(User2 user){
        user2Mapper.insert(user);
        throw new RuntimeException();
    }
}
3.1 模擬場景一

此場景外圍方法沒有開啟事務(wù)秉颗。
驗(yàn)證方法1:

  @Override
    public void notransaction_exception_nested_nested(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addNested(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addNested(user2);
        throw new RuntimeException();
    }

驗(yàn)證方法2:

 @Override
    public void notransaction_nested_nested_exception(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addNested(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addNestedException(user2);
    }

分別執(zhí)行驗(yàn)證方法痢毒,結(jié)果:

驗(yàn)證方法序號(hào) 數(shù)據(jù)庫結(jié)果 結(jié)果分析
1 “張三”、“李四”均插入蚕甥。 外圍方法未開啟事務(wù)哪替,插入“張三”、“李四”方法在自己的事務(wù)中獨(dú)立運(yùn)行菇怀,外圍方法異常不影響內(nèi)部插入“張三”凭舶、“李四”方法獨(dú)立的事務(wù)。
2 “張三”插入爱沟,“李四”未插入帅霜。 外圍方法沒有事務(wù),插入“張三”钥顽、“李四”方法都在自己的事務(wù)中獨(dú)立運(yùn)行,所以插入“李四”方法拋出異常只會(huì)回滾插入“李四”方法义屏,插入“張三”方法不受影響。

結(jié)論:通過這兩個(gè)方法我們證明了在外圍方法未開啟事務(wù)的情況下Propagation.NESTED和Propagation.REQUIRED作用相同蜂大,修飾的內(nèi)部方法都會(huì)新開啟自己的事務(wù)闽铐,且開啟的事務(wù)相互獨(dú)立,互不干擾奶浦。

3.2 模擬場景二

外圍方法開啟事務(wù)兄墅。
驗(yàn)證方法1:

    @Transactional
    @Override
    public void transaction_exception_nested_nested(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addNested(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addNested(user2);
        throw new RuntimeException();
    }

驗(yàn)證方法2:

   @Transactional
    @Override
    public void transaction_nested_nested_exception(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addNested(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        user2Service.addNestedException(user2);
    }

驗(yàn)證方法3:

     @Transactional
    @Override
    public void transaction_nested_nested_exception_try(){
        User1 user1=new User1();
        user1.setName("張三");
        user1Service.addNested(user1);
        
        User2 user2=new User2();
        user2.setName("李四");
        try {
            user2Service.addNestedException(user2);
        } catch (Exception e) {
            System.out.println("方法回滾");
        }
    }

分別執(zhí)行驗(yàn)證方法,結(jié)果:

驗(yàn)證方法序號(hào) 數(shù)據(jù)庫結(jié)果 結(jié)果分析
1 “張三”澳叉、“李四”均未插入隙咸。 外圍方法開啟事務(wù)沐悦,內(nèi)部事務(wù)為外圍事務(wù)的子事務(wù),外圍方法回滾五督,內(nèi)部方法也要回滾藏否。
2 “張三”、“李四”均未插入充包。 外圍方法開啟事務(wù)副签,內(nèi)部事務(wù)為外圍事務(wù)的子事務(wù),內(nèi)部方法拋出異郴回滾淆储,且外圍方法感知異常致使整體事務(wù)回滾。
3 “張三”插入家浇、“李四”未插入本砰。 外圍方法開啟事務(wù),內(nèi)部事務(wù)為外圍事務(wù)的子事務(wù)钢悲,插入“張三”內(nèi)部方法拋出異常点额,可以單獨(dú)對(duì)子事務(wù)回滾。

結(jié)論:以上試驗(yàn)結(jié)果我們證明在外圍方法開啟事務(wù)的情況下Propagation.NESTED修飾的內(nèi)部方法屬于外部事務(wù)的子事務(wù)譬巫,外圍主事務(wù)回滾咖楣,子事務(wù)一定回滾,而內(nèi)部子事務(wù)可以單獨(dú)回滾而不影響外圍主事務(wù)和其他子事務(wù)

4.REQUIRED,REQUIRES_NEW,NESTED異同

由“1.2 場景二”和“3.2 場景二”對(duì)比芦昔,我們可知:
NESTED和REQUIRED修飾的內(nèi)部方法都屬于外圍方法事務(wù),如果外圍方法拋出異常娃肿,這兩種方法的事務(wù)都會(huì)被回滾咕缎。但是REQUIRED是加入外圍方法事務(wù),所以和外圍事務(wù)同屬于一個(gè)事務(wù)料扰,一旦REQUIRED事務(wù)拋出異常被回滾凭豪,外圍方法事務(wù)也將被回滾。而NESTED是外圍方法的子事務(wù)晒杈,有單獨(dú)的保存點(diǎn)嫂伞,所以NESTED方法拋出異常被回滾,不會(huì)影響到外圍方法的事務(wù)拯钻。
由“2.2 場景二”和“3.2 場景二”對(duì)比帖努,我們可知:
NESTED和REQUIRES_NEW都可以做到內(nèi)部方法事務(wù)回滾而不影響外圍方法事務(wù)。但是因?yàn)镹ESTED是嵌套事務(wù)粪般,所以外圍方法回滾之后拼余,作為外圍方法事務(wù)的子事務(wù)也會(huì)被回滾。而REQUIRES_NEW是通過開啟新的事務(wù)實(shí)現(xiàn)的亩歹,內(nèi)部事務(wù)和外圍事務(wù)是兩個(gè)事務(wù)匙监,外圍事務(wù)回滾不會(huì)影響內(nèi)部事務(wù)凡橱。

模擬用例

假設(shè)我們有一個(gè)注冊(cè)的方法,方法中調(diào)用添加積分的方法亭姥,如果我們希望添加積分不會(huì)影響注冊(cè)流程(即添加積分執(zhí)行失敗回滾不能使注冊(cè)方法也回滾)稼钩,我們會(huì)這樣寫:

   @Service
   public class UserServiceImpl implements UserService {
        
        @Transactional
        public void register(User user){
                   
            try {
                membershipPointService.addPoint(Point point);
            } catch (Exception e) {
               //省略...
            }
            //省略...
        }
        //省略...
   }

我們還規(guī)定注冊(cè)失敗要影響addPoint()方法(注冊(cè)方法回滾添加積分方法也需要回滾),那么addPoint()方法就需要這樣實(shí)現(xiàn):

    @Service
   public class MembershipPointServiceImpl implements MembershipPointService{
        
        @Transactional(propagation = Propagation.NESTED)
        public void addPoint(Point point){
                   
            try {
                recordService.addRecord(Record record);
            } catch (Exception e) {
               //省略...
            }
            //省略...
        }
        //省略...
   }

我們注意到了在addPoint()中還調(diào)用了addRecord()方法达罗,這個(gè)方法用來記錄日志变抽。他的實(shí)現(xiàn)如下:

     @Service
   public class RecordServiceImpl implements RecordService{
        
        @Transactional(propagation = Propagation.NOT_SUPPORTED)
        public void addRecord(Record record){
                   
           
            //省略...
        }
        //省略...
   }

我們注意到addRecord()方法中propagation = Propagation.NOT_SUPPORTED,因?yàn)閷?duì)于日志無所謂精確氮块,可以多一條也可以少一條绍载,所以addRecord()方法本身和外圍addPoint()方法拋出異常都不會(huì)使addRecord()方法回滾,并且addRecord()方法拋出異常也不會(huì)影響外圍addPoint()方法的執(zhí)行滔蝉。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末击儡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蝠引,更是在濱河造成了極大的恐慌阳谍,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件螃概,死亡現(xiàn)場離奇詭異矫夯,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)吊洼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門训貌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人冒窍,你說我怎么就攤上這事递沪。” “怎么了综液?”我有些...
    開封第一講書人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵款慨,是天一觀的道長。 經(jīng)常有香客問我谬莹,道長檩奠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任附帽,我火速辦了婚禮埠戳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘士葫。我一直安慰自己乞而,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開白布慢显。 她就那樣靜靜地躺著爪模,像睡著了一般欠啤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上屋灌,一...
    開封第一講書人閱讀 52,475評(píng)論 1 312
  • 那天洁段,我揣著相機(jī)與錄音,去河邊找鬼共郭。 笑死祠丝,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的除嘹。 我是一名探鬼主播写半,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼尉咕!你這毒婦竟也來了叠蝇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤年缎,失蹤者是張志新(化名)和其女友劉穎悔捶,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體单芜,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜕该,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了洲鸠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堂淡。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖坛怪,靈堂內(nèi)的尸體忽然破棺而出淤齐,到底是詐尸還是另有隱情,我是刑警寧澤袜匿,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站稚疹,受9級(jí)特大地震影響居灯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜内狗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一怪嫌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧柳沙,春花似錦岩灭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽柱恤。三九已至,卻和暖如春找爱,著一層夾襖步出監(jiān)牢的瞬間梗顺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來泰國打工车摄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留寺谤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓吮播,卻偏偏與公主長得像变屁,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子意狠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

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