攔截機(jī)制中Aspect突琳、ControllerAdvice、Interceptor符相、Fliter之間的區(qū)別詳解



????????在項(xiàng)目的開(kāi)發(fā)中拆融,在某些情況下,我們需要對(duì)客戶(hù)端發(fā)出的請(qǐng)求進(jìn)行攔截啊终,常用的API攔截方式有Fliter镜豹,Interceptor,ControllerAdvice以及Aspect蓝牲。

上圖是spring中的攔截機(jī)制,如果出現(xiàn)異常的話趟脂,異常的順序是從里面到外面一步一步的進(jìn)行處理,如果到了最外層都沒(méi)有進(jìn)行處理的話搞旭,就會(huì)由tomcat容器拋出異常散怖。下面我將詳細(xì)的解釋這四個(gè)攔截方式的不同菇绵。因?yàn)橹皇茄菔揪筒皇撬械氖褂昧巳罩居涗浺奚_@里相關(guān)的依賴(lài)自己可以去https://mvnrepository.com/下載,我就不一一添加了

先做一個(gè)總的總結(jié)吧

1.過(guò)濾器:Filter

:可以獲得Http原始的請(qǐng)求和響應(yīng)信息咬最,但是拿不到響應(yīng)方法的信息

2.攔截器:Interceptor

? :可以獲得Http原始的請(qǐng)求和響應(yīng)信息翎嫡,也拿得到響應(yīng)方法的信息,但是拿不到方法響應(yīng)中參數(shù)的值

3.ControllerAdvice(Controller增強(qiáng)永乌,自spring3.2的時(shí)候推出):

主要是用于全局的異常攔截和處理,這里的異郴笊辏可以使自定義異常也可以是JDK里面的異常

用于處理當(dāng)數(shù)據(jù)庫(kù)事務(wù)業(yè)務(wù)和預(yù)期不同的時(shí)候拋出封裝后的異常,進(jìn)行數(shù)據(jù)庫(kù)事務(wù)回滾翅雏,并將異常的顯示給用戶(hù)

4.切片:Aspect

? ?主要是進(jìn)行公共方法的

? 可以拿得到方法響應(yīng)中參數(shù)的值圈驼,但是拿不到原始的Http請(qǐng)求和相對(duì)應(yīng)響應(yīng)的方法


Filter(過(guò)濾器)

可以獲得Http原始的請(qǐng)求和響應(yīng)信息,但是拿不到響應(yīng)方法的信息

filter是屬于Servlet規(guī)范的望几,不屬于Spring

springboot中的配置方法:

自定義一個(gè)Filter

import javax.servlet.*;

import java.io.IOException;

public class TimeFilter implements Filter {

/**Filter接口中的部分方法添加了default關(guān)鍵字绩脆,這樣的方法就不是一定要重寫(xiě)*/

@Override

? ? public void init(FilterConfig filterConfig)throws ServletException {

System.out.println("Time Filter init");

? ? }

@Override

? ? public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {

System.out.println("time filter start");

? ? ? ? /**這里說(shuō)明一下,在JDK8以及之后的JDK版本中都不再建議使用new Date().getTime()這種方式來(lái)獲得時(shí)間*/

? ? ? ? long start = System.currentTimeMillis();

? ? ? ? chain.doFilter(request,response);

? ? ? ? System.out.println("time filter:"+(System.currentTimeMillis()-start));

? ? ? ? System.out.println("time filter finish");

? ? }

@Override

? ? public void destroy() {

System.out.println("time filter destroy");

? ? }

}

方式一:通過(guò)Bean注入的方式

注冊(cè)Filter橄抹,springboot當(dāng)中提供了FilterRegistrationBean類(lèi)來(lái)注冊(cè)Filter

import com.imooc.Filter.TimeFilter;

import com.imooc.Interceptor.TimeInterceptor;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.web.servlet.FilterRegistrationBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;

import java.util.List;

@Configuration

public class WebConfigimplements WebMvcConfigurer {

/**WebMvcConfigurerAdapter在JDK8中這個(gè)類(lèi)已經(jīng)過(guò)時(shí)靴迫,我們直接繼承這個(gè)類(lèi)所繼承的接口*/

@Bean

? ? public FilterRegistrationBeantimeFilter(){

FilterRegistrationBean registrationBean =new FilterRegistrationBean();

? ? ? ? TimeFilter timeFilter =new TimeFilter();

? ? ? ? registrationBean.setFilter(timeFilter);

????????/**添加攔截的地址*/

? ? ? ? List urls =new ArrayList<>();

? ? ? ? urls.add("/*");

? ? ? ? return registrationBean;

? ? }

}

方式二:通過(guò)@WebFilter注解實(shí)現(xiàn)

import org.springframework.stereotype.Component;

import javax.servlet.*;

import javax.servlet.annotation.WebFilter;

import java.io.IOException;

@Component

@WebFilter(filterName ="TimeFilter",urlPatterns ="/*")

public class TimeFilterimplements Filter {

@Override

? ? public void init(FilterConfig filterConfig)throws ServletException {

System.out.println("Time Filter init");

? ? }

@Override

? ? public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {

System.out.println("time filter start");

? ? ? ? /**這里說(shuō)明一下,在JDK8以及之后的JDK版本中都不再建議使用new Date().getTime()這種方式來(lái)獲得時(shí)間*/

? ? ? ? long start = System.currentTimeMillis();

? ? ? ? chain.doFilter(request,response);

? ? ? ? System.out.println("time filter:"+(System.currentTimeMillis()-start));

? ? ? ? System.out.println("time filter finish");

? ? }

@Override

? ? public void destroy() {

System.out.println("time filter destroy");

? ? }

}

@WebFilter 的常用屬性

屬性名? ? ? ? ? ? ? ????類(lèi)型? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 描述

filterName? ? ? ? ?????String? ? ? ? ? ? ? ? ? ? ? ????指定過(guò)濾器的 name 屬性楼誓,等價(jià)于 <filter-name>

value? ? ? ? ? ? ? ? ????? String[]? ? ? ? ? ? ? ? ? ? ? ?該屬性等價(jià)于 urlPatterns 屬性玉锌。但是兩者不應(yīng)該同時(shí)使用。

urlPatterns ????????????String[] ????????????????????????指定一組過(guò)濾器的 URL 匹配模式疟羹。等價(jià)于 <url-pattern> 標(biāo)簽主守。

servletNames? ? ? ????String[]? ? ? ? ? ? ? ? ? ? ? 指定過(guò)濾器將應(yīng)用于哪些 Servlet禀倔。取值是 @WebServlet 中的 name 屬性的取值,或者是

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????web.xml 中 <servlet-name> 的取值丸逸。

dispatcherTypes ????DispatcherType? ? ? ? ? ? ?指定過(guò)濾器的轉(zhuǎn)發(fā)模式蹋艺。具體取值包括:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????ASYNC、ERROR黄刚、FORWARD捎谨、INCLUDE、REQUEST憔维。

initParams ????????????????WebInitParam[] ????????????指定一組過(guò)濾器初始化參數(shù)涛救,等價(jià)于 <init-param> 標(biāo)簽。

asyncSupported ????????boolean ????????????????????????聲明過(guò)濾器是否支持異步操作模式业扒,等價(jià)于 <async-supported> 標(biāo)簽检吆。

description ????????????????String ????????????????????????????該過(guò)濾器的描述信息,等價(jià)于 <description> 標(biāo)簽程储。

displayName ????????????????String ????????????????????????該過(guò)濾器的顯示名蹭沛,通常配合工具使用,等價(jià)于 <display-name> 標(biāo)簽章鲤。

相較而言摊灭,方式一會(huì)更加的靈活,而方式二更加的方便败徊,但是兩者在實(shí)質(zhì)上是一樣的


Interceptor (攔截器) :

可以獲得Http原始的請(qǐng)求和響應(yīng)信息帚呼,也拿得到響應(yīng)方法的信息,但是拿不到方法響應(yīng)中參數(shù)的值

在web開(kāi)發(fā)中皱蹦,攔截器是經(jīng)常用到的功能煤杀。它可以幫我們驗(yàn)證是否登陸、預(yù)先設(shè)置數(shù)據(jù)以及統(tǒng)計(jì)方法的執(zhí)行效率等沪哺。在spring中攔截器有兩種沈自,第一種是HandlerInterceptor,第二種是MethodInterceptor辜妓。HandlerInterceptor是SpringMVC中的攔截器枯途,它攔截的是Http請(qǐng)求的信息,優(yōu)先于MethodInterceptor嫌拣。而MethodInterceptor是springAOP的柔袁。前者攔截的是請(qǐng)求的地址,而后者是攔截controller中的方法异逐,因?yàn)橄旅嬉獙spect捶索,就不詳細(xì)講述MethodInterceptor

在springboot中HandlerInterceptor的配置

1.首先定義自己的Interceptor

import org.springframework.stereotype.Component;

import org.springframework.web.method.HandlerMethod;

import org.springframework.web.servlet.HandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

/**

* 攔截器會(huì)攔截所有的控制器,不管是spring的還是自定義的

*/

@Component

public class TimeInterceptorimplements HandlerInterceptor {

/**

? ? *控制器方法調(diào)用之前會(huì)進(jìn)行

? ? *和上面的Filter一樣灰瞻,繼承的某些接口方法中也加了default關(guān)鍵字腥例,可以不用重寫(xiě)辅甥,這里為了演示就都寫(xiě)了

*/

? ? @Override

? ? public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {

System.out.println("proHandle");

? ? ? ? System.out.println(((HandlerMethod)handler).getBean().getClass().getName());

? ? ? ? System.out.println(((HandlerMethod)handler).getMethod().getName());

? ? ? ? request.setAttribute("startTime",System.currentTimeMillis());

return true;

? ? ? ? /**true的話 就是選擇可以調(diào)用后面的方法? 也就是controller中的getInfo方法*/

? ? }

/**控制后方法執(zhí)行之后會(huì)進(jìn)行,拋出異常則不會(huì)被執(zhí)行*/

? ? @Override

? ? public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception {

System.out.println("postHandle");

? ? ? ? Long start = (Long)request.getAttribute("startTime");

? ? ? ? System.out.println("time interceptor 耗時(shí):"+(System.currentTimeMillis()-start));

? ? }

/**方法被調(diào)用或者拋出異常都會(huì)被執(zhí)行*/

? ? @Override

? ? public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {

System.out.println("afterCompletion");

? ? ? ? Long start = (Long)request.getAttribute("startTime");

? ? ? ? System.out.println("time interceptor 耗時(shí):"+(System.currentTimeMillis()-start));

? ? }zai

}

2.在配置類(lèi)中配置自定義的Interceptor

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.imooc.Interceptor.TimeInterceptor;

import org.springframework.beans.factory.annotation.Autowired;

@Configuration

public class WebConfigimplements WebMvcConfigurer {

/**WebMvcConfigurerAdapter在JDK8中這個(gè)類(lèi)已經(jīng)過(guò)時(shí)燎竖,我們直接繼承這個(gè)類(lèi)所繼承的接口*/

? ? @Autowired

? ? private TimeInterceptortimeInterceptor;

? ? @Override

? ? public void addInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(timeInterceptor);

? ? }

}


ControllerAdvice(Controller增強(qiáng)璃弄,自spring3.2的時(shí)候推出):

用于處理當(dāng)數(shù)據(jù)庫(kù)事務(wù)業(yè)務(wù)和預(yù)期不同的時(shí)候拋出封裝后的異常,進(jìn)行數(shù)據(jù)庫(kù)事務(wù)回滾构回,并將異常的顯示給用戶(hù)

1.定義自己的異常類(lèi)

import lombok.Data;

@Data

public class UserNotExistExceptionextends RuntimeException{

private static final long serialVersionUID =4820951478405122770L;

? ? private Stringid;

? ? public UserNotExistException(String id) {

super("user not exist.......");

? ? ? ? this.id = id;

? ? }

}

2.編寫(xiě)全局異常處理類(lèi)

import com.imooc.Exception.UserNotExistException;

import org.springframework.http.HttpStatus;

import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.web.bind.annotation.ExceptionHandler;

import org.springframework.web.bind.annotation.ResponseBody;

import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.HashMap;

import java.util.Map;

@ControllerAdvice

public class ControllerExceptionHandler {

/**指定拋出的異常類(lèi)*/

@ExceptionHandler(UserNotExistException.class)

/**如果全部異常處理返回json格式夏块,那么可以使用 @RestControllerAdvice 代替 @ControllerAdvice ,這樣在方法上就可以不需要添加 @ResponseBody.@ResponseBody注解的作用是將controller的方法返回的對(duì)象通過(guò)適當(dāng)?shù)霓D(zhuǎn)換器轉(zhuǎn)換為指定的格式之后纤掸,寫(xiě)入到response對(duì)象的body區(qū)脐供,通常用來(lái)返回JSON數(shù)據(jù)或者是XML數(shù)據(jù)。*/

@ResponseBody

? ? @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)

/**當(dāng)出現(xiàn)該Http狀態(tài)碼的時(shí)候拋出異常*/

? ? public MaphandlerUserNotExistException(UserNotExistException exception){

Map result =new HashMap<>();

? ? ? ? result.put("id",exception.getId());

? ? ? ? result.put("message",exception.getMessage());

? ? ? ? return result;

? ? }

}

3借跪、controller中拋出異常進(jìn)行測(cè)試

import com.imooc.Exception.UserNotExistException;

import com.imooc.dto.User;

import com.imooc.dto.UserQueryCondition;

import lombok.extern.slf4j.Slf4j;

import org.springframework.validation.BindingResult;

import org.springframework.web.bind.annotation.*;

@RestController

public class UserController {

? ??@GetMapping(value ="/user/{id}")

????public UsergetInfo(@PathVariable String id)throws Exception{

????throw new UserNotExistException(id);

? ? ????}

}



Aspect(切面):

? ????可以拿得到方法響應(yīng)中參數(shù)的值政己,但是拿不到原始的Http請(qǐng)求和相對(duì)應(yīng)響應(yīng)的方法,基于Controller層掏愁。對(duì)于統(tǒng)一異常處理和日志記錄非常方便歇由,有效地減少了代碼的重復(fù)率。

可以參照https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html果港,spring的官方文檔

1.創(chuàng)建Controller

2.創(chuàng)建一個(gè)Aspect切面

import lombok.extern.slf4j.Slf4j;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.springframework.stereotype.Component;

@Aspect

@Component

@Slf4j

public class TimeAspect {

@Around("execution(* com.imooc.controller.UserController.*(..))")

public ObjecthandleControllerMethod(ProceedingJoinPoint proceedingJoinPoint)throws Throwable {

log.info("Time aspect start");

? ? ? ? Long start = System.currentTimeMillis();

? ? ? ? Object[] args = proceedingJoinPoint.getArgs();

? ? ? ? for(Object object:args)

{

log.info("arg is:"+String.valueOf(object));

? ? ? ? }

Object object =proceedingJoinPoint.proceed();

? ? ? ? System.out.println("time filter:"+(System.currentTimeMillis()-start));

? ? ? ? log.info("Time aspect finish");

? ? ? ? return object;

? ? }

}

切面的方法說(shuō)明:

@Aspect

作用是把當(dāng)前類(lèi)標(biāo)識(shí)為一個(gè)切面供容器讀取

@Before

標(biāo)識(shí)一個(gè)前置增強(qiáng)方法沦泌,相當(dāng)于BeforeAdvice的功能

@AfterReturning

后置增強(qiáng),相當(dāng)于AfterReturningAdvice京腥,方法退出時(shí)執(zhí)行

@AfterThrowing

異常拋出增強(qiáng)赦肃,相當(dāng)于ThrowsAdvice

@After

final增強(qiáng)溅蛉,不管是拋出異彻耍或者正常退出都會(huì)執(zhí)行

@Around

環(huán)繞增強(qiáng),相當(dāng)于MethodInterceptor

除了@Around外船侧,每個(gè)方法里都可以加或者不加參數(shù)JoinPoint欠气,如果有用JoinPoint的地方就加,不加也可以镜撩,JoinPoint里包含了類(lèi)名预柒、被切面的方法名,參數(shù)等屬性袁梗,可供讀取使用宜鸯。@Around參數(shù)必須為ProceedingJoinPoint,pjp.proceed相應(yīng)于執(zhí)行被切面的方法遮怜。@AfterReturning方法里淋袖,可以加returning = “XXX”,XXX即為在controller里方法的返回值锯梁,本例中的返回值是“first controller”即碗。@AfterThrowing方法里焰情,可以加throwing = "XXX"

關(guān)于切面PointCut的切入點(diǎn)

execution切點(diǎn)函數(shù)

execution函數(shù)用于匹配方法執(zhí)行的連接點(diǎn),語(yǔ)法為:

execution(方法修飾符(可選) ?返回類(lèi)型 ?方法名 ?參數(shù) ?異常模式(可選))?

例如:execution(* com.imooc.controller.UserController.*(..))

第一個(gè)*代表的是所有的返回值類(lèi)型剥懒,com.imooc.controller.UserController.*代表的是com.imooc.controller包下UserController類(lèi)的所有方法内舟,(..)代表的是所有的參數(shù)

參數(shù)部分允許使用通配符:

* ?匹配任意字符,但只能匹配一個(gè)元素

.. 匹配任意字符初橘,可以匹配任意多個(gè)元素验游,表示類(lèi)時(shí),必須和*聯(lián)合使用

+ ?必須跟在類(lèi)名后面保檐,如Horseman+批狱,表示類(lèi)本身和繼承或擴(kuò)展指定類(lèi)的所有類(lèi)

除了execution(),Spring中還支持其他多個(gè)函數(shù)展东,這里列出名稱(chēng)和簡(jiǎn)單介紹赔硫,以方便根據(jù)需要進(jìn)行更詳細(xì)的查詢(xún)

?@annotation()

表示標(biāo)注了指定注解的目標(biāo)類(lèi)方法

例如 @annotation(org.springframework.transaction.annotation.Transactional) 表示標(biāo)注了@Transactional的方法

args()

通過(guò)目標(biāo)類(lèi)方法的參數(shù)類(lèi)型指定切點(diǎn)

例如 args(String) 表示有且僅有一個(gè)String型參數(shù)的方法

@args()

通過(guò)目標(biāo)類(lèi)參數(shù)的對(duì)象類(lèi)型是否標(biāo)注了指定注解指定切點(diǎn)

如 @args(org.springframework.stereotype.Service) 表示有且僅有一個(gè)標(biāo)注了@Service的類(lèi)參數(shù)的方法

within()

通過(guò)類(lèi)名指定切點(diǎn)

如 with(examples.chap03.Horseman) 表示Horseman的所有方法

target()

通過(guò)類(lèi)名指定,同時(shí)包含所有子類(lèi)

如 target(examples.chap03.Horseman) ?且Elephantman extends Horseman盐肃,則兩個(gè)類(lèi)的所有方法都匹配

@within()

匹配標(biāo)注了指定注解的類(lèi)及其所有子類(lèi)

如?@within(org.springframework.stereotype.Service) 給Horseman加上@Service標(biāo)注爪膊,則Horseman和Elephantman 的所有方法都匹配

@target()

所有標(biāo)注了指定注解的類(lèi)

如?@target(org.springframework.stereotype.Service)?表示所有標(biāo)注了@Service的類(lèi)的所有方法

?this()

大部分時(shí)候和target()相同,區(qū)別是this是在運(yùn)行時(shí)生成代理類(lèi)后砸王,才判斷代理類(lèi)與指定的對(duì)象類(lèi)型是否匹配

關(guān)于Aspect參考了https://www.cnblogs.com/bigben0123/p/7779357.html推盛,如有侵權(quán),請(qǐng)作者聯(lián)系刪除


具體使用哪種攔截機(jī)制還是要根據(jù)項(xiàng)目開(kāi)發(fā)的需求來(lái)決定谦铃。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末耘成,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子驹闰,更是在濱河造成了極大的恐慌瘪菌,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘹朗,死亡現(xiàn)場(chǎng)離奇詭異师妙,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)屹培,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)默穴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人褪秀,你說(shuō)我怎么就攤上這事蓄诽。” “怎么了媒吗?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵仑氛,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我蝴猪,道長(zhǎng)调衰,這世上最難降的妖魔是什么膊爪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮嚎莉,結(jié)果婚禮上米酬,老公的妹妹穿的比我還像新娘。我一直安慰自己趋箩,他們只是感情好赃额,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著叫确,像睡著了一般跳芳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上竹勉,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天飞盆,我揣著相機(jī)與錄音,去河邊找鬼次乓。 笑死吓歇,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的票腰。 我是一名探鬼主播城看,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼杏慰!你這毒婦竟也來(lái)了测柠?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤缘滥,失蹤者是張志新(化名)和其女友劉穎轰胁,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體完域,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡软吐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年瘩将,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吟税。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡姿现,死狀恐怖肠仪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情备典,我是刑警寧澤异旧,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站提佣,受9級(jí)特大地震影響吮蛹,放射性物質(zhì)發(fā)生泄漏荤崇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一潮针、第九天 我趴在偏房一處隱蔽的房頂上張望术荤。 院中可真熱鬧,春花似錦每篷、人聲如沸瓣戚。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)子库。三九已至,卻和暖如春矗晃,著一層夾襖步出監(jiān)牢的瞬間仑嗅,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工张症, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留无畔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓吠冤,卻偏偏與公主長(zhǎng)得像浑彰,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拯辙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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