SpringBoot | 第二十四章:日志管理之AOP統(tǒng)一日志

第二十四章:日志管理之AOP統(tǒng)一日志

前言

上一章節(jié)晰韵,介紹了目前開(kāi)發(fā)中常見(jiàn)的log4j2logback日志框架的整合知識(shí)。在很多時(shí)候熟妓,我們?cè)陂_(kāi)發(fā)一個(gè)系統(tǒng)時(shí)雪猪,不管出于何種考慮,比如是審計(jì)要求起愈,或者防抵賴只恨,還是保留操作痕跡的角度,一般都會(huì)有個(gè)全局記錄日志的模塊功能抬虽。此模塊一般上會(huì)記錄每個(gè)對(duì)數(shù)據(jù)有進(jìn)行變更的操作記錄官觅,若是在web應(yīng)用上,還會(huì)記錄請(qǐng)求的url,請(qǐng)求的IP,及當(dāng)前的操作人阐污,操作的方法說(shuō)明等等休涤。在很多時(shí)候,我們需要記錄請(qǐng)求的參數(shù)信息時(shí)笛辟,通常是利用攔截器功氨、過(guò)濾器或者AOP等來(lái)進(jìn)行統(tǒng)一攔截。本章節(jié)手幢,就主要來(lái)說(shuō)一說(shuō)如何利用AOP實(shí)現(xiàn)統(tǒng)一的web日志記錄捷凄。

一點(diǎn)知識(shí)

何為AOP

AOP全稱:Aspect Oriented Programming。是一種面向切面編程的围来,利用預(yù)編譯方式和運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)程序功能統(tǒng)一的一種技術(shù)跺涤。它也是Spring很重要的一部分匈睁,和IOC一樣重要。利用AOP可以很好的對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離桶错,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低航唆,提高程序的可重用性,同時(shí)提高了開(kāi)發(fā)的效率牛曹。

簡(jiǎn)單來(lái)說(shuō)佛点,就是AOP可以在既有的程序基礎(chǔ)上,在無(wú)代碼嵌入前提下完成對(duì)相關(guān)業(yè)務(wù)的處理黎比,業(yè)務(wù)方可以只關(guān)注自身業(yè)務(wù)的邏輯超营,而無(wú)需關(guān)系一些和業(yè)務(wù)無(wú)關(guān)的事項(xiàng),比如最常見(jiàn)的日志阅虫、事務(wù)演闭、權(quán)限檢驗(yàn)性能統(tǒng)計(jì)颓帝、統(tǒng)一異常處理等等米碰。

spring官網(wǎng)給出的AOP介紹如下:

AOP介紹

AOP基本概念

關(guān)于AOP的相關(guān)介紹可點(diǎn)擊官網(wǎng)鏈接查看:aop-introduction

AOP concepts

以下簡(jiǎn)單的說(shuō)明下:

  1. 切面(Aspect):切面是一個(gè)關(guān)注點(diǎn)的模塊化,這個(gè)關(guān)注點(diǎn)可能是橫切多個(gè)對(duì)象购城;

  2. 連接點(diǎn)(Join Point):連接點(diǎn)是指在程序執(zhí)行過(guò)程中某個(gè)特定的點(diǎn)吕座,比如某方法調(diào)用的時(shí)候或者處理異常的時(shí)候;

  3. 通知(Advice):指在切面的某個(gè)特定的連接點(diǎn)上執(zhí)行的動(dòng)作瘪板。Spring切面可以應(yīng)用5中通知:

    • 前置通知(Before):在目標(biāo)方法或者說(shuō)連接點(diǎn)被調(diào)用前執(zhí)行的通知吴趴;
    • 后置通知(After):指在某個(gè)連接點(diǎn)完成后執(zhí)行的通知;
    • 返回通知(After-returning):指在某個(gè)連接點(diǎn)成功執(zhí)行之后執(zhí)行的通知侮攀;
    • 異常通知(After-throwing):指在方法拋出異常后執(zhí)行的通知锣枝;
    • 環(huán)繞通知(Around):指包圍一個(gè)連接點(diǎn)通知,在被通知的方法調(diào)用之前和之后執(zhí)行自定義的方法兰英。
  4. 切點(diǎn)(Pointcut):指匹配連接點(diǎn)的斷言撇叁。通知與一個(gè)切入點(diǎn)表達(dá)式關(guān)聯(lián),并在滿足這個(gè)切入的連接點(diǎn)上運(yùn)行畦贸,例如:當(dāng)執(zhí)行某個(gè)特定的名稱的方法陨闹。

  5. 引入(Introduction):引入也被稱為內(nèi)部類型聲明,聲明額外的方法或者某個(gè)類型的字段薄坏。

  6. 目標(biāo)對(duì)象(Target Object):目標(biāo)對(duì)象是被一個(gè)或者多個(gè)切面所通知的對(duì)象正林。

  7. AOP代理(AOP Proxy):AOP代理是指AOP框架創(chuàng)建的對(duì)對(duì)象,用來(lái)實(shí)現(xiàn)切面契約(包括通知方法等功能)

  8. 織入(Wearving):指把切面連接到其他應(yīng)用出程序類型或者對(duì)象上颤殴,并創(chuàng)建一個(gè)被通知的對(duì)象觅廓。或者說(shuō)形成代理對(duì)象的方法的過(guò)程涵但。

以下這張圖杈绸,對(duì)以上部分概念進(jìn)行簡(jiǎn)單介紹:

image

代理機(jī)制

SpirngAOP的動(dòng)態(tài)代理實(shí)現(xiàn)機(jī)制有兩種帖蔓,分別是:JDK動(dòng)態(tài)代理CGLib動(dòng)態(tài)代理。簡(jiǎn)單介紹下兩種代理機(jī)制瞳脓。

  • JDK動(dòng)態(tài)代理

JDK動(dòng)態(tài)代理面向接口代理模式塑娇,如果被代理目標(biāo)沒(méi)有接口那么Spring也無(wú)能為力,Spring通過(guò)java的反射機(jī)制生產(chǎn)被代理接口的新的匿名實(shí)現(xiàn)類劫侧,重寫了其中AOP的增強(qiáng)方法埋酬。

  • CGLib動(dòng)態(tài)代理

CGLib是一個(gè)強(qiáng)大、高性能的Code生產(chǎn)類庫(kù)烧栋,可以實(shí)現(xiàn)運(yùn)行期動(dòng)態(tài)擴(kuò)展java類写妥,Spring在運(yùn)行期間通過(guò) CGlib繼承要被動(dòng)態(tài)代理的類,重寫父類的方法审姓,實(shí)現(xiàn)AOP面向切面編程珍特。

兩者對(duì)比:

  1. JDK動(dòng)態(tài)代理是面向接口,在創(chuàng)建代理實(shí)現(xiàn)類時(shí)比CGLib要快魔吐,創(chuàng)建代理速度快扎筒。而且JDK動(dòng)態(tài)代理只能對(duì)實(shí)現(xiàn)了接口的類生成代理,而不能針對(duì)類酬姆。

  2. CGLib動(dòng)態(tài)代理是通過(guò)字節(jié)碼底層繼承要代理類來(lái)實(shí)現(xiàn)(如果被代理類被final關(guān)鍵字所修飾嗜桌,那么抱歉會(huì)失敗)辞色,在創(chuàng)建代理這一塊沒(méi)有JDK動(dòng)態(tài)代理快骨宠,但是運(yùn)行速度比JDK動(dòng)態(tài)代理要快。

至于相關(guān)原理淫僻,大家自行搜索下吧诱篷,⊙﹏⊙‖∣

切入點(diǎn)指示符簡(jiǎn)單介紹

為了能夠靈活定義切入點(diǎn)位置壶唤,Spring AOP提供了多種切入點(diǎn)指示符雳灵。以下簡(jiǎn)單的介紹下。

  • execution:匹配執(zhí)行方法的連接點(diǎn)
execution切入點(diǎn)指示符

可以從上圖中闸盔,看見(jiàn)切入點(diǎn)指示符execution的語(yǔ)法結(jié)構(gòu)為:execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)悯辙。這也是最常使用的一個(gè)指示符了。

  • within:用于匹配指定類型內(nèi)的方法執(zhí)行迎吵;

  • this:用于匹配當(dāng)前AOP代理對(duì)象類型的執(zhí)行方法躲撰;注意是AOP代理對(duì)象的類型匹配睬塌,這樣就可能包括引入接口也類型匹配铣焊;

  • target:用于匹配當(dāng)前目標(biāo)對(duì)象類型的執(zhí)行方法;注意是目標(biāo)對(duì)象的類型匹配搔预,這樣就不包括引入接口也類型匹配蔫巩;

  • args:用于匹配當(dāng)前執(zhí)行的方法傳入的參數(shù)為指定類型的執(zhí)行方法谆棱;

  • @within:用于匹配所以持有指定注解類型內(nèi)的方法快压;

  • @target:用于匹配當(dāng)前目標(biāo)對(duì)象類型的執(zhí)行方法,其中目標(biāo)對(duì)象持有指定的注解垃瞧;

  • @args:用于匹配當(dāng)前執(zhí)行的方法傳入的參數(shù)持有指定注解的執(zhí)行蔫劣;

  • @annotation:用于匹配當(dāng)前執(zhí)行方法持有指定注解的方法;

  • bean:Spring AOP擴(kuò)展的个从,AspectJ沒(méi)有對(duì)于指示符脉幢,用于匹配特定名稱的Bean對(duì)象的執(zhí)行方法;

  • reference pointcut:表示引用其他命名切入點(diǎn)嗦锐,只有@ApectJ風(fēng)格支持嫌松,Schema風(fēng)格不支持。

對(duì)于相關(guān)的語(yǔ)法和使用意推,大家可查看:https://blog.csdn.net/zhengchao1991/article/details/53391244豆瘫。里面有較為詳細(xì)的介紹。這里就不多加闡述了菊值。

統(tǒng)一日志記錄

介紹完相關(guān)知識(shí)后外驱,我們開(kāi)始來(lái)使用AOP實(shí)現(xiàn)統(tǒng)一的日志記錄功能。本文直接利用@Around環(huán)繞模式來(lái)實(shí)現(xiàn)腻窒,同時(shí)自定義一個(gè)日志注解類昵宇,來(lái)個(gè)性化記錄日志信息。

0.加入Aop依賴儿子。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

1.編寫自定義日志注解類Log瓦哎。

/**
 * 日志注解類
 * @author oKong
 *
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})//只能在方法上使用此注解
public @interface Log {
    /**
     * 日志描述,這里使用了@AliasFor 別名柔逼。spring提供的
     * @return
     */
    @AliasFor("desc")
    String value() default "";
    
    /**
     * 日志描述
     * @return
     */
    @AliasFor("value")
    String desc() default "";
    
    /**
     * 是否不記錄日志
     * @return
     */
    boolean ignore() default false;
}

友情提示:熟悉Spring常用注解類的朋友蒋譬,對(duì)@AliasFor應(yīng)該不陌生。它是Spring提供的一個(gè)注解愉适,主要是給注解的屬性起名別的犯助。讓使用注解時(shí),更加的容易理解(比如給value屬性起別名)维咸。一般上是配對(duì)別名剂买。由于是Spring框架提供的,所以要使其生效癌蓖,可以使用AnnotationUtils.synthesizeAnnotation或者AnnotationUtils.getAnnotation方法調(diào)用獲取注解瞬哼,以下代碼中會(huì)有個(gè)簡(jiǎn)單示例。

2.編寫切面類租副。

/**
 * 日志切面類
 * @author xiedeshou
 *
 */
//加入@Aspect 申明一個(gè)切面
@Aspect
@Component
@Slf4j
public class LogAspect {
    
    //設(shè)置切入點(diǎn):這里直接攔截被@RestController注解的類
    @Pointcut("within(@org.springframework.web.bind.annotation.RestController *)")
    public void pointcut() {
        
    }
    
    /**
     * 切面方法,記錄日志
     * @return
     * @throws Throwable 
     */
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long beginTime = System.currentTimeMillis();//1坐慰、開(kāi)始時(shí)間 
        //利用RequestContextHolder獲取requst對(duì)象
        ServletRequestAttributes requestAttr = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
        String uri = requestAttr.getRequest().getRequestURI();
        log.info("開(kāi)始計(jì)時(shí): {}  URI: {}", new Date(),uri);
        //訪問(wèn)目標(biāo)方法的參數(shù) 可動(dòng)態(tài)改變參數(shù)值
        Object[] args = joinPoint.getArgs();
        //方法名獲取
        String methodName = joinPoint.getSignature().getName();
        log.info("請(qǐng)求方法:{}, 請(qǐng)求參數(shù): {}", methodName, Arrays.toString(args));
        //可能在反向代理請(qǐng)求進(jìn)來(lái)時(shí),獲取的IP存在不正確行 這里直接摘抄一段來(lái)自網(wǎng)上獲取ip的代碼
        log.info("請(qǐng)求ip:{}", getIpAddr(requestAttr.getRequest()));
                
        Signature signature = joinPoint.getSignature();
        if(!(signature instanceof MethodSignature)) {
            throw new IllegalArgumentException("暫不支持非方法注解");
        }
        //調(diào)用實(shí)際方法
        Object object = joinPoint.proceed();
        //獲取執(zhí)行的方法
        MethodSignature methodSign = (MethodSignature) signature;
        Method method = methodSign.getMethod();
        //判斷是否包含了 無(wú)需記錄日志的方法
        Log logAnno = AnnotationUtils.getAnnotation(method, Log.class);
        if(logAnno != null && logAnno.ignore()) {
            return object;
        } 
        log.info("log注解描述:{}", logAnno.desc());
        long endTime = System.currentTimeMillis();
        log.info("結(jié)束計(jì)時(shí): {},  URI: {},耗時(shí):{}", new Date(),uri,endTime - beginTime);
        //模擬異常
        //System.out.println(1/0);
        return object;
    }
    
    /**
     * 指定攔截器規(guī)則用僧;也可直接使用within(@org.springframework.web.bind.annotation.RestController *)
     * 這樣簡(jiǎn)單點(diǎn) 可以通用
     * @param 異常對(duì)象
     */
    @AfterThrowing(pointcut="pointcut()",throwing="e")
    public void afterThrowable(Throwable e) {
        log.error("切面發(fā)生了異常:", e);
        //這里可以做個(gè)統(tǒng)一異常處理
        //自定義一個(gè)異常 包裝后排除
        //throw new AopException("xxx);
    }

    /**
     * 轉(zhuǎn)至:https://my.oschina.net/u/994081/blog/185982
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = null;
        try {
            ipAddress = request.getHeader("x-forwarded-for");
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if (ipAddress.equals("127.0.0.1")) {
                    // 根據(jù)網(wǎng)卡取本機(jī)配置的IP
                    InetAddress inet = null;
                    try {
                        inet = InetAddress.getLocalHost();
                    } catch (UnknownHostException e) {
                        log.error("獲取ip異常:{}" ,e.getMessage());
                        e.printStackTrace();
                    }
                    ipAddress = inet.getHostAddress();
                }
            }
            // 對(duì)于通過(guò)多個(gè)代理的情況结胀,第一個(gè)IP為客戶端真實(shí)IP,多個(gè)IP按照','分割
            if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
                                                                // = 15
                if (ipAddress.indexOf(",") > 0) {
                    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                }
            }
        } catch (Exception e) {
            ipAddress = "";
        }
        // ipAddress = this.getRequest().getRemoteAddr();

        return ipAddress;
    }    
}

3.啟動(dòng)類加入注解@EnableAspectJAutoProxy两残,生效注解。另一說(shuō)法把跨,默認(rèn)引入pom依賴就是默認(rèn)開(kāi)啟的人弓。無(wú)所謂,加了就是了着逐,加上總之是個(gè)好習(xí)慣崔赌,因?yàn)椴恢篮罄m(xù)版本是否會(huì)修改默認(rèn)值呢~

@SpringBootApplication
@EnableAspectJAutoProxy
@Slf4j
public class Chapter24Application {

    public static void main(String[] args) {
        SpringApplication.run(Chapter24Application.class, args);
        log.info("Chapter24啟動(dòng)!");
    }
}

4.編寫控制層。

/**
 * aop統(tǒng)一異常示例
 * @author xiedeshou
 *
 */
@RestController
public class DemoController {
    /**
     * 簡(jiǎn)單方法示例
     * @param hello
     * @return
     */
    @RequestMapping("/aop")
    @Log(value="請(qǐng)求了aopDemo方法")
    public String aopDemo(String hello) {
        return "請(qǐng)求參數(shù)為:" + hello;
    }

    /**
     * 不攔截日志示例
     * @param hello
     * @return
     */
    @RequestMapping("/notaop")
    @Log(ignore=true)
    public String notAopDemo(String hello) {
        return "此方法不記錄日志耸别,請(qǐng)求參數(shù)為:" + hello;
    }
}

友情提示:在編寫了切面類后健芭,若符合切面攔截條件的方法,IDE會(huì)進(jìn)行標(biāo)識(shí)的秀姐。

切面提示

5.啟動(dòng)應(yīng)用慈迈,訪問(wèn)api,即可看見(jiàn)控制臺(tái)輸出了對(duì)應(yīng)信息了。

訪問(wèn)了:/aop省有,輸出

2018-08-23 22:54:59.003  INFO 12928 --- [nio-8080-exec-3] c.l.l.s.chapter24.config.LogAspect       : 開(kāi)始計(jì)時(shí): Fri Aug 23 22:54:59 CST 2018  URI: /aop
2018-08-23 22:54:59.004  INFO 12928 --- [nio-8080-exec-3] c.l.l.s.chapter24.config.LogAspect       : 請(qǐng)求方法:aopDemo, 請(qǐng)求參數(shù): [oKong]
2018-08-23 22:54:59.005  INFO 12928 --- [nio-8080-exec-3] c.l.l.s.chapter24.config.LogAspect       : 請(qǐng)求ip:192.168.2.107
2018-08-23 22:54:59.005  INFO 12928 --- [nio-8080-exec-3] c.l.l.s.chapter24.config.LogAspect       : log注解描述:請(qǐng)求了aopDemo方法
2018-08-23 22:54:59.005  INFO 12928 --- [nio-8080-exec-3] c.l.l.s.chapter24.config.LogAspect       : 結(jié)束計(jì)時(shí): Fri Aug 23 22:54:59 CST 2018,  URI: /aop,耗時(shí):2

參考資料

  1. https://blog.csdn.net/zhengchao1991/article/details/53391244
  2. https://blog.csdn.net/wqh8522/article/details/72887209

總結(jié)

本文主要是簡(jiǎn)單介紹了利用AOP實(shí)現(xiàn)統(tǒng)一的web日志記錄功能痒留。本示例未演示日志入庫(kù)功能,大家可自行實(shí)現(xiàn)蠢沿。在實(shí)際開(kāi)發(fā)過(guò)程中伸头,一般上都是將日志保存進(jìn)行異步化后進(jìn)行入庫(kù)處理的,這點(diǎn)需要注意舷蟀,日志記錄不能影響正常的方法請(qǐng)求恤磷,若是同步的,會(huì)本末倒置的野宜。本文只是簡(jiǎn)單的使用環(huán)繞機(jī)制進(jìn)行講解扫步,大家還可以試試其他的注解進(jìn)行相應(yīng)實(shí)踐下,大都大同小異匈子,只是要注意下各注解的觸發(fā)時(shí)機(jī)河胎。

最后

目前互聯(lián)網(wǎng)上很多大佬都有SpringBoot系列教程,如有雷同旬牲,請(qǐng)多多包涵了仿粹。本文是作者在電腦前一字一句敲的搁吓,每一步都是自己實(shí)踐和理解的原茅。若文中有所錯(cuò)誤之處,還望提出堕仔,謝謝擂橘。

老生常談

  • 個(gè)人QQ:499452441
  • 微信公眾號(hào):lqdevOps
公眾號(hào)

個(gè)人博客:http://blog.lqdev.cn

完整示例:https://github.com/xie19900123/spring-boot-learning/tree/master/chapter-24

原文地址:http://blog.lqdev.cn/2018/08/24/springboot/chapter-twenty-four/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市摩骨,隨后出現(xiàn)的幾起案子通贞,更是在濱河造成了極大的恐慌朗若,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件昌罩,死亡現(xiàn)場(chǎng)離奇詭異哭懈,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)茎用,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門遣总,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人轨功,你說(shuō)我怎么就攤上這事旭斥。” “怎么了古涧?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵垂券,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我羡滑,道長(zhǎng)菇爪,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任柒昏,我火速辦了婚禮娄帖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘昙楚。我一直安慰自己近速,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布堪旧。 她就那樣靜靜地躺著削葱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪淳梦。 梳的紋絲不亂的頭發(fā)上析砸,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音爆袍,去河邊找鬼首繁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛陨囊,可吹牛的內(nèi)容都是我干的弦疮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蜘醋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼胁塞!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤啸罢,失蹤者是張志新(化名)和其女友劉穎编检,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體扰才,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡允懂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衩匣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片累驮。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖舵揭,靈堂內(nèi)的尸體忽然破棺而出谤专,到底是詐尸還是另有隱情,我是刑警寧澤午绳,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布置侍,位于F島的核電站,受9級(jí)特大地震影響拦焚,放射性物質(zhì)發(fā)生泄漏蜡坊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一赎败、第九天 我趴在偏房一處隱蔽的房頂上張望秕衙。 院中可真熱鬧,春花似錦僵刮、人聲如沸据忘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)勇吊。三九已至,卻和暖如春窍仰,著一層夾襖步出監(jiān)牢的瞬間汉规,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工驹吮, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留针史,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓碟狞,卻偏偏與公主長(zhǎng)得像啄枕,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子篷就,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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

  • 每一句傷感的話語(yǔ) 都一片片割下我的心 在冷寂的冬季 清晰感受體溫的流逝 只有跟著音樂(lè)的節(jié)奏律動(dòng) 我才醒著卻沒(méi)了靈魂...
    閱簡(jiǎn)上書(shū)閱讀 225評(píng)論 2 4
  • 轉(zhuǎn)載請(qǐng)以鏈接形式標(biāo)明出處: http://www.reibang.com/p/66a4e1377ca8本文出自:...
    103style閱讀 2,558評(píng)論 3 9