Maven笔记

一、Maven使用

1.1 背景介绍

微服务开发过程中,为了避免为每一个微服务创建一个单独的项目,可以将和项目息息相关的微服务放在一个工程中,通过Maven的多模块来组织管理。假设有这么一个场景,有三个微服务,分别为apiorderprice,介绍如下:

  • api:对外接口服务,这个微服务对外提供查询接口
  • order:订单服务,这个微服务提供了查询所有订单的接口,以供api这个微服务调用
  • price:计价服务,这个微服务提供了查询所有订单价格的接口,以供order这个微服务调用

1.2 Maven多模块

1.2.1 Maven的父模块

我们将上述背景中的三个微服务在一个项目内开发,因此首先我们创建一个Maven工程,其POM文件内容大致如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.istio.app</groupId>
    <artifactId>istio-app</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>istio-app</name>
    <packaging>pom</packaging>
    <description>Istio Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <modules>
        <module>app-api</module>
        <module>app-order</module>
        <module>app-price</module>
    </modules>

    <dependencyManagement>
        <dependencies>
            ...
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            ...
        </plugins>
    </build>

</project>

上述的POM文件即为三个微服务的父POM文件,有几点值得注意的地方:

  • 父POM文件的打包方式为pom,因为父POM文件仅仅为了管理子模块
  • 父POM中通过dependencyManagement来统一管理子模块依赖的版本
  • 父POM中通过modules来声明有哪些子模块

1.2.1 Maven的子模块

api这个微服务为例,它的POM文件如下面这样:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.istio.app</groupId>
        <artifactId>istio-app</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../</relativePath> <!-- lookup parent from repository -->
    </parent>

    <artifactId>app-api</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>app-api</name>
    <description>Demo project for Spring Boot</description>

    <dependencies>
        ...
    </dependencies>

    <build>
        <plugins>
            ...
        </plugins>
    </build>

</project>

这个子模块的POM文件中同样也有几点值得注意的:

  • 通过parent来指明父模块,其中relativePath通过相对路径指向父POM文件所在位置
  • 通过dependencies来引入子模块具体的依赖

1.3 Maven的标签

Maven的POM文件中有很多标签,下面列举下那些经常用但很容易混淆的标签

  • dependencyManagement和dependencies:dependencyManagement只是对依赖的声明,并不会真的引入依赖,目的是为了方便统一各个子模块中相同依赖的版本号;而dependencies才会引入具体的依赖,而且如果待引入的依赖已经在父模块中通过dependencyManagement声明,那么在子模块中只需要这样即可,即不需要指定版本号
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
  • pluginManagement和plugins:区别即联系同上述dependencyManagement和dependencies
  • dependency下的scope标签:scope标签的取值范围包括compile、provided、runtime、system、test、import,默认的值为compile,什么时候需要显示的指定scope标签值?在了解了Maven的生命周期后可以自行了解。
  • dependency下的type标签:type标签的取值范围常见的包括jar、war、apk、pom等,默认的值为jar,什么时候需要显示的指定type标签值?在了解了Maven的插件后可以自行了解。

二、Maven原理

2.1 Maven的生命周期

Maven通过其生命周期来帮助我们管理项目,我们经常执行的mvn clean package命令,其实就是在调用maven的生命周期来帮助我们完成清理、打包等工作。Maven的声明周期包括三个:

  • clean:完成清理工作,主要用于清理target目录
  • default:完成编译、打包、发布等工作
  • site:完成文档、项目站点等工作,笔者还没用过

每个生命周期又包含多个阶段,就好比一个接口(Interface)会包含多个方法(Method),每个生命周期包含的主要阶段列举如下:

  • clean:
    • clean:clean阶段是这个生命周期内的主要阶段,我们通常执行的命令mvn clean其实就是在执行这个阶段
  • default:
    • process-sources:处理源代码
    • compile:编译源代码
    • process-test-resources:处理测试代码
    • test-compile:编译测试代码
    • test:运行测试用例
    • package:项目打包
    • install:项目包安装到本地仓库
    • deploy:项目包发布到远程仓库

关于maven的生命周期必须要明确的两点:

  • 同一个生命周期内的阶段是从前往后顺序执行的,而且直接执行后面的阶段时,这个阶段前的阶段会全部按顺序执行,这也是为什么我们直接执行mvn package也能完成代码处理、编译、运行测试用例等功能的原因。因为compile、test这些阶段都在package阶段前。
  • 不同生命周期之间是相互隔离的,即clean生命周期和default生命周期是完全无关的,这也是为什么我们通常需要执行mvn clean package的原因,因为clean阶段是属于clean生命周期的,如果要实现清理并打包,而这两个阶段是属于不同生命周期。

2.2 Maven的插件

基本上,我们了解了maven的生命周期后在日常开发中就可以正常使用maven来管理项目了。如果想要深究maven生命周期背后的原理,那就必须要了解maven的插件了。

我们在项目开发过程中肯定见过如下的POM文件内容:

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
</build>

想要理解上面的POM文件内容,也必须要了解maven的插件。

2.2.1 从Maven生命周期了解插件

我们再次回到mvn clean这个命令,现在我们已经知道这个命令其实就是调用maven的clean生命周期内的clean阶段,我们看一下这个命令的输出:

E:\project\spring\mavenbase>mvn clean
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven-base 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-base ---
[INFO] Deleting E:\my-project\spring\mavenbase\target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.203 s
[INFO] Finished at: 2021-05-28T11:42:16+08:00
[INFO] Final Memory: 7M/245M
[INFO] ------------------------------------------------------------------------

注意这行输出maven-clean-plugin:2.5:clean,这行表达了三个重要信息:插件名称是maven-clean-plugin,插件版本号是2.5,插件的目标是clean。这里引入了一个新的名词插件的目标,插件与插件目标的关系,其实就相当于生命周期与阶段的关系,插件是一个统一的接口(Interface),而插件目标是接口中的方法(Method)。
这行输出说明mvn clean命令背后真正干活的是maven-clean-plugin这个插件的clean这个目标,通俗的可以理解为mvn clean调用的是maven-clean-plugin这个接口的clean方法。

像上面这种阶段与目标的调用关系,我们可以称为绑定,不同阶段所绑定的插件目标如下:

阶段 插件:目标
clean maven-clean-plugin:clean
process-resources maven-resources-plugin:resources
compile maven-compiler-plugin:compile
process-test-resources maven-resources-plugin:testResources
test-compile maven-compiler-plugin:testCompile
test maven-surefile-plugin:test
package maven-jar-plugin:jar
install maven-install-plugin:install
deploy maven-deploy-plugin:deploy

还有一个命令mvn help,我们通常用来查询帮助信息,其本质也是绑定到了一个插件目标上,对应的是maven-help-plugin:help

2.2.2 使用Maven插件

我们通过maven-help-plugin来详细了解一下maven官方实现的插件

mvn <groupId>:<artifactId>:<goal>

  • 查看maven-help-plugin的用法
# 命令中使用的是这个插件的全称,其中包括groupId和artifactId
E:\project\spring\mavenbase>mvn org.apache.maven.plugins:maven-help-plugin:help
...
[INFO] --- maven-help-plugin:3.2.0:help (default-cli) @ maven-base 
...
# 这个插件有8个目标,仅列出部分
This plugin has 8 goals:

help:describe
  Displays a list of the attributes for a Maven Plugin and/or goals (aka Mojo -
  Maven plain Old Java Object).

help:effective-pom
  Displays the effective POM as an XML for this build, with the active profiles
  factored in, or a specified artifact. If verbose, a comment is added to each
  XML element describing the origin of the line.

help:help
  Display help information on maven-help-plugin.
  Call mvn help:help -Ddetail=true -Dgoal=<goal-name> to display parameter
  details.
  • 获取maven-help-plugin插件名称的简称
# 使用上面的describe目标查看这个插件的详情
E:\project\spring\mavenbase>mvn org.apache.maven.plugins:maven-help-plugin:describe -Dplugin=org.apache.maven.plugins:maven-help-plugin
...
[INFO] org.apache.maven.plugins:maven-help-plugin:3.2.0

Name: Apache Maven Help Plugin
...
Group Id: org.apache.maven.plugins
Artifact Id: maven-help-plugin
Version: 3.2.0
# 可以看出`maven-help-plugin`的简称是help,
Goal Prefix: help
  • 查看maven-clean-plugin插件(简称:clean)的目标
# 命令中使用的是插件的简称
E:\my-project\spring\mavenbase>mvn help:describe -Dplugin=clean
...
Name: Maven Clean Plugin
...
Group Id: org.apache.maven.plugins
Artifact Id: maven-clean-plugin
Version: 2.5
# 这个插件的简称确实是clean
Goal Prefix: clean
# 这个插件有两个目标
This plugin has 2 goals:

clean:clean
  Description: Goal which cleans the build.
    This attempts to clean a project's working directory of the files that were
    generated at build-time. By default, it discovers and deletes the
    directories configured in project.build.directory,
    project.build.outputDirectory, project.build.testOutputDirectory, and
    project.reporting.outputDirectory.

    Files outside the default may also be included in the deletion by
    configuring the filesets tag.

clean:help
  Description: Display help information on maven-clean-plugin.
    Call
     mvn clean:help -Ddetail=true -Dgoal=<goal-name>
    to display parameter details.

  • 查看maven-clean-plugin插件的clean目标详情
E:\project\spring\mavenbase>mvn help:describe -Dplugin=clean -Dgoal=clean -Ddetail
...
[INFO] Mojo: 'clean:clean'
clean:clean
  Description: ...
  # 这个目标开放了这些参数可设置,这也是我们在POM文件里通过<configuration>可以指定的参数来源
  Available parameters:

    excludeDefaultDirectories (Default: false)
      User property: clean.excludeDefaultDirectories
      ...

    failOnError (Default: true)
      User property: maven.clean.failOnError
      ...

    filesets
      The list of file sets to delete, in addition to the default directories.
      ...

    followSymLinks (Default: false)
      User property: clean.followSymLinks
      ...

    retryOnError (Default: true)
      User property: maven.clean.retryOnError
      ...

    skip (Default: false)
      User property: clean.skip
      ...

    verbose
      User property: clean.verbose
      ...

上面的目标详情里有两点值得注意:

  • 目标开放的参数即是POM文件里可以通过<configuration>指定的参数
  • 有些目标参数的说明里有User property,这个对应的即是POM文件里我们可以直接通过<properties>来指定的参数

看到这里后,读者应该明白了mvn clean package -DskipTests命令里的参数为什么能生效了。(可以自行验证猜想)

2.3 验证插件目标与生命周期阶段的绑定关系

前面我们直接给出了maven中的一些常见生命周期阶段与插件目标的绑定关系,下面我们通过查看父POM来验证下。(每个POM文件都会显示或隐式的继承自一个父POM,如果我们没有在项目POM文件中显示的声明<parent>标签,那么当前项目就隐式的继承自一个POM),我们看一下父POM的内容:

E:\project\spring\mavenbase>mvn help:effective-pom
...
[INFO] --- maven-help-plugin:3.2.0:effective-pom (default-cli) @ maven-base ---
[INFO]
Effective POMs, after inheritance, interpolation, and profiles are applied:

<?xml version="1.0" encoding="UTF-8"?>
<!-- ====================================================================== -->
<!--                                                                        -->
<!-- Generated by Maven Help Plugin on 2021-05-28T16:06:20+08:00            -->
<!-- See: http://maven.apache.org/plugins/maven-help-plugin/                -->
<!--                                                                        -->
<!-- ====================================================================== -->
<!-- ====================================================================== -->
<!--                                                                        -->
<!-- Effective POM for project 'com.gjj.maven:maven-base:jar:1.0-SNAPSHOT'  -->
<!--                                                                        -->
<!-- ====================================================================== -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.ap
ache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.gjj.maven</groupId>
  <artifactId>maven-base</artifactId>
  <version>1.0-SNAPSHOT</version>
  # 很多项目都会指定这个,经过今天的学习后,你应该能够知道这个为什么能够直接生效?
  # 提示:读者可以去看一下maven-resources-plugin这个插件的目标及参数详情
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  # maven默认从这里去拉取依赖
  <repositories>
    <repository>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
    </repository>
  </repositories>
  # maven默认从这里去拉取插件
  <pluginRepositories>
    <pluginRepository>
      <releases>
        <updatePolicy>never</updatePolicy>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
    </pluginRepository>
  </pluginRepositories>
  <build>
    # maven默认的源代码、测试代码、编译代码的路径
    <sourceDirectory>E:\my-project\spring\mavenbase\src\main\java</sourceDirectory>
    <scriptSourceDirectory>E:\my-project\spring\mavenbase\src\main\scripts</scriptSourceDirectory>
    <testSourceDirectory>E:\my-project\spring\mavenbase\src\test\java</testSourceDirectory>
    <outputDirectory>E:\my-project\spring\mavenbase\target\classes</outputDirectory>
    <testOutputDirectory>E:\my-project\spring\mavenbase\target\test-classes</testOutputDirectory>
    <resources>
      <resource>
        <directory>E:\my-project\spring\mavenbase\src\main\resources</directory>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>E:\my-project\spring\mavenbase\src\test\resources</directory>
      </testResource>
    </testResources>
    <directory>E:\my-project\spring\mavenbase\target</directory>
    <finalName>maven-base-1.0-SNAPSHOT</finalName>
    <pluginManagement>
      <plugins>
        <plugin>
          <artifactId>maven-antrun-plugin</artifactId>
          <version>1.3</version>
        </plugin>
        <plugin>
          <artifactId>maven-assembly-plugin</artifactId>
          <version>2.2-beta-5</version>
        </plugin>
        <plugin>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>2.8</version>
        </plugin>
        <plugin>
          <artifactId>maven-release-plugin</artifactId>
          <version>2.3.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
   # 以下即是插件目标与生命周期阶段的默认绑定关系
    <plugins>
      <plugin>
        <artifactId>maven-clean-plugin</artifactId>
        <version>2.5</version>
        <executions>
          <execution>
            <id>default-clean</id>
            # maven-clean-plugin插件的goal=clean目标绑定到clean阶段
            <phase>clean</phase>
            <goals>
              <goal>clean</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.6</version>
        <executions>
          <execution>
            <id>default-testResources</id>
            # maven-resources-plugin插件的goal=testResources目标绑定到process-test-resources阶段
            <phase>process-test-resources</phase>
            <goals>
              <goal>testResources</goal>
            </goals>
          </execution>
          <execution>
            <id>default-resources</id>
            # maven-resources-plugin插件的goal=resources目标绑定到process-resources阶段
            <phase>process-resources</phase>
            <goals>
              <goal>resources</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.4</version>
        <executions>
          <execution>
            <id>default-jar</id>
            # maven-jar-plugin插件的goal=jar目标绑定到package阶段
            <phase>package</phase>
            <goals>
              <goal>jar</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <executions>
          <execution>
            <id>default-compile</id>
            # maven-compiler-plugin插件的goal=compile目标绑定到compile阶段
            <phase>compile</phase>
            <goals>
              <goal>compile</goal>
            </goals>
          </execution>
          <execution>
            <id>default-testCompile</id>
            # maven-compiler-plugin插件的goal=testCompile目标绑定到test-compile阶段
            <phase>test-compile</phase>
            <goals>
              <goal>testCompile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.12.4</version>
        <executions>
          <execution>
            <id>default-test</id>
            <phase>test</phase>
            <goals>
              <goal>test</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-install-plugin</artifactId>
        <version>2.4</version>
        <executions>
          <execution>
            <id>default-install</id>
            <phase>install</phase>
            <goals>
              <goal>install</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-deploy-plugin</artifactId>
        <version>2.7</version>
        <executions>
          <execution>
            <id>default-deploy</id>
            <phase>deploy</phase>
            <goals>
              <goal>deploy</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-site-plugin</artifactId>
        <version>3.3</version>
        <executions>
          <execution>
            <id>default-site</id>
            <phase>site</phase>
            <goals>
              <goal>site</goal>
            </goals>
            <configuration>
              <outputDirectory>E:\my-project\spring\mavenbase\target\site</outputDirectory>
              <reportPlugins>
                <reportPlugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-project-info-reports-plugin</artifactId>
                </reportPlugin>
              </reportPlugins>
            </configuration>
          </execution>
          <execution>
            <id>default-deploy</id>
            <phase>site-deploy</phase>
            <goals>
              <goal>deploy</goal>
            </goals>
            <configuration>
              <outputDirectory>E:\my-project\spring\mavenbase\target\site</outputDirectory>
              <reportPlugins>
                <reportPlugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-project-info-reports-plugin</artifactId>
                </reportPlugin>
              </reportPlugins>
            </configuration>
          </execution>
        </executions>
        <configuration>
          <outputDirectory>E:\my-project\spring\mavenbase\target\site</outputDirectory>
          <reportPlugins>
            <reportPlugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-project-info-reports-plugin</artifactId>
            </reportPlugin>
          </reportPlugins>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <reporting>
   <outputDirectory>E:\project\spring\mavenbase\target\site</outputDirectory>
  </reporting>
</project>

3. 前文遗留的两个问题

  • 什么时候需要指定依赖的scope标签?
    • 什么时候需要将依赖指定为scope=provided:这个依赖我们在编译及测试过程中需要使用该依赖,但是在运行时会有其它服务器提供该依赖。如web应用中依赖servlet-api.jar,但是在运行时我们不需要该 jar包,因为这个jar 包已由web服务器提供,如果在打包时又被加入进去,那么就可能产生冲突。常见的如:servlet-api.jar、jsp-api.jar
    • 什么时候需要将依赖指定为scope=runtime:这个依赖仅在测试及运行时需要使用,但是在编译时没有也能通过编译。如mysql-connector-java.jar,编码期间不会使用该依赖,但是运行时需要使用该依赖操作数据库。
    • 什么时候需要将依赖指定为scope=test:这个依赖仅被测试代码依赖,项目源代码的编译、运行均不需要该依赖。打包时这些依赖也会被忽略。
  • 什么时候需要显示的指定type标签值?
    • 什么时候需要指定type=pom:当所需要的依赖的打包方式为pom包时。
    • 什么时候需要指定type=war:当所需要的依赖的打包方式为war包时。

4. 参考

关于插件原理讲的很清楚:http://www.itsoku.com/article/240#menu_14
关于scope标签内容:https://blog.csdn.net/u010979642/article/details/107554068/

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

推荐阅读更多精彩内容

  • 一、Maven基础 1.1 Maven功能 Maven能帮助我们干什么?它主要有两个功能: 依赖管理(jar包管理...
    斯文遮阳阅读 588评论 0 1
  • 一、生命周期 maven有三套生命周期:分别为clean、compile、site。三个生命周期不会互相关联,而每...
    yjaal阅读 540评论 0 0
  • 概念 lifecycle 生命周期 phases 阶段。生命周期由多个阶段组成 goals 目标。每个阶段都可以有...
    donglq阅读 261评论 0 0
  • 表情是什么,我认为表情就是表现出来的情绪。表情可以传达很多信息。高兴了当然就笑了,难过就哭了。两者是相互影响密不可...
    Persistenc_6aea阅读 123,978评论 2 7
  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 6,030评论 0 4