[前端学java09-SpringBoot实战] 多模块配置 + Mybatis-plus + 单多模块打包部署

导航

[react] Hooks

[封装01-设计模式] 设计原则 和 工厂模式(简单抽象方法) 适配器模式 装饰器模式
[封装02-设计模式] 命令模式 享元模式 组合模式 代理模式

[React 从零实践01-后台] 代码分割
[React 从零实践02-后台] 权限控制
[React 从零实践03-后台] 自定义hooks
[React 从零实践04-后台] docker-compose 部署react+egg+nginx+mysql
[React 从零实践05-后台] Gitlab-CI使用Docker自动化部署

[源码-webpack01-前置知识] AST抽象语法树
[源码-webpack02-前置知识] Tapable
[源码-webpack03] 手写webpack - compiler简单编译流程
[源码] Redux React-Redux01
[源码] axios
[源码] vuex
[源码-vue01] data响应式 和 初始化渲染
[源码-vue02] computed 响应式 - 初始化,访问,更新过程
[源码-vue03] watch 侦听属性 - 初始化和更新
[源码-vue04] Vue.set 和 vm.$set
[源码-vue05] Vue.extend

[源码-vue06] Vue.nextTick 和 vm.$nextTick
[部署01] Nginx
[部署02] Docker 部署vue项目
[部署03] gitlab-CI

[数据结构和算法01] 二分查找和排序

[深入01] 执行上下文
[深入02] 原型链
[深入03] 继承
[深入04] 事件循环
[深入05] 柯里化 偏函数 函数记忆
[深入06] 隐式转换 和 运算符
[深入07] 浏览器缓存机制(http缓存机制)
[深入08] 前端安全
[深入09] 深浅拷贝
[深入10] Debounce Throttle
[深入11] 前端路由
[深入12] 前端模块化
[深入13] 观察者模式 发布订阅模式 双向数据绑定
[深入14] canvas
[深入15] webSocket
[深入16] webpack
[深入17] http 和 https
[深入18] CSS-interview
[深入19] 手写Promise
[深入20] 手写函数
[深入21] 数据结构和算法 - 二分查找和排序
[深入22] js和v8垃圾回收机制
[深入23] JS设计模式 - 代理,策略,单例

[前端学java01-SpringBoot实战] 环境配置和HelloWorld服务
[前端学java02-SpringBoot实战] mybatis + mysql 实现歌曲增删改查
[前端学java03-SpringBoot实战] lombok,日志,部署
[前端学java04-SpringBoot实战] 静态资源 + 拦截器 + 前后端文件上传
[前端学java05-SpringBoot实战] 常用注解 + redis实现统计功能
[前端学java06-SpringBoot实战] 注入 + Swagger2 3.0 + 单元测试JUnit5
[前端学java07-SpringBoot实战] IOC扫描器 + 事务 + Jackson
[前端学java08-SpringBoot实战总结1-7] 阶段性总结
[前端学java09-SpringBoot实战] 多模块配置 + Mybatis-plus + 单多模块打包部署

(一) 前置知识

(1) 一些单词

batch 批 分批

Stalled 停滞
pratices 实践,通常的做法 // best practices 最佳实践
key map 键盘映射

artifact 人工制品
look up 查找 查阅 // lookup parent from repository
property 属性
annotation 注解 // java中的注解
surefire 万全 可靠的
verify 验证 校验

(2) mac版 idea快捷键记录

1. 全局查找
command + shift + r
2. 调出actions
command + 3
3. 设置
command + ,
4. 文件间的跳转
command + e
5. 信息提示
command + 1
6. 跳转到别的类
control + 鼠标左键
7. 复制文件的引用路径
鼠标右键 - copy path - copy reference
8. 左右移动代码块
- 左移动 shift + tab
- 右移动 tab
9. 查找文件
- ctrl + h


1. command + k 查找下一个
2. ctrl + h 查找文件
3. 设置快捷键 ( command + , ) => ( keymap ) => ( 搜索find ) => ( 添加查找快捷键 ) => ( command + f )

(3) pom.xml配置项

  • 项目的打包类型
    • packaging
      • pom jar war
      • 默认打包类型packaging=jar,即默认是打成jar包
  • pom模型版本
    • modelVersion
  • 项目信息
    • 项目唯一标识 groupId ,包括几个字段,比如com.wu7,com是域,wu7是域名
    • 项目名或者模块名 artifactId
    • 项目版本 version
    • 项目名称 name
    • 打包方式(项目的打包类型) packaging pom jar war
    • 一般来说,( 包名根目录 ) = ( groupId ) + ( artifactId ),不允许重复
    • packageName = groupId + artifactId
  • 父级项目 parent
    • 也包括 groupIdartifactIdversionrelativePath
    • relativePath
      • relativePath用来指定查找该父项目 pom.xml 的相对路径
      • 默认:../pom.xml
      • 优先级:relativePath > 本地仓库 > 远程仓库
      • 1.设定一个空值,将始终从仓库中获取,而不从本地路径获取,如 <relativePath/>
      • 2.没有relativePath标签表示从 ../pom.xml 来查找
  • 属性信息 properties
    • java的版本:java.version
    • 编译字符编码 project.build.sourceEncoding
    • 输出字符编码 project.reporting.outputEncoding
    • 打包时跳过test <skipTests>true</skipTests>
  • ================================= 依赖关系 dependencies
  • 编译 build
    • 插件集 plugins
    • 插件 plugin
  • ================================= 模块 modules
    • 在父模块中用来表示包含的 ( 子模块 )

(4) jackson

image.png
  • 之前掘金写的文章

  • jackson fastjson gson

  • 安装

    • 一般在web开发中使用了 spring-boot-starter-web 启动器的话,已经包含了 jackson
    • 如果没有使用上边的starter,则需要自己安装 spring-boot-starter-json 依赖
      <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-json</artifactId>
      </dependency>
      
  • jackson常用注解

    • @JsonFormat
    • @JsonPropertyOrder
    • @JsonProperty
    • @JsonInclude
    • @JsonIgnore
    • @JsonFormat(pattern = "YYYY-MM-dd HH:mm:ss", timezone = "GMT+8") - 格式化时间,用于类的属性
    • @JsonPropertyOrder(value = {"singer", "album"}) - 调整属性的顺序,用于类
    • @JsonProperty("aaa") - 修改返回数据的属性名称,修改为aaa
    • @JsonInclude(JsonInclude.Include.NON_NULL) - 包含则不返回该属性,包含null则不返回该属性
    • @JsonIgnore - 返回的属性不包括该字段
  • @JsonFormat - 格式化时间

    • ( 全局配置 ) 和 ( bean中单独配置@JsonFormat() )
    • 日期格式化配置优先级 ( bean对象中属性 @JsonFormat 注解 > 全局配置)
    • @JsonFormat(pattern = "YYYY-MM-dd HH:mm:ss", timezone = "GMT+8")
1. 全局配置
- 在application.yml中全局配置jackson

spring:
  jackson:
    date-format: YYYY-MM-dd HH:mm:ss # 全局时间格式化
    time-zone: GMT+8 # 时区
2. 局部配置
- 实体中使用 @JsonFormat()

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName("music")
public class MpMusicBean {
    Integer id;
    String name;
    String album;
    String singer;

    @TableField(value = "startTime") // value是数据库字段名
    @JsonFormat(pattern = "YYYY-MM-dd") // jackson格式化时间,优先级 ( bean中设置 > 全局配置 )
    Timestamp startTime;

    @TableField(value = "endTime") // value是数据库字段名
    @JsonFormat(pattern = "YYYY-MM-dd HH:mm:ss") // jackson格式化时间,优先级 ( bean中设置 > 全局配置 )
    Timestamp endTime;
}
  • @JsonPropertyOrder - 调整属性顺序
@JsonPropertyOrder(value = {"singer", "album"}) // jackson调整属性顺序,singer在album前面
public class MpMusicBean {
    Integer id;
    String name;
    String album;
    String singer;
}

结果:
未使用前
    {
            "album": "七里香112233",
            "singer": "周杰伦112233",

    },
使用后
    {
            "singer": "周杰伦112233", //----------------- 1
            "album": "七里香112233",  // ---------------- 2
    },

  • @JsonProperty
    @JsonProperty("start") // jackson修改返回数据的属性名
    @TableField(value = "startTime") // value是数据库字段名
    @JsonFormat(pattern = "YYYY-MM-dd") // jackson格式化时间,优先级 ( bean中设置 > 全局配置 )
    // 这三个注解的最终效果:将数据库中的startTime列的数据key对应实体的startTime,然后将返回值修改成star,并格式化时间
    Timestamp startTime;
  • @JsonInclude
@JsonInclude(JsonInclude.Include.NON_NULL) // jackson,包含null,则不返回该字段
String singer;
  • @JsonIgnore
@JsonIgnore // jackson返回值中不包含该属性,忽略该属性
String name;

(5) SimpleDateFormat,sring,Timestamp,datetime 几个的关系

  • Timestamp
    • ( java中的Timestamp ) 相当于 ( 数据库中的datetime )
    • Timestamp.valueOf(String v) 将string转成Timestamp
  • SimpleDateFormat
    • 主要用来格式化时间
    • new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") 生成实例,然后再调用实例上的方法
    @Test
    void testDate() {
        Date date = new Date(); // 获取时间实例
        SimpleDateFormat dateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss"); // 生成实例
        String format = dateFormat.format(date); // 调用实例实例上的format()方法,返回一个字符串
        log.info("SimpleDateFormat: {}", format);
    }


(二) 多模块配置 module

(2.1) 多模块的优点

  • 每个模块具有 ( 高内聚 ) 性,方便校验,调试,测试

(2.2) 模块的依赖关系

common 一般不依赖任何模块,除非common封装的方法涉及到其他模块
mapper => 依赖 common
service => 依赖 common mapper
controller => 依赖 common service mapper
注意点:
1. 需要删除 ( 父模块的src ) 文件夹,因为父模块不需要写代码
2. controller 模块是需要建 ( srping-boot ) 项目
3. 除了controller模块,其他模块都是建 ( maven ) 项目

(2.3) idea 做相关设置

  • 字符编码设置:ctrl + , => File Encodings => utf-8
  • 注解生效激活:compiler => annotation processors => Enable annotation processing

(2.4) 多模块配置具体过程

(1) 父模块
1.1 首先新建父模块 ----------------------------------- 【 创建的类型为springboot项目 】
1.2 修改父模块的 pom.xml,将 ( packaging ) 类型从jar改为pom,即打包类型为pom
1.3 dependences 交给父模块来打理
1.4 注意区分 ( dependencies ) 和 ( dependencyManagenment )
     - dependencyManagenment => dependencies => dependency
     - dependencyManagenment 只是声明依赖,并不实际导入package,子模块需要显示的引入
1.5 创建好子模块后,父项目的pom.xml中会自动生成 ( modules ) 标签,并显示所有子模块


(2) 子模块
2.1 创建module - mapper service controller ---------- 【 创建类型事maven项目 】


(3) 模块的依赖关系
      common 一般不依赖任何模块,除非common封装的方法涉及到其他模块
      mapper => 依赖 common
      service => 依赖 common mapper
      controller => 依赖 common service mapper
   
   
(4) 具体配置
4.1在子模块中的pom.xml中配置好模块的依赖关系即可
4.2 所有模块的 groupId 都是一样的
4.3 controller
<dependencies>
    <!-- controller 依赖 service -->
    <dependency>
        <groupId>com.woow.wu7</groupId>
        <artifactId>service</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
</dependencies>
image.png

image.png


(三) Mybatis-plus

(1) Mybatis-plus ( Mapper ) 的基本使用

(1.1) 安装idea插件 - MyBatisX

  • command + , 选择 plugins,搜索 MyBatisX 安装
  • 好处就是点击图标能直接跳转mapper和xml配置文件

(1.2) 添加 maven 依赖

  • 注意:Mybatis-plus 包中已经包含了 mybatis 和 jdbc 的start包了,所以不需要再安装这两个包
    • 包含 mybatis-spring-boot-starter
    • 包含 spring-boot-starter-data-jdbc
  • application.yml 文件中通过 mybatis-plus: xxx 对其进行定制配置
    • mapperLocations: 自动配置好了
      • 默认值是:classpath*:/mapper/**/*.xml,表示在 resources/mapper
      • 所以sql映射文件,建议放在 resrouces/mapper 文件中
    • SqlSessionFactory:自动在容器中配置好了,底层是容器中的默认数据源
    • SqlSessionTemplate:自动在容器中配置好了
    • @Mapper 标注也会被自动扫描
      • 建议使用@MapperScan进行指定扫描的包,进行批量扫描,就不用一个个@Mapper了
<!-- mybatis plus包含了 ( mybatis-spring-boot-starter ) 和 ( spring-boot-starter-data-jdbc ) -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
</dependency>

(1.3) 配置 @MapperScan

  • 指定扫描的mapper包,就不用在一个个@Mapper了
  • @MapperScan注解的 ( 参数 ) 是 ( mappe文件夹路径引用 )
@SpringBootApplication
@MapperScan("com.example.demo.mapper") // 指定mapper的目录,将自动扫描,则不用在每个类上都加@Mapper
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

(1.4) 准备一个bean对象即user类 - MybatisPlusUserBean

  • 注意注意注意:( 实体类名 ) 必须和 ( 数据库表名 ) 保持一致,否则需要指定数据库名称
  • 这里实体名叫 MybatisPlusUserBean,那么数据库名就要叫 mybatis_plus_user_bean
  • @TableName 指定数据库表名,默认情况下mp会将实体名首字母小写,用_连接,作为表名
@Data
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Component
@TableName("mybatis_plus_user_bean") 
// @TableName 
// 指定数据库表名,默认情况下mp会将实体名首字母小写,用_连接,作为表名
// @TableName 是mybatis-plus中的注解
public class MybatisPlusUserBean {
    private Long id;
    private String name;
    private Integer age;
    private String email;
    
    @TableField(exist = false) // mybatis-plus的注解,表示该属性在数据库中不存在
    private String other;
}

(1.5) 编写一个mapper - 继承BaseMapper

  • 继承 extends BaseMapper<bean对象> 就具有crud的能力,不用在手写crud了
  • bean对象的命名需要和数据库的表一致
  • 比如实体名叫 MybatisPlusUserBean,那么数据库名就要叫 mybatis_plus_user_bean
  • 可以不用再写 @Mapper,因为配置了 @MapperScan
@Mapper
public interface MybatisPlusUserMapper extends BaseMapper<MybatisPlusUserBean> {
}

(1.6) 准备好数据库和user表

  • 1.注意注意注意:( 实体类名 ) 必须和 ( 数据库表名 ) 保持一致
  • 2.也可以通过 @TableName 指定数据库表名,默认情况下mp会将实体名首字母小写,用_连接,作为表名

(1.7) 测试是否已经配置成功

@SpringBootTest
@Slf4j
public class MybatisPlusUserTest {

    @Autowired
    MybatisPlusUserMapper mybatisPlusUserMapper;

    // mapper相关测试
    // 查询
    @Test
    void getUser() {
        MybatisPlusUserBean user = mybatisPlusUserMapper.selectById(1);
        log.info("用户信息{}", user);
    }

    // mapper相关测试
    // 添加
    @Test
    void addUser() {
        MybatisPlusUserBean user = new MybatisPlusUserBean();
        long a = 11;
        MybatisPlusUserBean user2  = user.builder()
                .name("周杰伦2")
                .age(200)
                .email("woow.wu7@gmail.com")
                .id(a)
                .build();

        int status = mybatisPlusUserMapper.insert(user2);
        log.info("Mybatis-plus插入insert()方法的返回值{}", status);
    }

    // mapper相关测试
    // 删除
    @Test
    void deleteUser() {
        int id = 11;
        int status = mybatisPlusUserMapper.deleteById(id);
    }

    // mapper相关测试
    // 更新
    @Test
    void editUser() {
        MybatisPlusUserBean user = new MybatisPlusUserBean();
        long userId = 11;
        MybatisPlusUserBean user2  = user.builder()
                .name("周杰伦13000")
                .age(3000)
                .email("woow.wu3000@gmail.com")
                .id(userId)
                .build();
        int status = mybatisPlusUserMapper.updateById(user2);
    }
}
  • mybatis-plus 的 mapper 查询 selectById

    image.png

  • mybatis-plus 的 mapper 插入 insert

    image.png

  • mybatisx插件如下


    image.png

(2) Mybatis-plus ( Service ) 的基本使用

(2.1) 以上 1 步,测试了extends BaseMapper,继续测试 extends IService

  • ( mapper ) 是除了继承mybatis-plus的 ( BaseMaper )
  • Interface接口 - ( interface ) 也可以继承mybatis-plus的 ( IService )
  • Implements实现类 - (implements service) 继承 ( ServiceImpl<mapper bean> )

(2.2) 编写一个 Interface Service

MpIService - 是一个interface
-------

public interface MpIService extends IService<MybatisPlusUserBean> {
}

(2.3) 编写一个实现类

MpIServiceImpl - 是一个实现类
------

@Service
public class MpIServiceImpl extends ServiceImpl<MybatisPlusUserMapper, MybatisPlusUserBean> implements MpIService {
}

-------
// extends ServiceImpl<MybatisPlusUserMapper, MybatisPlusUserBean>
  // - MybatisPlusUserMapper 是上面继承了 BaseMapper 的 mapper
// MpIServiceImpl 除了继承 ServiceImpl 外,还需要实现我们自己定义的 MpIService
  // - MpIService 需要继承 IS而ver

(2.4) 测试

@SpringBootTest
@Slf4j
public class MpIServiceTest {

    @Autowired
    MpIService mpIService;

    @Test
    void mpIServiceTest() {
        List<MybatisPlusUserBean> data = mpIService.list();
        log.info("{}", data);
    }
}
image.png

(3) Mybatis-plus 开启日志

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启mybatis-plus日志


(四) springboot 单模块项目打包和部署

(4.1) package 和 install 的区别

  • package 是简单的打包
  • install 除了打包,还会把这个打包好的包安装到maven仓库中
  • 注意:如果 ( 其他项目依赖a项目 ),则应该使用 ( install ) 来进行打包a项目

打包

(4.2.1) 单模块打包过程

  • 如果springboot项目中有jsp页面,就只能打成war包,没有则可以达成jar包
  • 步骤 ( idea方式 )
    • 1.添加 srping boot 的打包插件 spring-boot-maven-plugin
    <!-- maven插件 -->
    <plugins>
      <plugin>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
    
    • 2.在idea中关闭项目,清楚缓存,然后选择 Lifecycle=> clean compile package,package打包说明没有依赖关系,不会打包后不会放在maven仓库中
    • 3.打完包,会生成 target 文件夹,里面就会有 .jar
  • 步骤( 使用命令的方式打包,不用idea来操作 )
1. mvn -Dmaven.test.skip -U clean package
-D 是指定参数的意思
-D maven.test.skip 表示跳过test检查
-U 表示强制去远程更新插件或依赖
clean package 表示清楚target然后再打包
这个命令能执行的前提是需要插件:Spring-boot-maven-plugin

(4.2.2) 多模块打包过程

(1) 将父模块的pom.xml文件中的build标签的所有内容复制到controller模块,因为controller其实已经变成了主模块
(2) 想build标签中添加 configuration => mainClass => application主类的引用路径
(3) 最终的controller模块中的build标签内容如下
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.woow.wu7.Application</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
(4) 然后在利用idea或者mvn命令来打包即可
image.png

(4.3) 如果打包过程报错:提示test没通过,则可以设置忽略测试

  • 有两种方式跳过test进行打包
    • 1.在 pom.xml 中做如下配置
    <properties>
       <skipTests>true</skipTests>
    </properties> 
    
    • 2.添加plugin maven-surefire-plugin
    <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-surefire-plugin</artifactId>
       <!-- 打包时跳过检查 -->
       <!-- surefire 是万全,可靠的意思 -->
       <configuration>
          <skip>true</skip>
       </configuration>
    </plugin>
    

部署jar包

(4.4) 使用命令运行 jar 包

结尾是否有 &
---

(1) java -jar 7-react-admin-java-0.0.1-SNAPSHOT.jar
// ssh通过 ( ctrl+c ) 则可以终止java服务
// 缺点:当退出命令行工具后,java服务将不在运行


(2) java -jar 7-react-admin-java-0.0.1-SNAPSHOT.jar &
// 1. 在尾部加上 ( & ) 表示该命令在后台执行,ssh通过 ( ctrl+c ) 则无法终止java服务
// 2. 只有 ( 关闭命令窗口 ) 才会终止java程序
指定环境
---

(3) java -jar -Dspring.profiles.active=production target/7-react-admin-java-0.0.1-SNAPSHOT.jar
// -Dspring.profiles.active=production 指定环境变量是生产环境
// 则需要在 src/main/resources/application-production.properties 文件来配置生产环境中的配置
// -D 表示指定参数

(4.5) 持久化

  • nohup 和 & 的区别
    • 不加& 当ctrl+c后就会终止java程序执行
    • & 后台运行,但是 ( 关闭了终端或者ssh窗口 ) 就还是会终止java程序执行
    • nohup + & ( 关闭终端或窗口 ) 仍然运行,即持久化操作
nohup java -jar -Dspring.profiles.active=production target/7-react-admin-java-0.0.1-SNAPSHOT.jar >temp.txt &

(4.6) 查看已部署的java项目的后台运行进程

  • ps -ef | grep java > a.txt
    • 检查java程序是否存在,可以看到 PID PPID CMD等信息,即可以根据PID关闭相关进程,比如java
    • ps 将某个进程显示出来
      • -e 显示所有进程
      • -f 全格式
    • grep 表示查找
    • ps -ef | grep java > a.txt 表示将查到的java后台进程结果写进 a.txt 文件中
      image.png

(4.7) 杀掉java进程,终止java程序在后台运行

  • kill 进程号
  • 进程号可以通过 ps -ef | grep java 来查看
  • kill 76619
image.png

部署war包

1. 如果是多模块,并且想用war包的方式进行部署,那么
2. 首先需要将controller模块中的pom.xml中的 ( packaging ) 改成 ( war )
3. 然后需要在 ( src/main ) 中新建 ( webapp/WEB-INF/web.xml ) 文件
4. 然后输入命令打包即可
image.png

资料

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

推荐阅读更多精彩内容