RabbitMQ筆記二十三 :異步RPC之二(使用Spring AMQP實(shí)現(xiàn)RPC異步調(diào)用)

使用Spring AMQP實(shí)現(xiàn)RPC異步調(diào)用

示列

服務(wù)器端

應(yīng)用啟動(dòng)類代碼,

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

import java.util.concurrent.TimeUnit;

@ComponentScan
public class Application {
    public static void main(String[] args) throws Exception{
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
        System.out.println("===server startup======");
        TimeUnit.SECONDS.sleep(120);
        context.close();
    }
}

配置類:
監(jiān)聽了sms隊(duì)列,這個(gè)隊(duì)列將會(huì)是客戶端請(qǐng)求消息發(fā)送到的隊(duì)列,配置了適配器,適配器中去調(diào)用服務(wù)叉抡,適配器返回的值就是服務(wù)端返回給客戶端的RPC調(diào)用的結(jié)果

import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MQConfig {

    @Bean
    public ConnectionFactory connectionFactory(){
        CachingConnectionFactory factory = new CachingConnectionFactory();
        factory.setUri("amqp://zhihao.miao:123456@192.168.1.131:5672");
        return factory;
    }

    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
        return rabbitAdmin;
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        return rabbitTemplate;
    }

    @Bean
    public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory){
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames("sms");
        container.setAcknowledgeMode(AcknowledgeMode.NONE);
        //使用適配器的方式
        container.setMessageListener(new MessageListenerAdapter(new SendSMSHandler()));
        return container;
    }
}

處理器,處理器中調(diào)用具體的服務(wù)答毫,我們此列子中處理器方法返回的值是boolean類型

import java.util.concurrent.TimeUnit;

public class SendSMSHandler {

    public boolean handleMessage(byte[] body){
        String _body = new String(body);
        System.out.println(_body);
        String[] sms = _body.split(":");
        String phone = sms[0];
        String content = sms[1];

        boolean is = SendSMSTool.sendSMS(phone,content);

        try {
            TimeUnit.SECONDS.sleep(6);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return is;
    }
}

服務(wù)接口

public class SendSMSTool {

    public static boolean sendSMS(String phone,String content){
        System.out.println("發(fā)送短信內(nèi)容:【"+content+"】到手機(jī)號(hào):"+phone);
        return phone.length() > 6;
    }
}

服務(wù)端步驟

  1. 消息處理方法褥民,一定要有返回值,這個(gè)返回值就是就是server回復(fù)客戶端的結(jié)果洗搂。比如我們SendSMSHandler.handleMessage方法返回的值消返。

客戶端
應(yīng)用啟動(dòng)類:

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

@ComponentScan
public class Application {
    public static void main(String[] args) throws Exception{
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);

        RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);

        //設(shè)置超時(shí)時(shí)間,單位是ms
        rabbitTemplate.setReplyTimeout(10000);

        String phone = "15634344321";
        String content ="周年慶耘拇,五折優(yōu)惠";

        MessageProperties messageProperties = new MessageProperties();
        Message message = new Message((phone+":"+content).getBytes(),messageProperties);

        //rabbitTemplate.send("","sms",message);

        Message reply = rabbitTemplate.sendAndReceive("","sms",message,
                new CorrelationData(UUID.randomUUID().toString()));

        System.out.println(reply);
        System.out.println("message,body:"+new String(reply.getBody()));
        System.out.println("message,properties:"+reply.getMessageProperties());

        TimeUnit.SECONDS.sleep(30);
        context.close();
    }
}

配置類代碼:

import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MQConfig {

    @Bean
    public ConnectionFactory connectionFactory(){
        CachingConnectionFactory factory = new CachingConnectionFactory();
        factory.setUri("amqp://zhihao.miao:123456@192.168.1.131:5672");
        return factory;
    }

    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
        return rabbitAdmin;
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        return rabbitTemplate;
    }
}

如果服務(wù)端睡眠6s撵颊,則客戶端通過sendAndReceive方法接收到的Message對(duì)象為空,怎樣設(shè)置呢惫叛?
客戶端通過設(shè)置rabbitTemplate.setReplyTimeout(10000);就可以了倡勇。

客戶端步驟

  1. 使用sendAndReceive方法發(fā)送消息,該方法返回一個(gè)Message對(duì)象嘉涌,該對(duì)象就是server返回的結(jié)果
  2. sendAndReceive如果超過5s還沒有收到結(jié)果妻熊,則返回null夸浅,這個(gè)超時(shí)時(shí)間可以通過rabbitTemplate.setReplyTimeout()來進(jìn)行設(shè)置
  3. server端返回的結(jié)果一定要注意,和MessageConverter有關(guān)扔役,默認(rèn)的org.springframework.amqp.support.converter.SimpleMessageConverter會(huì)把基本的數(shù)據(jù)類型轉(zhuǎn)換成Serializable對(duì)象帆喇,這樣的話,client端接收的也是序列化的java對(duì)象亿胸,所以坯钦,需要合理設(shè)置MessageConverter

示列代碼中服務(wù)端返回給客戶端的是Boolean類型,

啟動(dòng)服務(wù)端客戶端代碼:
服務(wù)器打印控制臺(tái)打映扌:

15634344321:周年慶婉刀,五折優(yōu)惠
發(fā)送短信內(nèi)容:【周年慶,五折優(yōu)惠】到手機(jī)號(hào):15634344321

客戶端控制臺(tái)打愚致:

message,body:????sr??java.lang.Boolean? r???????Z??valuexp?
message,properties:MessageProperties [headers={}, timestamp=null, messageId=null, userId=null, receivedUserId=null, appId=null, clusterId=null, type=null, correlationId=null, correlationIdString=null, replyTo=null, contentType=application/x-java-serialized-object, contentEncoding=null, contentLength=0, deliveryMode=null, receivedDeliveryMode=PERSISTENT, expiration=null, priority=0, redelivered=false, receivedExchange=, receivedRoutingKey=amq.rabbitmq.reply-to.g2dkAB5yYWJiaXRAaVpicDFqY3d4N3NmYjFud3pyZWh5NloAAFu0AAAABwI=.kHL9zxtdQmtcxl0mQF8zrg==, receivedDelay=null, deliveryTag=1, messageCount=null, consumerTag=null, consumerQueue=null]

我們發(fā)現(xiàn)客戶端接收到的數(shù)據(jù)亂碼路星,將服務(wù)端的處理器的返回值改寫成String類型的,

import java.util.concurrent.TimeUnit;

public class SendSMSHandler {

    public String handleMessage(byte[] body){
        String _body = new String(body);
        System.out.println(_body);
        String[] sms = _body.split(":");
        String phone = sms[0];
        String content = sms[1];

        boolean is = SendSMSTool.sendSMS(phone,content);

        try {
            TimeUnit.SECONDS.sleep(6);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return is ? "success":"false";
    }
}

此時(shí)發(fā)現(xiàn)客戶端接收的消息數(shù)據(jù)沒有亂碼诱桂,原因何在?我們總結(jié)一下就是服務(wù)器端處理器返回給客戶端boolean類型呈昔,那么返回的消息數(shù)據(jù)就亂碼挥等,如果返回的是String類型,那么返回的消息數(shù)據(jù)就不會(huì)亂碼堤尾。

之前我們學(xué)習(xí)了org.springframework.amqp.support.converter.MessageConverter接口肝劲,當(dāng)客戶端向服務(wù)端發(fā)送消息的時(shí)候會(huì)進(jìn)行消息類型轉(zhuǎn)換,調(diào)用了fromMessage方法郭宝,而當(dāng)服務(wù)器返回給客戶端的時(shí)候會(huì)將服務(wù)端的對(duì)象轉(zhuǎn)換成Message對(duì)象辞槐,很明顯調(diào)用的是toMessage方法。

我們知道org.springframework.amqp.support.converter.MessageConverter接口的默認(rèn)實(shí)現(xiàn)是org.springframework.amqp.support.converter.SimpleMessageConverter粘室,而toMessage方法的實(shí)現(xiàn)是在其繼承的對(duì)象AbstractMessageConverter中榄檬,

我們看到其AbstractMessageConverter.toMessage方法的實(shí)現(xiàn)邏輯是:

    @Override
    public final Message toMessage(Object object, MessageProperties messageProperties)
            throws MessageConversionException {
        if (messageProperties == null) {
            messageProperties = new MessageProperties();
        }
        //將對(duì)象轉(zhuǎn)換成Message對(duì)象
        Message message = createMessage(object, messageProperties);
        messageProperties = message.getMessageProperties();
        if (this.createMessageIds && messageProperties.getMessageId() == null) {
            messageProperties.setMessageId(UUID.randomUUID().toString());
        }
        return message;
    }

createMessage方法就是將對(duì)象轉(zhuǎn)換成Message對(duì)象,

    /**
     * Creates an AMQP Message from the provided Object.
     */
    @Override
    protected Message createMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {
        byte[] bytes = null;
        if (object instanceof byte[]) {
            bytes = (byte[]) object;
            messageProperties.setContentType(MessageProperties.CONTENT_TYPE_BYTES);
        }
        else if (object instanceof String) {
            try {
                bytes = ((String) object).getBytes(this.defaultCharset);
            }
            catch (UnsupportedEncodingException e) {
                throw new MessageConversionException(
                        "failed to convert to Message content", e);
            }
            messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
            messageProperties.setContentEncoding(this.defaultCharset);
        }
        //因?yàn)閎oolean類型實(shí)現(xiàn)Serializable接口衔统,所以會(huì)將其序列化
        else if (object instanceof Serializable) {
            try {
                bytes = SerializationUtils.serialize(object);
            }
            catch (IllegalArgumentException e) {
                throw new MessageConversionException(
                        "failed to convert to serialized Message content", e);
            }
            messageProperties.setContentType(MessageProperties.CONTENT_TYPE_SERIALIZED_OBJECT);
        }
        if (bytes != null) {
            messageProperties.setContentLength(bytes.length);
        }
        return new Message(bytes, messageProperties);
    }

我們?cè)诔绦蛑袑⑿蛄谢瘜?duì)象直接轉(zhuǎn)換成字符串所以亂碼鹿榜,而返回的是String類型的情形的時(shí)候先將字符串轉(zhuǎn)換成相應(yīng)的字節(jié)數(shù)組,然后返回new Message(bytes, messageProperties);就不會(huì)亂碼锦爵。

繼續(xù)探討舱殿,當(dāng)我們服務(wù)端返回的是一個(gè)對(duì)象的時(shí)候,客戶端會(huì)返回空
返回的對(duì)象:

public class SendStatus {

    private String phone;

    private String result;

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }
}

將該對(duì)象返回:

public class SendSMSHandler {

    public SendStatus handleMessage(byte[] body){
        String _body = new String(body);
        System.out.println(_body);
        String[] sms = _body.split(":");
        String phone = sms[0];
        String content = sms[1];

        boolean is = SendSMSTool.sendSMS(phone,content);
        SendStatus sendStatus = new SendStatus();
        sendStatus.setPhone(phone);
        sendStatus.setResult(is ? "SUCCESS":"FAILURE");
        return sendStatus;
    }
}

服務(wù)端控制臺(tái):

15634344321:周年慶险掀,五折優(yōu)惠
發(fā)送短信內(nèi)容:【周年慶沪袭,五折優(yōu)惠】到手機(jī)號(hào):15634344321

客戶端:

message,body:
message,properties:MessageProperties [headers={}, timestamp=null, messageId=null, userId=null, receivedUserId=null, appId=null, clusterId=null, type=null, correlationId=null, correlationIdString=null, replyTo=null, contentType=application/octet-stream, contentEncoding=null, contentLength=0, deliveryMode=null, receivedDeliveryMode=PERSISTENT, expiration=null, priority=0, redelivered=false, receivedExchange=, receivedRoutingKey=amq.rabbitmq.reply-to.g2dkAB5yYWJiaXRAaVpicDFqY3d4N3NmYjFud3pyZWh5NloAAFxBAAAABwI=.01fOGW/nvS2nz6gKza+cjg==, receivedDelay=null, deliveryTag=1, messageCount=null, consumerTag=null, consumerQueue=null]

原因何在,因?yàn)槲覀兌x的SendStatus不走createMessage中的所有if分支樟氢,最后返回的是null冈绊,怎么解決呢侠鳄,要么自己去定義一個(gè)org.springframework.amqp.support.converter.MessageConverter實(shí)現(xiàn),要么換一個(gè)默認(rèn)的org.springframework.amqp.support.converter.MessageConverter實(shí)現(xiàn)焚碌。

改造后的示列

使用AMQP自帶的消息類型轉(zhuǎn)換器Jackson2JsonMessageConverter
服務(wù)端

應(yīng)用啟動(dòng)類畦攘,

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

import java.util.concurrent.TimeUnit;

@ComponentScan
public class Application {
    public static void main(String[] args) throws Exception{
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
        System.out.println("===server startup======");
        TimeUnit.SECONDS.sleep(120);
        context.close();
    }
}

配置類,添加自定義的消息轉(zhuǎn)換器

import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MQConfig {

    @Bean
    public ConnectionFactory connectionFactory(){
        CachingConnectionFactory factory = new CachingConnectionFactory();
        factory.setUri("amqp://zhihao.miao:123456@192.168.1.131:5672");
        return factory;
    }

    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
        return rabbitAdmin;
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        return rabbitTemplate;
    }

    @Bean
    public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory){
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames("sms");
        container.setAcknowledgeMode(AcknowledgeMode.NONE);
        //使用適配器的方式
        container.setMessageListener(new MessageListenerAdapter(new SendSMSHandler(),new Jackson2JsonMessageConverter()));
        return container;
    }
}

處理器handler十电,返回自定義的SendStatus類型

import java.util.concurrent.TimeUnit;

public class SendSMSHandler {

    public SendStatus handleMessage(byte[] body){
        String _body = new String(body);
        System.out.println(_body);
        String[] sms = _body.split(":");
        String phone = sms[0];
        String content = sms[1];

        boolean is = SendSMSTool.sendSMS(phone,content);
        SendStatus sendStatus = new SendStatus();
        sendStatus.setPhone(phone);
        sendStatus.setResult(is ? "SUCCESS":"FAILURE");

        try {
            TimeUnit.SECONDS.sleep(6);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return sendStatus;
    }
}

接口服務(wù)知押,

public class SendSMSTool {

    public static boolean sendSMS(String phone,String content){
        System.out.println("發(fā)送短信內(nèi)容:【"+content+"】到手機(jī)號(hào):"+phone);
        return phone.length() > 6;
    }
}

服務(wù)端返回的對(duì)象,

public class SendStatus {
    private String phone;

    private String result;

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }
}

客戶端
應(yīng)用啟動(dòng)類鹃骂,

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

@ComponentScan
public class Application {
    public static void main(String[] args) throws Exception{
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);

        RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);

        //設(shè)置超時(shí)時(shí)間台盯,單位是ms
        rabbitTemplate.setReplyTimeout(10000);

        String phone = "15634344321";
        String content ="周年慶,五折優(yōu)惠";

        MessageProperties messageProperties = new MessageProperties();
        Message message = new Message((phone+":"+content).getBytes(),messageProperties);

        //rabbitTemplate.send("","sms",message);

        Message reply = rabbitTemplate.sendAndReceive("","sms",message,
                new CorrelationData(UUID.randomUUID().toString()));

        System.out.println(reply);
        System.out.println("message,body:"+new String(reply.getBody()));
        System.out.println("message,properties:"+reply.getMessageProperties());

        TimeUnit.SECONDS.sleep(30);
        context.close();
    }
}

配置類

import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MQConfig {

    @Bean
    public ConnectionFactory connectionFactory(){
        CachingConnectionFactory factory = new CachingConnectionFactory();
        factory.setUri("amqp://zhihao.miao:123456@192.168.1.131:5672");
        return factory;
    }

    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
        return rabbitAdmin;
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        return rabbitTemplate;
    }
}

啟動(dòng)服務(wù)器客戶端畏线,客戶端返回

message,body:{"phone":"15634344321","result":"SUCCESS"}
message,properties:MessageProperties [headers={__TypeId__=rpc.server.SendStatus}, timestamp=null, messageId=null, userId=null, receivedUserId=null, appId=null, clusterId=null, type=null, correlationId=null, correlationIdString=null, replyTo=null, contentType=application/json, contentEncoding=UTF-8, contentLength=0, deliveryMode=null, receivedDeliveryMode=PERSISTENT, expiration=null, priority=0, redelivered=false, receivedExchange=, receivedRoutingKey=amq.rabbitmq.reply-to

返回了SendStatus的JSON格式静盅,因?yàn)槭褂昧?code>Jackson2JsonMessageConverter消息類型轉(zhuǎn)換器。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末寝殴,一起剝皮案震驚了整個(gè)濱河市蒿叠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蚣常,老刑警劉巖市咽,帶你破解...
    沈念sama閱讀 212,332評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異抵蚊,居然都是意外死亡施绎,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,508評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門贞绳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谷醉,“玉大人,你說我怎么就攤上這事冈闭【隳幔” “怎么了?”我有些...
    開封第一講書人閱讀 157,812評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵拒秘,是天一觀的道長号显。 經(jīng)常有香客問我,道長躺酒,這世上最難降的妖魔是什么押蚤? 我笑而不...
    開封第一講書人閱讀 56,607評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮羹应,結(jié)果婚禮上揽碘,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好雳刺,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,728評(píng)論 6 386
  • 文/花漫 我一把揭開白布劫灶。 她就那樣靜靜地躺著,像睡著了一般掖桦。 火紅的嫁衣襯著肌膚如雪本昏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,919評(píng)論 1 290
  • 那天枪汪,我揣著相機(jī)與錄音涌穆,去河邊找鬼。 笑死雀久,一個(gè)胖子當(dāng)著我的面吹牛宿稀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赖捌,決...
    沈念sama閱讀 39,071評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼祝沸,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了越庇?” 一聲冷哼從身側(cè)響起罩锐,我...
    開封第一講書人閱讀 37,802評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎卤唉,沒想到半個(gè)月后唯欣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,256評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡搬味,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,576評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蟀拷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碰纬。...
    茶點(diǎn)故事閱讀 38,712評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖问芬,靈堂內(nèi)的尸體忽然破棺而出悦析,到底是詐尸還是另有隱情,我是刑警寧澤此衅,帶...
    沈念sama閱讀 34,389評(píng)論 4 332
  • 正文 年R本政府宣布强戴,位于F島的核電站,受9級(jí)特大地震影響挡鞍,放射性物質(zhì)發(fā)生泄漏骑歹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,032評(píng)論 3 316
  • 文/蒙蒙 一墨微、第九天 我趴在偏房一處隱蔽的房頂上張望道媚。 院中可真熱鬧,春花似錦、人聲如沸最域。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镀脂。三九已至牺蹄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間薄翅,已是汗流浹背沙兰。 一陣腳步聲響...
    開封第一講書人閱讀 32,026評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留匿刮,地道東北人僧凰。 一個(gè)月前我還...
    沈念sama閱讀 46,473評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像熟丸,于是被迫代替她去往敵國和親训措。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,606評(píng)論 2 350

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理光羞,服務(wù)發(fā)現(xiàn)绩鸣,斷路器,智...
    卡卡羅2017閱讀 134,637評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,778評(píng)論 6 342
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 10,934評(píng)論 6 13
  • 轉(zhuǎn)眼間回望自己以不或之年纱兑,過去呀闻,現(xiàn)在還是未來不知覺的突然不怎么喜歡再去想得太多了。生活有點(diǎn)象萬花筒般總會(huì)有...
    火熱如冰閱讀 200評(píng)論 0 2
  • 對(duì)號(hào)入座
    0nePIECE閱讀 209評(píng)論 0 1