Spring-web

spring-web,spring-webmvc模块笔记,这块的类非常多,采用包划分对主要类&接口进行说明

Http部分

常用的常量和枚举

MediaType,HttpStatus,HttpHeaders,RequestMethod(有非常常用的key)

常见的接口

ClientHttpRequestFactory:请求对象生成工厂.常见的有HttpComponentsClientHttpRequestFactory,封装HttpClient对象

ClientHttpRequest:请求对象.可以执行请求方法,返回响应对象

ClientHttpResponse:响应对象.对于HttpComponentsClientHttpResponse而言就是封装HttpResponse

InterceptingClientHttpRequest-这里引入请求拦截器采用iterator来实现的责任链模式,这种实现还是第一次见,和i++的套路一样

HttpMessageConverterExtractor:消息转换提取器.类型转换

HttpMessageConverter:这个接口非常重要.它是实际的Java对象+MediaType与Http消息(请求->参数读取,响应->返回值写入)之间的转换,如MappingJackson2HttpMessageConverter

HttpEntity:表示一个Http实体对象,含有HttpHeaders信息和返回的body信息.后面分为RequestEntity和ResponseEntity

RestTemplate:通过api编程式发起http请求.实现部分通过RequestCallback构造请求回调,处理头信息和参数转换.返回时同理,它引入请求工厂和响应消息提取器帮助处理

remoting-httpinvoker

HttpInvokerRequestExecutor:请求执行器.默认采用jdk的http发送,可以换成HttpComponentsHttpInvokerRequestExecutor使用apache的

HttpInvokerProxyFactoryBean:客户端代理.配置url,本地接口代理,调用请求执行器获取执行结果

HttpInvokerServiceExporter:服务端执行器.配置实际执行代理对象,序列化和反序列化返回

web包

SpringServletContainerInitializer:servlet3.0支持的容器初始化调用方式,spring将会对jar包中所有的WebApplicationInitializer类进行初始化

WebApplicationInitializer:内部的容器初始化回调的接口

HttpRequestHandler:主要是配合HttpRequestHandlerAdapter进行转换映射调用.可以比较通用的处理request和response,框架内使用较多

RequestAttributes:定义了request的基本属性及操作.使用较多的是ServletRequestAttributes

RequestScope/SessionScope:继承AbstractRequestAttributesScope,将资源绑定到request中.每次请求进来后通过RequestContextHolder获取

context

WebApplicationContext:web容器的顶层定义.它继承原ApplicationContext

ConfigurableWebApplicationContext:可配置的WebApplicationContext接口定义

ConfigurableWebEnvironment:定义web环境.主要为将ServletContext和ServletConfig内容加载到环境中,一般实现为StandardServletEnvironment

ServletContextScope:与ServletContext对象绑定参数

StandardServletEnvironment:将ServletConfigPropertySource与ServletContextPropertySource对应的配置参数注册到环境对象中

AbstractContextLoaderInitializer:将ContextLoaderListener绑定到ServletContext

拓展容器类

AbstractRefreshableWebApplicationContext:web容器的基类.在postProcessBeanFactory阶段进行了初始化,包括ServletContextAware,ServletConfigAware的支持,web中scope的支持,ServletRequest,ServletResponse的属性注入支持,将ServletContext,ServletConfig加入容器等对应的web调整

AnnotationConfigWebApplicationContext:重写loadBeanDefinitions方法.载入AnnotatedBeanDefinitionReader对象,将处理注解需要的配置类注册到容器

XmlWebApplicationContext:重写loadBeanDefinitions方法.载入XmlBeanDefinitionReader对象,以xml的形式直接解析给定的资源集合

GenericWebApplicationContext:基本web应用,包含ServletContext对象的Aware提供,web相关作用域注册,主题支持

Listener相关

ContextLoaderListener:容器初始化后加载context对象并刷新,绑定context对象到容器中(默认加载的是XmlWebApplicationContext)

ContextCleanupListener:关闭容器时.对容器的属性中以”org.springframework.”开头的属性检查是否为DisposableBean,符合条件则调用destroy()方法

RequestContextListener:实现了ServletRequestListener,当有请求进入时将request对象绑定到RequestContextHolder中

ServletRequestHandledEvent:当请求完成后会推送的事件

cors

origin不支持ant风格 表示全部否则必须精准匹配域名,比如:http://domain1.com

CorsProcessor:DefaultCorsProcessor对跨域请求的是否允许判定,以及响应头信息

CorsConfiguration:跨域配置.如允许的origin/method等

CorsConfigurationSource:管理url对应的CorsConfiguration

CorsRegistration:标记了url和对应的CorsConfiguration配置

CorsRegistry:提供了管理一组CorsRegistration的能力

filter

GenericFilterBean:实现Filter默认的init方法,尝试将过滤器初始化的参数设置到当前对象属性中.通过BeanWrapper形式设值的,可以参考下

OncePerRequestFilter:保证一次请求只执行一次过滤器.其通过在request中增加FilterName属性进而判断,还有默认的不过滤异步,不过滤已产生错误行为.这是一个很好的基类,基本上所有的Filter都继承此基类.

CommonsRequestLoggingFilter:在拦截器执行前和执行后进行日志输出

CharacterEncodingFilter:字符编码设值过滤器.在执行前在request或response调用setCharacterEncoding(encoding)方法

CorsFilter:跨域过滤器处理.判断是否跨域请求.进行判定处理,主要依托CorsProcessor和CorsConfigurationSource类

HiddenHttpMethodFilter:在post请求中参数(默认_method)的值转为request.getMethod方法返回的值,用于有些请求中的方法指定

HttpPutFormContentFilter:支持PUT和PATCH请求的表单提交(默认情况下只支持GET和POST的表单)

RelativeRedirectFilter:通过RelativeRedirectResponseWrapper包装原Response对象,重写默认的sendRedirect重定向方法改为相对路径重定向

RequestContextFilter:主要将request对象绑定到RequestContextHolder中,方便后续直接获取

MultipartFilter:判断当前content-type为”multipart/*”的多文件类型,那么将request转为MultipartHttpServletRequest

method

ControllerAdviceBean:将@ControllerAdvice注解转换为类对象操作

HandlerMethodArgumentResolver:参数解析器 对进行注解/指定类型的参数做转换

HandlerMethodReturnValueHandler:方法返回处理器

ModelAttributeMethodProcessor:默认非简单类型的处理转换.将表单数据读取通过DataBinder设值到参数对象,默认表单提交的参数转换器

RequestResponseBodyMethodProcessor:将@ResponseBody注解的参数从body体读取换成对应类型的对象以及支持 @ResponseBody注解的返回值返回json,实际上通过HttpMessageConverter进行的转换,ReturnValueHandler更多是处理header信息设置,具体的转换还是委托出去通过转换器处理

对参数和返回值做处理的2个常见处理器就是ModelAttributeMethodProcessor和RequestResponseBodyMethodProcessor

WebDataBinderFactory:创建DataBinder的工厂

DataBinder:进行数据绑定,转换和验证的聚合类.简单来看就是通过k-v的形式进行设值,并且将key对应value的对应属性类型进行转换处理

multipart

MultipartFile: 上传文件的定义.主要实现为StandardMultipartFile

MultipartRequest:定义了Request操作获取MultipartFile的接口

MultipartHttpServletRequest:多文件上传时request会被转为此接口定义,它继承了MultipartRequest接口.

StandardMultipartHttpServletRequest:servlet3.0的标准实现.主要将javax.servlet.http.Part对象转为StandardMultipartFile对象

MultipartResolver:判断当前Request是否为多文件请求,转换request到MultipartHttpServletRequest.一般实现为StandardServletMultipartResolver

必须配合MultipartFilter过滤器使用,可以配合RequestPartMethodArgumentResolver参数解析支持@RequestPart注解

util

DefaultUriBuilderFactory:提供uri的基本转换,编码,参数设置.

ContentCachingRequestWrapper:缓存request的内容,通过getContentAsByteArray方法可以多次获取

ContentCachingResponseWrapper:缓存response的响应内容,通过getContentAsByteArray方法可以多次获取,最后可以通过copyBodyToResponse响应

webmvc

FrameworkServlet:主要定义初始化流程方法(initWebApplicationContext),以及HttpServlet的所有请求方法统一转到processRequest让子类doService处理,在顶层进行了Request和LocaleContext的线程绑定


这里详细说下DispatcherServlet核心转发流程部分.

初始化包含:

initMultipartResolver(context);

initLocaleResolver(context);

initThemeResolver(context);

initHandlerMappings(context);

initHandlerAdapters(context);

initHandlerExceptionResolvers(context);

initRequestToViewNameTranslator(context);

initViewResolvers(context);

initFlashMapManager(context);

这里的初始化很多都是直接指定到"beanName+类型"也就是beanName不对的话也不会成功,比如MultipartResolver的beanName就必须是multipartResolver

主要执行流程:

入口请求都会到doService,它先把自己流程中使用到的Bean通过request属性暴露出去,然后执行核心转发接口doDispatch,

先检查是否为multipartRequest,如果是的话,通过multipartResolver把request换为MultipartHttpServletRequest

通过初始化的HandlerMapping列表依次进行getHandler来获取本次uri可以支持的HandlerExecutionChain(常见RequestMappingHandlerMapping)

继续通过初始化的HandlerAdapter列表进行support检查handler以找到对应的HandlerAdapter.

HandlerExecutionChain中已经初始化过了拦截器,此时开始执行前置拦截器

然后通过HandlerAdapter开始进行实际调用(常见RequestMappingHandlerAdapter)

这里举例RequestMappingHandlerAdapter#invokeHandlerMethod流程

1@InitBinder解析

    解析执行类和@ControllerAdvice注解类的@InitBinder注解方法. 通过使用统一的WebDataBinderFactory在初始化DataBinder时将所有参数调用@InitBinder注解的方法在参数中传入DataBinder对象,让方法可以调整所有的参数转换和赋值

2@ModelAttribute解析

    解析执行类和@ControllerAdvice注解类的@ModelAttribute注解方法.  在执行目标方法前,先调用所有的@ModelAttribute注解方法

3执行目标方法并返回

    生成ServletInvocableHandlerMethod对象来执行目标方法.将参数一一通过参数解析器转换,然后调用方法,最后如果需要的话对返回值进行转换处理

然后执行后置拦截器,最后进行结果处理

结果处理流程-如果有异常,那么通过之前初始化的HandlerExceptionResolver列表获取可以解析此异常的方法,并调用,获取返回值(通常无需返回值,直接通过response响应)替换原返回值,将获得的返回值ModelAndView进行处理,主要为通过之前初始化的ViewResolver列表获取View对象,然后调用将之前全流程组装的Model对象和request,response一起传入渲染方法render中进行响应处理(比如jsp,html页面,静态资源等)


Handle映射处理器

HandlerMapping: 映射处理器顶层接口.处理url->handler的关系,以及url->HandlerInterceptor的关系

AbstractHandlerMapping:定义getHandler的基本流程,委托子类获取Handler对象,添加符合条件的过滤器到执行链中,生成HandlerExecutionChain返回

AbstractHandlerMethodMapping:定义了getHandlerInternal基本流程,进行url匹配HandlerMethod,如果有多于1个HandlerMethod被匹配,抛出错误信息,否则设置request的attribute信息将HandlerMapping接口中的几个属性暴露出来,最后返回HandlerMethod.同时它也实现了Handler和Method的收集和url映射规则.它实现了InitializingBean,在初始化时调用子类判定bean和method是否需要映射,如果需要将映射信息保存到MappingRegistry内部类中

RequestMappingInfoHandlerMapping:为Handler引入具化类型RequestMappingInfo,同时实现部分父类抽象方法

RequestMappingHandlerMapping:引入@Controller和@RequestMapping注解的实现.实现父类需要具体判断的抽象方法

BeanNameUrlHandlerMapping:BeanName以”/“开头的直接当做url注册为处理,不过需要注意bean要实现Controller接口,可以选择继承AbstractController

其他关联类

HandlerExecutionChain:保存handler对象(这里的handler对象会被对应的XXAdapter进一步处理),控制当次请求过滤器链HandlerInterceptor的访问

HandlerMethod:保存Handler和Method的上下文和提供便捷操作方法

InvocableHandlerMethod:提供了请求参数转换和调用方法的功能

ServletInvocableHandlerMethod:增加了对返回值的处理转换能力

HandlerMethodArgumentResolver:参数解析器 一般情况通过HandlerMethodArgumentResolverComposite包装组合引用

HandlerMethodReturnValueHandler:返回值处理器 一般情况通过HandlerMethodReturnValueHandlerComposite包装组合引用

Handle适配器-适配转换Handler的调用处理

HandlerAdapter:接过HandlerMapping解析请求得到的handler对象.更精确的定位到能够执行请求的方法包装类

HttpRequestHandlerAdapter:转换适配带HttpRequestHandler接口handle的方法调用

SimpleControllerHandlerAdapter:转换适配带Controller接口handle的方法调用

RequestMappingHandlerAdapter:对RequestMappingInfo这个Handler的具化处理.这是一个主要的映射处理类.初始化了默认的参数解析器,@InitBinder时调用的参数解析器,返回值参数解析器,支持了@ControllerAdvice注解类中@InitBinder方法的全局调用,@ModelAttribute注解的方法级调用和全局调用

DataBinder-包装对象的访问/转换/验证封装

ServletRequestDataBinder:在bind时支持将reqesut.getParameterNames中的属性绑定到类对象属性

ExtendedServletRequestDataBinder:将URI信息也一起绑定到对象属性中

WebDataBinderFactory: DataBinder工厂.其中InitBinderDataBinderFactory在创建DataBinder时将@InitBinder注解的方法均触发执行

method

RequestBodyAdvice:允许在读取消息前后进行操作消息内容

ResponseBodyAdvice:允许在返回消息体前进行操作消息内容

RequestResponseBodyAdviceChain:持有一组RequestBodyAdvice和ResponseBodyAdvice.在RequestResponseBodyMethodProcessor对参数进行解析前后,触发所有的回调.

常见转换器转换器

AbstractJackson2HttpMessageConverter:Jackson转换的顶层接口

MappingJackson2HttpMessageConverter:通过ObjectMapper转换Json对象,用的非常多

MappingJackson2XmlHttpMessageConverter:通过ObjectMapper转换xml对象

AbstractJsonHttpMessageConverter:Json转换顶层接口

GsonHttpMessageConverter:通过Gson转换json对象

ByteArrayHttpMessageConverter:可以直接将body内容转为byte[]参数,也可以直接返回byte[]

FormHttpMessageConverter:表单提交内容可以转为MultiValueMap参数

resolver-常用的参数/返回值解析器

很多参数解析器的功能都是通过HttpMessageConverter来实现,他们自身实现具体一种MediaType数据获取方式,然后将具体的参数转换方法让转换器完成

以MethodArgumentResolver结尾一般代表方法参数解析

RequestPartMethodArgumentResolver:支持参数注解@RequestPart解析

RequestAttributeMethodArgumentResolver:支持参数注解@RequestAttribute解析

PathVariableMethodArgumentResolver:支持非Map参数类型的@PathVariable注解解析

PathVariableMapMethodArgumentResolver:支持Map参数类型的@PathVariable注解解析

ServletRequestMethodArgumentResolver:支持servlet的一些api参数解析.如:ServletRequest,MultipartRequest,InputStream

ServletResponseMethodArgumentResolver:支持servlet的一些api返回值解析.如:ServletResponse

SessionAttributeMethodArgumentResolver:支持参数注解@SessionAttribute解析

以ReturnValueHandler结尾一般代表返回值解析

HttpHeadersReturnValueHandler:支持返回类型HttpHeaders

ModelAndViewMethodReturnValueHandler:支持返回值类型ModelAndView

ViewMethodReturnValueHandler:支持View类型的返回值解析

ViewNameMethodReturnValueHandler:支持String类型的返回值当做viewName进行解析

以Processor结尾一般代表既有参数值解析也有返回值解析

HttpEntityMethodProcessor:支持参数和返回值为HttpEntity类型

RequestResponseBodyMethodProcessor:支持@RequestBody参数注解和@ResponseBody的返回值注解

MvcConfig配置

基本上xxRegistry都是管理一组配置项 xxConfigurer就是全局统一的配置项

InterceptorRegistry:拦截器注册表.管理一组InterceptorRegistration拦截器配置类,可以通过getInterceptor()方法得到MappedInterceptor对象

CorsRegistry:跨域注册表.同理.持有一组CorsRegistration,然后可以直接获取CorsConfiguration

WebMvcConfigurer:配置接口.子类实现后可以通过xxConfigurer和xxRegistry进行调整

WebMvcConfigurationSupport:@EnableWebMvc注解提供的默认配置 注意,它不是配置接口,它是持有一组WebMvcConfigurer的配置类对象,和默认配置

默认HandlerMapping有RequestMappingHandlerMapping,BeanNameUrlHandlerMapping以及SimpleUrlHandlerMapping(注册的有
viewControllerHandlerMapping(对应的handler为ParameterizableViewController)
resourceHandlerMapping(对应的handler为ResourceHttpRequestHandler)
defaultServletHandlerMapping(对应的handler为DefaultServletHttpRequestHandler))

默认的HandlerAdapter有RequestMappingHandlerAdapter,HttpRequestHandlerAdapter,SimpleControllerHandlerAdapter(必须有这些适配器,否则上面的各种Handler就没法起作用了)

默认的异常解析器组合异常解析器HandlerExceptionResolverComposite
其中最主要的为ExceptionHandlerExceptionResolver,其次还有ResponseStatusExceptionResolver和DefaultHandlerExceptionResolver这俩

可以配置很多WebMvcConfigurer的Bean,最后在WebMvcConfigurationSupport中会进行汇总回调配置

Mvc

Controller:接口,处理Request到ModelAndView转换

UrlFilenameViewController:url解析后直接访问资源视图.可以简单的配置BeanName映射然后访问静态资源

ModelAndView:方便将Model和View一起操作.在它之前的mav信息都是操作ModelAndViewContainer对象

ViewResolver:视图解析器.通过viewName返回View对象.比较常见的是InternalResourceViewResolver(普通的jsp,html加载都是它)

View:视图.只有一个渲染接口,响应内容

Resource

通过SimpleUrlHandlerMapping将url规则与ResourceResolver建立关联,最后通过HttpRequestHandlerAdapter调用ResourceHttpRequestHandler

ResourceHttpRequestHandler :资源请求处理handler

ResourceResolver是指资源解析过滤器链,包含有

CachingResourceResolver:增加一层spring缓存

GzipResourceResolver:gzip打包

PathResourceResolver:根据uri进行资源访问

DefaultResourceResolverChain:便于通过责任链模式操作ResourceResolver列表

DefaultResourceTransformerChain:便于通过责任链模式操作ResourceTransformer列表

View

InternalResourceViewResolver:内部资源视图解析器.比较常用的视图解析器,可以配置前后缀方便代码简化,以前使用的非常多,现在前后端分离后几乎不使用了

InternalResourceView:内部资源视图.通过RequestDispatcher的include(request, response);方法直接解析


spring-web中常见注解

@InitBinder:通过注解指定方法调整WebDataBinder对象(InitBinderDataBinderFactory).是整个流程所有参数都生效的

@ModelAttribute:支持在方法上设置,即可以调整Model对象属性(ModelFactory),也可以在参数标注,即为表单映射数据解析(ModelAttributeMethodProcessor).不过实际上默认的非简单类型都使用的这个参数解析器,实际参数上用的不多(参考这个)

@ExceptionHandler:标注方法可以处理的异常.配合@ControllerAdvice使用

@ControllerAdvice:注解内部使用@ExceptionHandler,@InitBinder,@ModelAttribute注解的方法应用到所有的@RequestMapping注解的方法.其中异常处理使用的最多

@CookieValue:将cookie里的值直接取到方法参数中(ServletCookieValueMethodArgumentResolver)

@CrossOrigin:跨域请求配置,支持类级和方法级(RequestMappingHandlerMapping#initCorsConfiguration)

@RequestMapping:用于将Web请求映射到请求处理类中的方法的注解(RequestMappingHandlerMapping)

@GetMapping,@PostMapping,@PutMapping,@DeleteMapping,@PatchMapping 都是@RequestMapping注解指定了http方法的组合注解

@MatrixVariable:便捷的提取指定格式参数(MatrixVariableMapMethodArgumentResolver,MatrixVariableMethodArgumentResolver)

@PathVariable:处理URI中参数的提取(PathVariableMethodArgumentResolver)

@RequestAttribute:类似request.getAttribute(key)一样获取Attribute中的值(RequestAttributeMethodArgumentResolver)

@RequestBody:处理body体内数据转换.一般情况是json数据(RequestResponseBodyMethodProcessor)

@ResponseBody:将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据,需要注意的呢,在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。

@RequestHeader:提取Header信息(RequestHeaderMethodArgumentResolver)

@RequestParam:默认的处理简单的类型参数映射.主要有get请求和post的表单提交(RequestParamMethodArgumentResolver)

@RequestPart:接收文件类型(MultipartFile)或文件集合类型(比如List<MultipartFile>)可以指定文件名的注解,如果没有此注解将会使用参数名作为默认名称

@ResponseStatus:在对应方法内发生异常时,将会按照方法或异常类含有的该枚举值进行设值提示

@RestController:@Controller+@ResponseBody的组合注解

@RestControllerAdvice:@ControllerAdvice+@ResponseBody的组合注解

@SessionAttribute,@SessionAttributes:从session获取值

@EnableWebMvc:引入默认配置DelegatingWebMvcConfiguration


类型转换的对比 BeanWrapper、DataBinder、ConversionService、Formatter

BeanWrapper

BeanWrapper提供了对属性设置的支持。BeanWrapper通常不会被应用程序的代码直接使用,而是由DataBinder和BeanFactory使用。

BeanWrapper的名字已经部分暗示了它的工作方式:它包装一个bean以对其执行操作,比如设置和获取属性。

支持复杂对象路由,数组对象,map对象

内置PropertyEditor,PropertyEditor隶属于Java Bean规范。PropertyEditor只提供了String <-> Object的转换。

使用PropertyEditorRegistry,继承PropertyEditorRegistrySupport管理PropertyEditor

ConversionService

ConversionService及其相关一套类型转换机制是一套通用的类型转换SPI,相比PropertyEditor只提供String<->Object的转换,ConversionService能够提供任意Object<->Object的转换。

所以我们可以猜测,Spring为何要使用ConversionService替代PropertyEditor有三个原因:

1ConversionService功能更强大,支持的类型转换范围更广。

2ConverterFactory支持一整个class hierarchy的转换(也就是多态),PropertyEditor则不行。

3Java Bean这个规范最初是和Java GUI(Swing)一起诞生的,PropertyEditor接口里有大量和GUI相关的方法,显然已经过时了。顺便提一句,Java Bean和POJO不是一个概念,Java Bean不仅有setter、getter,还有一系列和Java GUI配套的东西。

DefaultConversionService支持配置任意的ConverterRegistry

Formatter

Formatter SPI是另外一套和PropertyEditor类似的,String<->Object的转换机制,但是有两个优点:

接口更干净,没有关于GUI的部分,只有print和parse两个方法。

基于注解,支持同一类型的属性根据不同的格式来做String<->Object的转换。比如日期类型,一个字段的格式是yyyy-MM-dd,另一个格式是yyyyMMdd,如果利用PropertyEditor是比较麻烦,但是在这里就可以利用@DateTimeFormat来达到这个效果。

Spring提供了DefaultFormattingConversionService来支持Formatter SPI,也就是说如果要使用Formatter SPI,依然可以利用ConversionService接口.这里采用适配器进行了转换

注意:Formatter SPI必须基于注解才可以使用,这点和ConversionService基于类型不同。

Formatter是PropertyEditor的另一种转换格式的补充

DataBinder

DataBinder主要提供了两个功能:

1利用BeanWrapper,给对象的属性设值

2在设值的同时做Validation

关系图
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容