Spring Boot 参考指南2(1.5.2.RELEASE)

第二部分. 入门

如果你刚刚开始入门Spring Boot,或者说是大体了解“Spring”,本章节正是你的一部分! 在这里我们回答基本的“what?”,“how”和“why?”的问题。 你会发现一个Spring Boot平缓的介绍和安装说明。 然后,我们将构建我们的第一个Spring Boot应用程序,并讨论一些核心原理。

8. Spring Boot介绍

Spring Boot 可以轻松创建基于Spring的独立、生产级应用,你可以只需运行。我们采取一个Spring平台和第三方库的主张,你可以以极少的研究开始。大多Spring Boot 应用需要非常少的Spring配置。
你可以用Spring Boot创建Java应用,并可以使用Java -jar或者更多传统部署war包的方式启动它。我们也提供一个运行“spring脚本”的命令行工具。
我们的主要目标是:

  • 为所有的Spring开发提供一个从根本上更快,更广泛的入门体验。
  • 开箱即用,但随着需求从默认值偏离也可以快速脱离出来。
  • 提供一系列大型项目常用的非功能特性(例如嵌入式服务器,安全性,指标,运行状况检查,外部化配置)
  • 绝对没有代码生成,也不需要XML配置。

9. 系统要求

默认Spring Boot 1.5.2.RELEASE 要求 Java 7 and Spring Framework 4.3.7.RELEASE 或以上版本。你可以进行一些额外的配置使Spring Boot和Java6一起使用。有关详细信息,请参见第84.11节“如何使用Java 6”。 Maven (3.2+), and Gradle 2 (2.9 or later) and 3.提供了明确的构建支持。

| 虽然您可以基于Java6或7使用Spring Boot,但如果有可能的话,我们通常要求Java8。

9.1 Servlet 容器

下列内嵌的Servlet 容器支持开箱即用:

名称 Servlet版本 Java版本
Tomcat 8 3.1 Java 7+
Tomcat 7 3.0 Java 6+
Jetty 9.3 3.1 Java 8+
Jetty 9.2 3.1 Java 7+
Jetty 8 3.0 Java 6+
Undertow 1.3 3.1 Java 7+

您还可以将Spring Boot应用程序部署到任何Servlet 3.0+兼容容器。

10.安装Spring Boot

Spring Boot可以与“经典”Java开发工具一起使用或作为命令行工具安装。 无论如何,您将需要Java SDK v1.6或更高版本。您应该在开始之前检查当前的Java安装:
$ java -version
如果您是Java开发的新手,或者您只想尝试使用Spring Boot,您可能想要首先尝试使用Spring Boot CLI,否则,请继续阅读“经典”安装说明。

|
虽然Spring Boot与Java 1.6兼容,如果可能,您应该考虑使用最新版本的Java。

10.1 给Java开发者的安装说明

您可以使用与任何标准Java库相同的方式使用Spring Boot。 只需在您的类路径中包含适当的spring-boot - * .jar文件。Spring Boot不需要任何特殊的工具集成,所以可以使用任何IDE或文本编辑器;并且Spring Boot应用没有什么特别之处,因此您可以像任何其他Java程序一样运行和调试它。
虽然您可以只是复制Spring Boot jar,但我们通常建议您使用支持依赖管理的构建工具(如Maven或Gradle)。

10.1.1 Maven 安装

Spring Boot与Apache Maven 3.2或以上版本兼容。 如果您还没有安装Maven,可以按照maven.apache.org上的说明进行操作。

| 在许多操作系统上,Maven可以通过一个包进行安装。 如果您是OSX Homebrew用户,请尝试使用brew install maven。 Ubuntu用户可以运行sudo apt-get install maven

Spring Boot依赖使用org.springframework.boot groupId。通常,您的Maven POM文件将从spring-boot-starter-parent项目继承,并声明一个或多个“Starters”的依赖。 Spring Boot还提供了一个可选的Maven插件来创建可执行的jar。
这有一个典型的pom.xml文件:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>myproject</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <!-- 继承自Spring Boot的默认依赖 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
    </parent>

    <!-- 添加Web应用程序的典型依赖项 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <!--  (使用Maven插件)打包为可执行jar-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

| spring-boot-starter-parent 是使用Spring Boot的很好方法,但它可能不是所有的时间都适合。有时您可能需要从不同的父POM继承,或者您可能不喜欢我们的默认设置。 请参见第13.2.2节“使用不带父POM的Spring Boot”作为使用导入作用域(import scope)的替代解决方案。

10.1.2 Gradle 安装

Spring Boot与Gradle 2(2.9或更高版本)和Gradle 3兼容。如果您尚未安装Gradle,您可以按照www.gradle.org/上的说明进行操作。
Spring Boot依赖可以使用org.springframework.boot group 声明。 通常,您的项目将声明一个或多个“启动器”的依赖。 Spring Boot提供了一个有用的Gradle插件,可用于简化依赖关系声明和创建可执行文件。

Gradle Wrapper

当您需要构建项目时,Gradle Wrapper提供了一种“获取”Gradle的好方法。 它是一个小脚本和库,与你的代码一起提交,引导构建过程。

有关详细信息,请参阅docs.gradle.org/2.14.1/userguide/gradle_wrapper.html

这有一个典型的 build.gradle file:

plugins {
    id 'org.springframework.boot' version '1.5.2.RELEASE'
    id 'java'
}


jar {
    baseName = 'myproject'
    version =  '0.0.1-SNAPSHOT'
}

repositories {
    jcenter()
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("org.springframework.boot:spring-boot-starter-test")
}

10.2 安装 Spring Boot CLI

Spring Boot CLI是一个命令行工具,如果想要关于Spring的快速原型,可以使用它。 它允许您运行Groovy脚本,这意味着您具有熟悉的类似Java的语法,但没有太多的样板代码。

您不需要使用CLI来使用Spring Boot,但它绝对是将Spring应用程序从本地开始的最快方法。

10.2.1 手动安装

您可以从Spring软件仓库下载Spring CLI发行版:

10.2.2 使用SDKMAN安装!

SDKMAN! (软件开发套件管理器)可用于管理各种二进制SDK的多个版本,包括Groovy和Spring Boot CLI。 获取SDKMAN! 从sdkman.io并安装Spring Boot:

$ sdk install springboot
$ spring --version
Spring Boot v1.5.2.RELEASE

如果您正在开发CLI的功能,并希望轻松访问刚创建的版本,请遵循以下额外说明。

$ sdk install springboot dev /path/to/spring-boot/spring-boot-cli/target/spring-boot-cli-1.5.2.RELEASE-bin/spring-1.5.2.RELEASE/
$ sdk default springboot dev
$ spring --version
Spring CLI v1.5.2.RELEASE 

这将安装一个称为dev实例的spring的本地实例。它指向您的目标构建位置,所以每次重建Spring Boot时,Spring将更新为最新的。

通过做这个你可以看到它:

$ sdk ls springboot

================================================================================
可用的 Springboot 版本
================================================================================
> + dev
* 1.5.2.RELEASE

================================================================================
+ - local version
* - installed
> - currently in use
================================================================================  
10.2.3 OSX Homebrew 安装

如果您在Mac环境上,并使用Homebrew,则您需要做的所有安装Spring Boot CLI的操作是:

$ brew tap pivotal/tap
$ brew install springboot 

Homebrewspring 安装到/usr/local/bin

| 如果您没有看到公式,您的brew 安装可能已过期。 只需执行brew update,然后重试。

10.2.4 MacPorts 安装

如果您在Mac环境上,并使用MacPorts,那么您需要做的所有安装Spring Boot CLI的操作是:
$ sudo port install spring-boot-cli

10.2.5 命令行实现

Spring Boot CLI 与脚本搭配为BASH和zsh shell 提供命令行实现。您可以在任何shell中引用脚本(也称为spring),或将其放在您的个人或系统范围的bash中完成初始化。在一个Debian系统中,系统范围的脚本位于/ shell-completion / bash中,并且当新的shell启动时,该目录中的所有脚本将被执行。手动运行脚本,例如 如果您使用SDKMAN安装了!

$ . ~/.sdkman/candidates/springboot/current/shell-completion/bash/spring
$ spring <HIT TAB HERE>
  grab  help  jar  run  test  version 

| 如果使用Homebrew或MacPorts安装Spring Boot CLI,则命令行实现脚本与您的shell将自动注册。

10.2.6 Spring CLI 示例快速开始

这是一个非常简单的Web应用程序,可用于测试您的安装。 创建一个名为app.groovy的文件:

@RestController
class ThisWillActuallyRun {

    @RequestMapping("/")
    String home() {
        "Hello World!"
    }

} 

然后简单地从shell运行它:

$ spring run app.groovy  

10.3 从一个早期版本的Spring Boot升级

如果您正在从Spring Boot的一个早期发布的版本升级,请检查托管在项目wiki上的“发行说明”。 您将找到升级说明以及每个版本的“新的和值得注意的”功能的列表。

要升级现有的CLI安装,请使用相应的package manager命令(例如brew upgrade),或者如果您手动安装了CLI,请按照标准说明记住更新PATH环境变量以删除任何旧的引用。

11. 开发您的第一个Spring Boot应用程序

让我们在Java中开发一个简单的“Hello World!”Web应用程序,突出显示一些Spring Boot的主要功能。 我们将使用Maven构建该项目,因为大多数IDE支持它。

| spring.io网站包含许多使用Spring Boot的“入门指南”。 如果您正在期待着解决具体问题; 首先查看那里。
您可以通过转到start.spring.io并从依赖搜索器中选择Web启动器来快速完成以下步骤。 这将自动生成一个新的项目结构,所以您可以立即开始编码。 查看文档了解更多详细信息。

在开始之前,打开终端来检查您是否安装了有效的Java和Maven版本。

$ java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)  

maven

$ mvn -v
Apache Maven 3.2.3 (33f8c3e1027c3ddde99d3cdebad2656a31e8fdf4; 2014-08-11T13:58:10-07:00)
Maven home: /Users/user/tools/apache-maven-3.1.1
Java version: 1.7.0_51, vendor: Oracle Corporation

此示例需要在其自己的文件夹中创建。后续假设您已经创建了一个合适的文件夹,并且它是您的“当前目录”。

11.1 创建 POM

我们需要先创建一个Maven pom.xml文件。 pom.xml是用于构建项目的配置。 打开你最喜欢的文本编辑器并添加以下内容:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>myproject</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
    </parent>

    <!-- Additional lines to be added here... -->

</project>

这应该给你一个工作的构建,你可以通过运行 mvn package 来测试它(你可以忽略“jar将是空的 - 没有内容被标记为包含!”对现在的警告)。

| 此时,您可以将项目导入到IDE中(最现代的Java IDE包括内置的Maven支持)。 为了简单起见,我们将继续为此示例使用纯文本编辑器。

11.2 添加 classpath 依赖

Spring Boot提供了一些“启动器”,可以方便地将jar添加到您的classpath中。我们的示例应用程序已经在POM的 parent 节点中使用了spring-boot-starter-parentspring-boot-starter-parent是一个提供有用的Maven默认值的特殊启动器。 它还提供 dependency-management 节点,以便您可以省略“有福”依赖的 version 标签。
其他“启动器”只是提供当您在开发特定类型的应用时可能需要的依赖。 由于我们正在开发Web应用程序,所以我们将添加一个 spring-boot-starter-web 依赖,但在此之前,让我们来看看我们目前所拥有的。

$ mvn dependency:tree

[INFO] com.example:myproject:jar:0.0.1-SNAPSHOT  

mvn dependency:tree 打印你的项目依赖以树表示出来。 您可以看到 spring-boot-starter-parent 本身不提供依赖关系。 我们来编辑我们的 pom.xml 并添加 spring-boot-starter-web 依赖关系,就在父节之下:

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

如果您再次运行 mvn dependency:tree ,您将看到现在有许多附加依赖,包括Tomcat Web服务器和Spring Boot本身。

11.3 编写代码

要完成我们的应用程序,我们需要创建一个单一的Java文件。 默认情况下,Maven将从 src/main/java 编译源代码,因此您需要创建该文件夹结构,然后添加一个名为 src/main/java/Example.java 的文件:

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

@RestController
@EnableAutoConfiguration
public class Example {

    @RequestMapping("/")
    String home() {
        return "Hello World!";
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Example.class, args);
    }

}

虽然这里没有太多的代码,(但)相当多的事情正在继续。让我们来看看重要的部分。

11.3.1 @RestController 和 @RequestMapping 注解

在我们Example 类上第一个注解是@RestController,这被称为构造型(stereotype)注解。它为人们阅读代码提供了一些提示,并且对于Spring来说,这个类饰演一个特定的角色。 在这种情况下,我们的类是一个web @Controller,所以Spring在处理传入的Web请求时会考虑它。

@RequestMapping注解提供“路由”的信息。它告诉Spring任何来自路径“/”的HTTP请求都应映射到home方法。@RestController 注解告诉Spring将生成的字符串直接返回给调用者。

| @RestController@RequestMapping 是Spring MVC的注解(它们不是Spring Boot特有的)有关更多详细信息,请参阅Spring参考文档中的MVC 章节

11.3.2 @EnableAutoConfiguration annotation

第二个类级别的注解是@EnableAutoConfiguration 这个注解告诉Spring Boot根据您已添加的jar依赖来“猜测”你将如何配置Spring。由于 spring-boot-starter-web 添加了Tomcat和Spring MVC,自动配置将假定您正在开发Web应用程序并相应地设置Spring。

启动器和自动配置

自动配置被设计为与“启动器”很好的配合使用,但两个概念并不直接捆绑。
您可以自由选择启动器之外的jar依赖项,Spring Boot仍然会尽力而为自动配置您的应用程序。

11.3.3 main方法

我们应用程序的最后一部分是 main 方法。这只是一个遵循Java惯例的应用程序入口点的标准方法。我们的main方法通过调用 run. ,(将业务)委托到Spring Boot的 SpringApplication 类。 SpringApplication 将引导我们的应用程序,启动Spring,然后将依次启动自动配置的Tomcat Web服务器。我们需要将 Example.class 作为一个参数传递给 run 方法来告诉 SpringApplication,它是主要的Spring组件。 还传递了 args 数组以暴露任何命令行参数。

11.4 运行示例

在这一点上,我们的应用程序应该工作。 由于我们使用了 spring-boot-starter-parent POM,所以我们有了一个有用的 run 目标,我们可以使用它来启动应用程序。 (也可以)键入 mvn spring-boot:run 从项目根目录运行去启动应用程序:

$ mvn spring-boot:run

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v1.5.2.RELEASE)
....... . . .
....... . . . (log output here)
....... . . .
........ Started Example in 2.222 seconds (JVM running for 6.514)

如果你打开一个web浏览器到localhost:8080你应该看到以下输出:

Hello World!

要正常退出应用程序,请点击ctrl-c。

11.5 创建一个可执行的 jar

让我们通过创建一个完全自包含的可执行的jar文件来完成我们的示例,我们可以(让它)在生产环境中运行。可执行的jar(有时称为“肥胖 jars”)是包含你编译的类以及代码需要运行的所有jar依赖的归档。

可执行的jars和Java

Java不提供任何标准的方法来加载嵌套的jar文件(即 jar 文件自己包含一个jar在内)。 如果您正在寻找分发一个自包含的应用程序,这可能是有问题的。为了解决这个问题,许多开发人员使用“uber”jar。 一个uber jar简单地将所有类,从所有jar包到一个单个档案。 这种方法的问题是,很难看到您在应用程序中实际使用哪些库。 如果在多个jar中使用相同的文件名(但具有不同的内容),也可能会有问题。
Spring Boot采用不同的方法,允许你真正的直接对jar进行嵌套。

要创建一个可执行的jar我们需要将 spring-boot-maven-plugin 添加到我们的 pom.xml 。只是在 dependencies 节点的下方插入以下行:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

| spring-boot-starter-parent POM包含绑定 repackage 目标的 <executions> 配置。如果您不使用父POM,您将需要自己声明此配置。 有关详细信息,请参阅插件文档

保存您的pom.xml并从命令行运行 mvn package 命令:

$ mvn package

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building myproject 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] .... ..
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ myproject ---
[INFO] Building jar: /Users/developer/example/spring-boot-example/target/myproject-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:1.5.2.RELEASE:repackage (default) @ myproject ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

如果你在看 target 文件夹,你将看到 myproject-0.0.1-SNAPSHOT.jar 该文件的大小约为10 MB。 如果你想偷看里面,可以使用 jar tvf

$ jar tvf target/myproject-0.0.1-SNAPSHOT.jar

您还应该在 target 文件夹中看到一个名为 myproject-0.0.1-SNAPSHOT.jar.original 的较小文件。 这是Maven在由Spring Boot重新打包之前创建的原始jar文件。
要运行该应用程序,请使用 java -jar 命令:

$ java -jar target/myproject-0.0.1-SNAPSHOT.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v1.5.2.RELEASE)
....... . . .
....... . . . (log output here)
....... . . .
........ Started Example in 2.536 seconds (JVM running for 2.864)

像以前一样,要正常退出应用程序,点击ctrl-c

12. 接下来要阅读什么

希望本节已为您提供一些Spring Boot基础知识,并让您以自己的方式编写自己的应用程序。 如果你是一个任务导向的开发人员,你可能想跳过spring.io,查看一些解决具体的“如何用Spring”问题的入门指南; 我们还有Spring Boot-specific How-to参考文档。

Spring Boot库还有一大堆可以运行的示例。 示例对于rest和代码(来说)是独立的(这就是您不需要构建rest服务来运行或使用样本)。

否则,下一个逻辑步骤是阅读 第三部分, “使用 Spring Boot”。 如果你真的不耐烦,你也可以向前跳去阅读关于Spring Boot 特性

第一部分和第二部分翻译完毕,继续阅读请移步到这里

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

推荐阅读更多精彩内容