Java 常用工具集

常用工具集

1. Java 工具集

Java Community Process

1.1. Bean 映射

5种常见Bean映射工具的性能比对

1.1.1. ModelMapper

ModelMapper 是一个从对象到对象(object-to-object)的框架,能将 Java Bean(Pojo)对象从一种表现形式转化为另一种表现形式。它采用“通过约定来配置”的方式,自动匹配不同的对象映射,同时具备满足某些特殊需求的高级功能。在项目中很多时候需要把 Model 和 DTO 两个模型类来回转换,保证 Model 对外是隐私的,同时类似密码之类的属性也能很好地避免暴露在外了。那么 ModelMapper 就是为了方便转换而实现的一个类库。

1.1.2. Dozer

Dozer 是 Java Bean 到 Java Bean 映射器,它以递归方式将数据从一个对象复制到另一个对象。通常,这些 Java Bean 将具有不同的复杂类型。

Dozer 支持简单属性映射,复杂类型映射,双向映射,隐式显式映射以及递归映射。这包括映射还需要在元素级别进行映射的集合属性。

Dozer 轻松高效玩转 DTO(Data Transfer Object)

dozermapper gitbook

1.2. ArchUnit

官网中原话介绍是

ArchUnit is a free, simple and extensible library for checking the architecture of your Java code using any plain Java unit test framework.
意思是 ArchUnit 是一款免费、简单可扩展的库,它可以使用任何 Java 单元测试框架来检查 Java 代码的架构。

1.3. Bean Validation

https://beanvalidation.org/

1.4. Jasper Report

https://community.jaspersoft.com

1.5. Juel

Juel 是 Java Unified Expression Language 的简称,即 Java 统一表达语言,在 JSP2.1 标准(JSR-245)中定义的一部分。尽管 EL 表达式是伴随着 JSP 而生,但现在已经可以在非 JSP 应用中使用,相关的 API 放在 javax.el 包里面。引用

1.6. JGIT

如果你想在一个 Java 程序中使用 Git ,有一个功能齐全的 Git 库,那就是 JGit 。 JGit 是一个用 Java 写成的功能相对健全的 Git 的实现,它在 Java 社区中被广泛使用。 JGit 项目由 Eclipse 维护,它的主页在 http://www.eclipse.org/jgit

1.7. Diff Utils

java-diff-utils 库是一个开放源代码库,用于执行文本之间的比较操作:计算差异,应用补丁,生成统一的差异或对其进行解析,生成差异输出以方便将来显示(如并排视图)等等。

1.8. 共识算法:Raft

Raft 一致性协议
参考

1.9. flatbuffers

flatbuffers

FlatBuffer 序列化

1.10. Spring Integration

Spring Integration

实战:Spring Integration 示例

1.11. jsonp: Java HTML Parser

jsonp is a Java library for working with real-world HTML. It provides a very convenient API for fetching URLs and extracting and manipulating data, using the best of HTML5 DOM methods and CSS selectors.

1.12. swagger

swagger

The Best APIs are Built with Swagger Tools

Automated JSON API documentation for API's built with Spring

2. JSON 相关

2.1. JSON-Schema

json-schema 官网

xml中可以有xml schema对xml数据进行定义和校验,同样的,JSON中也有相应的叫做JSON schema的机制,来对JSON数据进行描述和定义,并且提供了相应的机制来检验某个JSON字符串是否符合JSON schema的定义。

JsonSchema和JsonSchemaValidator

2.2. JSONPath

官方文档:http://goessner.net/articles/JsonPath

JsonPath - XPath for JSON 是一种信息抽取类库,是从JSON文档中抽取指定信息的工具,提供多种语言实现版本,包括:Javascript, Python, PHP 和 Java。

JsonPath 对于 JSON 来说,相当于 XPATH 对于 XML。

XPath JSONPath 描述
/ $ 根节点
. @ 现行节点
/ .or[] 取子节点
.. n/a 取父节点,Jsonpath未支持
// .. 就是不管位置,选择所有符合条件的条件
* * 匹配所有元素节点
@ n/a 根据属性访问,Json不支持,因为Json是个Key-value递归结构,不需要。
[] [] 迭代器标示(可以在里边做简单的迭代操作,如数组下标,根据内容选值等)
| [,] 支持迭代器中做多选。
[] ?() 支持过滤操作.
n/a () 支持表达式计算
() n/a 分组,JsonPath不支持

3. Maven 常用插件

${basedir}表示项目根目录,即包含pom.xml文件的目录;

${version}表示项目版本;

${project.basedir}同${basedir};

${project.baseUri}表示项目文件地址;

${maven.build.timestamp}表示项目构件开始时间;

${maven.build.timestamp.format}表示属性${maven.build.timestamp}的展示格式,默认值为yyyyMMdd-HHmm,可自定义其格式,其类型可参考java.text.SimpleDateFormat。

${project.build.directory}表示主源码路径;

${project.build.sourceEncoding}表示主源码的编码格式;

${project.build.sourceDirectory}表示主源码路径;

${project.build.finalName}表示输出文件名称;

${project.version}表示项目版本,与 ${version}相同;

${project.xxx} 当前pom文件的任意节点的内容

${env.xxx} 获取系统环境变量。

${settings.xxx} 指代了settings.xml中对应元素的值。

3.1. Mojo

Mojo 就是 Maven plain Old Java Object。每一个 Mojo 就是 Maven 中的一个执行目标(executable goal),而插件则是对单个或多个相关的 Mojo 做统一分发。一个 Mojo 包含一个简单的 Java 类。插件中多个类似 Mojo 的通用之处可以使用抽象父类来封装。

3.2. maven-compile-plugin

https://maven.apache.org/plugins/maven-compiler-plugin/usage.html

打包时设置编译参数。

这个插件就如同名字所显示的这样,用来编译源代码的。

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

3.3. exec-maven-plugin

我们写一些 java console 相关的程序时,比较头疼的一点就是真正要通过命令行将打包后的程序执行起来还是比较麻烦的。我们需要在命令行里敲如下的命令:java -cp *.jar:.jar:/**/ 。因为要将 classpath 目录以及引用的类库都加入进来,并指定运行的入口,这样子每次用手工的方式来处理实在是太繁琐也比较容易出错。所以一种办法就是利用这个插件,通过一些基本的配置,我们可以执行起代码来的时候很方便

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
            <goal>java</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <mainClass>com.yunzero.App</mainClass>
    </configuration>
</plugin>

3.4. maven-dependency-plugin

https://maven.apache.org/plugins/maven-dependency-plugin/

通过该插件可以对被依赖组件进行复制,解压等一系列操作。

场景一: 在 Maven 多模块化项目中,可以使用 maven-dependency-plugin 将被依赖模块 jar 文件中 class 文件提取出来放在指定位置。


<!-- 将依赖模块的jar包文件提取出来放到指定位置 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>unpack</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>unpack</goal>
            </goals>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>com.xxx</groupId>
                        <artifactId>xxx-xxx</artifactId>
                        <version>1.0.0</version>
                        <type>jar</type>
                        <includes>**/*.class</includes>
                        <overWrite>false</overWrite>
                        <outputDirectory>${project.build.directory}/classes</outputDirectory>
                    </artifactItem>
                </artifactItems>
            </configuration>
        </execution>
    </executions>
</plugin>

场景二:将 scope 为 system 的依赖 jar 包一起打包


<!-- 打包scope为system的jar包 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>3.0.2</version>
        <executions>
            <execution>
                <phase>prepare-package</phase>
                <goals>
                    <goal>copy-dependencies</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <includeScope>system</includeScope>
            <outputDirectory>${project.build.directory}/classes</outputDirectory>
        </configuration>
</plugin>

场景三:将 scope 为 system 的依赖 jar 包中的 class 文件解压出来重新打包


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>unpack</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
</execution>
</executions>
<configuration>
<includeScope>system</includeScope>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</plugin>

<!-- 依赖插件 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.6</version>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>compile</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <!-- ${project.build.directory}为Maven内置变量,缺省为target -->
                <outputDirectory>${project.build.directory}/lib</outputDirectory>
                <!-- 表示是否不包含间接依赖的包 -->
                <excludeTransitive>false</excludeTransitive>
                <!-- 表示复制的jar文件去掉版本信息 -->
                <stripVersion>true</stripVersion>
            </configuration>
        </execution>
    </executions>
</plugin>

3.5. maven-jar-plugin

https://maven.apache.org/plugins/maven-jar-plugin/usage.html

使用该插件可以在打包 jar 文件时做一些事情,比如:定义 MANIFEST.MF 文件,过滤文件等。

<!-- 打包jar文件时,配置manifest文件,加入lib包的jar依赖 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <classesDirectory>target/classes/</classesDirectory>
        <archive>
            <manifest>
                <mainClass>com.alibaba.dubbo.container.Main</mainClass>
                <!-- 打包时 MANIFEST.MF文件不记录的时间戳版本 -->
                <!--自动加载META-INF/spring目录下的所有Spring配置-->
                <useUniqueVersions>false</useUniqueVersions>
                <addClasspath>true</addClasspath>
                <classpathPrefix>lib/</classpathPrefix>
            </manifest>
            <manifestEntries>
                <Class-Path>.</Class-Path>
            </manifestEntries>
        </archive>
        <excludes>
            <exclude>**/profiles/**</exclude>
            <exclude>**/jdbc.properties</exclude>
            <exclude>**/*.proto</exclude>
        </excludes>
    </configuration>
</plugin>

3.6. maven-source-plugin

https://maven.apache.org/plugins/maven-source-plugin/usage.html

打包项目源码。

注意:在多项目构建中,将 source-plugin 置于顶层或 parent 的 pom 中并不会发挥作用,必须置于具体项目的 pom 中。


<!-- 打包源码 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-source-plugin</artifactId>
    <version>3.0.1</version>
    <executions>
        <execution>
            <id>attach-sources</id>
            <goals>
                <goal>jar-no-fork</goal>
            </goals>
        </execution>
    </executions>
</plugin>

3.7. maven-resource-plugin

https://maven.apache.org/plugins/maven-resources-plugin/

maven 默认使用该 maven-resources-plugin 资源文件,不需要明确配置。

说明:该插件处理项目的资源文件拷贝到输出目录。可以分别处理 main resources 和 test resources。


<resources>
    <resource>
        <!-- 指定资源目录 -->
        <directory>src/main/resources</directory>
        <!-- 不打包指定类型的资源 -->
        <excludes>
            <exclude>**/*.svn</exclude>
        </excludes>
    </resource>
    <resource>
        <directory>src/main/resources/profiles/${profile.dir}</directory>
        <includes>
            <include>*.properties</include>
        </includes>
    </resource>
</resources>


<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>3.0.1</version>
    <configuration>
          <encoding>UTF-8</encoding>
     </configuration>
 </plugin>

3.8. maven-assembly-plugin

该插件允许用户整合项目的输出,包括依赖,模块,网站文档和其他文档到一个单独的文档,即可用定制化打包。

创建的文档格式包括:zip, tar, tar.gz(tgz), gar.bz2(tbgz2), jar, dir,war 等等。四种预定义的描述器可用:bin, jar-with-dependencies, src, project.

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>
        <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
    <executions>
        <execution>
        <id>make-assembly</id> <!-- this is used for inheritance merges -->
        <phase>package</phase> <!-- bind to the packaging phase -->
        <goals>
            <goal>single</goal>
        </goals>
        </execution>
    </executions>
</plugin>

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
  <id>bin</id>
  <formats>
    <format>tar.gz</format>
    <format>tar.bz2</format>
    <format>zip</format>
  </formats>
  <fileSets>
    <fileSet>
      <directory>${project.basedir}</directory>
      <outputDirectory>/</outputDirectory>
      <includes>
        <include>README*</include>
        <include>LICENSE*</include>
        <include>NOTICE*</include>
      </includes>
    </fileSet>
    <fileSet>
      <directory>${project.build.directory}</directory>
      <outputDirectory>/</outputDirectory>
      <includes>
        <include>*.jar</include>
      </includes>
    </fileSet>
    <fileSet>
      <directory>${project.build.directory}/site</directory>
      <outputDirectory>docs</outputDirectory>
    </fileSet>
  </fileSets>
</assembly>

3.9. jetty-maven-plugin

http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin

在进行 Web 开发的时候,打开浏览器对应用进行手动的测试几乎是无法避免的,这种测试方法通常就是将项目打包成 war 文件,然后部署到 Web 容器 中,再启动容器进行验证,这显然十分耗时。为了帮助开发者节省时间,jetty-maven-plugin 应运而生,它完全兼容 Maven 项目的目录结构,能够周期性地检查源文件,一旦发现变更后自动更新到内置的 Jetty Web 容器中。做一些基本配置后(例如 Web 应用的 contextPath 和自动扫描变更的时间间隔),你只要执行 mvn jetty:run ,然后在 IDE 中修改代码,代码经 IDE 自动编译后产生变更,再由 jetty-maven-plugin 侦测到后更新至 Jetty 容器,这时你就可以直接 测试 Web 页面了。需要注意的是,jetty-maven-plugin 并不是宿主于 Apache 或 Codehaus 的官方插件,因此使用的时候需要额外 的配置 settings.xml 的 pluginGroups 元素,将 org.mortbay.jetty 这个 pluginGroup 加入。

3.10. versions-maven-plugin

http://mojo.codehaus.org/versions-maven-plugin/

很多 Maven 用户遇到过这样一个问题,当项目包含大量模块的时候,为他们集体更新版本就变成一件烦人的事情,到底有没有自动化工具能帮助完成这件 事情呢?(当然你可以使用 sed 之类的文本操作工具,不过不在本文讨论范围)答案是肯定的,versions-maven- plugin 提供了很多目标帮助你管理 Maven 项目的各种版本信息。例如最常用的,命令 mvn versions:set -DnewVersion=1.1-SNAPSHOT 就能帮助你把所有模块的版本更新到 1.1-SNAPSHOT。该插件还提供了其他一些很有用的目标,display-dependency- updates 能告诉你项目依赖有哪些可用的更新;类似的 display-plugin-updates 能告诉你可用的插件更新;然后 use- latest-versions 能自动帮你将所有依赖升级到最新版本。最后,如果你对所做的更改满意,则可以使用 mvn versions:commit 提交,不满意的话也可以使用 mvn versions:revert 进行撤销。

3.11. maven-shade-plugin

https://maven.apache.org/plugins/maven-shade-plugin/

打包可独立运行的 jar 文件

<!-- 打包可执行jar文件 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.1.0</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.handlers</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.schemas</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <mainClass>org.chench.Main</mainClass>
                    </transformer>
                </transformers>
            </configuration>
        </execution>
    </executions>
</plugin>

3.12. maven-surefire-plugin

https://maven.apache.org/surefire/maven-surefire-plugin/

简单说下 maven-surefire-plugin 是个什么插件,它是一个用于 mvn 生命周期的测试阶段的插件,可以通过一些参数设置方便的在 testNG 或 junit 下对测试阶段进行自定义。然而大家的时候一般都会按我上面的例子去配置,很少用到一些灵活的参数,这样的会不利于我们的测试效率,违背了 maven-surefire-plugin 插件设计的初衷。

<plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.16</version>
           <configuration>
           <suiteXmlFiles>
              <suiteXmlFile>src/test/resources/basic.xml</suiteXmlFile>
           </suiteXmlFiles>
           </configuration>

</plugin>

3.13. Maven 自动部署

https://www.cnblogs.com/EasonJim/p/6854746.html

3.13.1. maven-scm-plugin

http://maven.apache.org/scm/maven-scm-plugin/


 <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-scm-plugin</artifactId>
    <version>1.9.5</version>
    <configuration>
        <connectionType>developerConnection</connectionType>
    </configuration>
</plugin>

3.13.2. maven-release-plugin


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
  <username>jim</username>
  <password>1</password>
  <tagBase>https://127.0.0.1:5443/svn/Test/tags</tagBase>
  <releaseProfiles>release</releaseProfiles>
  </configuration>
</plugin>

3.14. 测试覆盖率

3.14.1. jacoco-maven-plugin

JaCoCo 是 Java 的免费代码覆盖库,由 EclEmma 团队基于多年的使用和整合现有库所获得的经验而创建。JACOCO 官网地址:http://www.jacoco.org/jacoco/, 下载最新版 JACOCO。

//www.greatytc.com/p/464a140b2c67

https://plugins.jenkins.io/jacoco/

https://www.bstester.com/2019/06/jacoco-da-jian-zhi-nan


<dependency>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.5</version>
</dependency>

3.15. 性能测试

3.15.1. JMeter

JMeter 官网

JMeter 使用

JMeter + Maven

jmeter-maven-plugin

4. GitLab

4.1. SonarQube 之 gitlab-plugin

https://blog.csdn.net/aixiaoyang168/article/details/78115646/

5. 监控

5.1. Grafana

grafana 是一款采用 go 语言编写的开源应用,主要用于大规模指标数据的可视化展现,是网络架构和应用分析中最流行的时序数据展示工具,目前已经支持绝大部分常用的时序数据库。

Grafana全面瓦解

5.2. Dropwizard Metrics

Dropwizard Metrics 能够帮助我们从各个角度度量已存在的java应用的成熟框架,简便地以jar包的方式集成进您的系统,可以以http、ganglia、graphite、log4j等方式提供全栈式的监控视野。

Dropwizard Metrics使用

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

推荐阅读更多精彩内容