为了账号安全,请及时绑定邮箱和手机立即绑定
4. 为什么使用 Maven?

说到这个问题,我们首先要看一下,如果没有 Maven,那么我们的工作是什么样子的呢?场景一当我们在开发过程中,当我们开发某个新功能或者修复了某个 Bug,都需要手动进行整个项目编译,运行单元测试,生成项目文档,打包,部署环境这些步骤。一旦需要重新修改代码的时候,便要将上述的操作重复一遍。机械性的重复劳动充斥着整个开发过程;场景二由于不同的人可能会有不同的习惯或者说是个人偏好,每当我们新建一个项目的时候,所建出来的项目可能会千奇百怪,这也给后续的维护升级带来了诸多的不便;场景三当项目需要依赖某个 jar 包的时候,需要到互联网上去寻找对应的 jar 包,找到 jar 包之后,将这个 jar 包添加到项目的 lib 目录下,项目组里面不同的人可能会找到不同的 jar 包,不同的 jar 包直接可能会存在冲突,这个时候,就需要去手动解决冲突;看到这里,只想说一句,我太难了。但是,不要慌,Maven 的存在,就是为了帮助解决这些问题。使用 Maven 之后,只需要执行一个命令就可以完成编译,运行单元测试,打包,部署的整个流程;并且 Maven 以 POM 的形式来管理 jar 包依赖;还有一点就是,使用 Maven 构建出的项目,结构统一,方便后续的维护升级。

2. 什么是背包问题?

假设我们一共有 n 种物品,每种物品 i 的价值为 vi,重量为 wi,我们有一个背包,背包的容量为 c(最多可以放的物品重量不能超过 c),我们需要选择物品放入背包中,使得背包中选择的物品中总价值最大,在这里每个物品可以只选择部分。这便是我们常说的背包问题背包问题是一种常见的可以用贪心算法进行求解的问题,接下来,就让我们看看如何利用贪心算法解决背包问题。

集成前的问题

因为本套课程使用 Maven 包管理工具构建,所以在集成之前需要我们先将 Swagger Editor 的依赖引入到项目中去,但是很不幸,Swagger Editor 官方并没有提供对 Maven 的支持,所以我们就不能通过 Maven 的方式将 Swagger Editor 集成进来。难道就没有办法将 Swagger Editor 与 SpringBoot 结合使用了吗 ?俗话说,方法总比困难多,所以这里我们另辟蹊径,通过使用配置 yml 文件的方式将 Swagger Editor 集成进来,话不多说,我们直入正题。

1.3 Maven 的坐标

接下来我们就重点介绍一下 Maven 的坐标(Coordinates)。groupId:groupId 为我们组织的逆向域名,这里的组织可以是公司,团体,小组等等。例如Apache 基金会的项目都是以 org.apache 来作为 groupId 的;artifactId:该组织下,项目的唯一标识;packaging:项目类型,描述的是项目在打包之后的输出结果,常见的 jar 类型的输出结果是一个jar 包,war 类型则输入 war 包,一般 Web 项目的打包方式为 war。version:项目的版本号,用来标记本项目的某一特定版本。SNAPSHOT 则是用来标记项目过程中的快照版本,该版本类型表明本项目不是稳定版本,常见的还有 RELEASE,则表示该版本为本项目的稳定版本。

2.2 Spring Boot 打包为 jar 并运行

Spring Boot 应用可以打包为 war 或者 jar ,官方和我个人都是推荐打 jar 包。可以直接运行,无需部署到 Web 服务器上。打开命令行工具,进入 spring-boot-cors 项目目录后运行 mvn clean package -Dmaven.test.skip=true 命令,即可快速打包 Spring Boot 应用。下图中的 jar 文件,即为打包后的 Spring Boot 应用。打包后生成的文件内容接下来我们将该应用拷贝至服务器,在同一目录下新建 start.bat 文件,内容如下:java -jar spring-boot-cors-0.0.1-SNAPSHOT.jar双击 start.bat 文件即可启动项目,效果如下,可以看出系统已经启动成功(started)。Spring Boot 打包项目已启动

3. 贪心算法求解背包问题

首先,这里我们考虑背包的容量为 30,并给出这个问题中我们考虑到的各类物品及对应的重量和价值,如下:物品 n (i)12345 重量 w (i)105151020 价值 v (i)2030152510回顾一下我们在贪心算法介绍中提到的,能够应用贪心算法求解的问题需要满足两个条件:最优子结构和贪心选择,接下来,我们就具体来看看在背包问题中的最优子结构和贪心选择分别是什么。首先,如果一个问题的最优解包含其子问题的最优解,则此问题具备最优子结构的性质。问题的最优子结构性质是该问题是否可以用贪心算法求解的关键所在。对于背包问题,很显然它是满足最优子结构性质的,因为一个容量为 c 的背包问题必然包含容量小于 c 的背包问题的最优解的。其次,我们需要考虑在背包问题中,我们应该按照什么样的贪心选择进行选取。很显然,如果要使得最终的价值最大,那么必定需要使得选择的单位重量的物品的价值最大。所以背包问题的贪心选择策略是:优先选择单位重量价值最大的物品,当这个物品选择完之后,继续选择其他价值最大的物品。这里的背包问题可以用贪心算法实现,是因为背包选择放入的物品可以进行拆分,即并不需要放入整个物品,可以选择放入部分物品,我们这样的背包选择问题为部分背包问题(可以只选择物品的部分),与之对应的另一种背包问题为 0-1 背包问题,这个时候整个物品不可以拆分,只可以选择放入或者不放入,0-1 背包问题用贪心算法并不能求得准确的解,需要用动态规划算法求解。背包问题求解详解:在这里,我们按照优先选择单位重量价值最大的物品,所以第一步需要计算单位每个物品的单位价值,如下:unitValue(1) = 20/10 = 2unitValue(2) = 30/5 = 6unitValue(3) = 15/15 = 1unitValue(4) = 25/10 = 2.5unitValue(5) = 10/20 = 0.5所以我们有:unitValue(2) > unitValue(4) > unitValue(1) > unitValue(3) > unitValue(5)当考虑背包的容量为 30 时, 我们发现可以按照物品的单位价值进行依次放入,直至背包容量放满或者物品放完为止,放入的过程如下:物品类型放入重量背包使用容量背包剩余容量 25525410151511025535300按照如上步骤我们简单分析了一下背包问题的求解过程,接下来,我们看一下如何用代码实现背包问题。

3.1 模拟拆包粘包问题

开始,之前我们先看一个简单的案例,具体如下所示:客户端: 客户端使用 for 循环,连续向服务端发送 hello world1000 遍(使用 StringEncoder 编码器)。public class ClientTestHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { for(int i=0;i<1000;i++){ ctx.channel().writeAndFlush( Unpooled.copiedBuffer("hello world 世界你好,Netty技术学习".getBytes()) ); } }}服务端: 正常输出客户端的信息(使用 StringDecoder 解码器)。public class ServerTestHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String str=msg.toString(); System.out.println(str); }}输出结果:总结:通过以上的输出结果,我们发现,客户端发送过来的数据,有时候能正确打印,有时候数据粘在了一起。以上输出结果有乱码想象、有多个信息输出到一行,就是 ByteBuf 粘包和 ByteBuf 半包。通过上面的简单案例,我们发现 TCP 协议下会产生数据安全性问题,其实在 TCP 中粘包和拆包是不可避免的,因为在 TCP 协议中,数据流向水流一样,根本不知道应该从哪里截取才是完整的数据包。TCP 并不了解上层业务的数据含义,它会根据 TCP 缓冲区的实际情况进行包的划分,因此一个完整的业务包可能会被 TCP 拆分成多个包进行发送,也可能会把多个小包封装成一个大包进行发送,这就是 TCP 粘包和拆包问题。

1. 什么是 Maven 仓库

我们先想象一下,如果没有 Maven,我们在开发不同项目的时候,如果需要依赖同一个 jar 包,那么就需要分别在两个不同项目中将这个 jar 包引入进去,对于一个程序员来说,这样的做法显然是不合理的,不仅需要我们手动到处复制,而且会多占用我们的磁盘空间。那这个时候,Maven 仓库就出现了。我们通常把依赖称为构件,每一个构件都有自己唯一的坐标,基于这种模式,我们就可以把这些构件存放在一个指定的位置–Maven仓库当中,然后通过其坐标来寻找该构件。在我们学习或者实际开发过程中,只需要在我们的项目当中声明依赖的坐标,在项目编译的或者打包的过程中,Maven 会自动从仓库中去寻找该构件,这样就不需要我们在本地存储这个依赖了。

2.7 exlude 排除依赖包中的部分类

我们开发中,可能大家或多或少都会遇到 jar 包冲突的问题,有时候两个 jar 包不同,但是里面有两个类的包名路径是一摸一样的。这样我们就需要排除掉某个包中的重复的类,这时候就需要用的 exclude 命令,如下我们就以排除这个hibernate包中的类为例子。compile('org.hibernate:hibernate:3.1') { //以artifact name来排除出 exclude module: 'cglib' //通过group name来排除 exclude group: 'org.jmock'}

2.1 超级 POM 路径位置

如下图,先找到指定的 jar 包,路径:.\apache-maven-3.6.3\lib\maven-model-builder-3.6.3.jar:然后我们可以使用解压工具查看该 jar 包,找到对应的 pom.xml。具体路径:org\apache\maven\model\pom-4.0.0.xml。

2.2 引入驱动

去 maven 中央仓库找到 mysql-connector-java 驱动。如果你熟悉 Maven,可直接引入 maven 依赖:<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version></dependency>如果你还不熟悉 Maven,请跟着我来做如下步骤:到 maven 中央仓库下载 jar 包,鼠标左键单击 jar:在工程目录下新建一个 lib 包,并将刚刚下载好的 jar 包复制到其中:在 jar 包上点击右键,选择 Add as Library:如果有弹窗,单击确定即可。此时就可以在你的项目中引入驱动里的类了。

2.2 Maven 的缺点

Maven 的整个体系相对庞大,想要完全掌握相对困难;如果项目的依赖过多,在第一次导入项目的时候需要花很长的时间来加载所需要的依赖;由于某种不可抗拒力,国内的开发者在使用 Maven 中央仓库的时候,下载速度过慢。但是,这些问题都是有可以有解决办法的,我们后续会慢慢一一介绍。

Maven 简介

大家好,今天我们这个专题的主角是 — Maven。Maven 作为我们开发当中比较常见的项目管理工具,用来帮助我们构建项目,管理依赖。Maven 目前是 Apache 基金会托管的顶级项目之一,诞生自 2003 年,现在已经 17 岁了。本文当中,我们将介绍 Maven 是什么,Maven 的优缺点有哪些,为什么我们要使用 Maven。

3.1 适用问题

首先,在利用动态规划算法之前,我们需要清楚哪些问题适合用动态规划算法求解。一般而言,能够利用动态规划算法求解的问题都会具备以下两点性质:最优子结构: 利用动态规划算法求解问题的第一步就是需要刻画问题最优解的结构,并且如果一个问题的最优解包含其子问题的最优解,则此问题具备最优子结构的性质。因此,判断某个问题是否适合用动态规划算法,需要判断该问题是否具有最优子结构。Tips: 最优子结构的定义主要是在于当前问题的最优解可以从子问题的最优解得出,当子问题满足最优解之后,才可以通过子问题的最优解获得原问题的最优解。重叠子问题: 适合用动态规划算法去求解的最优化问题应该具备的第二个性质是问题的子问题空间必须足够” 小 “,也就是说原问题递归求解时会重复相同的子问题,而不是一直生成新的子问题。如果原问题的递归算法反复求解相同的子问题,我们就称该最优化问题具有重叠子问题。Tips: 在这里,我们需要注意是,与适用动态规划算法去求解的问题具备重叠子问题性质相反,前面我们介绍的分治算法递归解决问题时,问题的子问题都是互不影响,相互独立的,这个也是我们在选用动态规划算法还是分治法解决问题时的一个判断条件。

2.1 第一步:获取 Swagger Codegen Jar 包

我们进入 Swagger Codegen 的开源界面,会得到官网所推荐的下载 jar 包的链接,链接比较长,这里我已经下好了,同学们可以直接从我的 Git 上进行下载:https://github.com/SteafanMrZhou/MoocSwaggerWiki

2.2 带来的问题

因为应用程序可能依赖特定版本的包,当系统中存在多个项目时,可能会出现冲突。例如:有两个项目:项目 A 和 项目 B;项目 A 依赖于 redis-3.5.3;项目 B 依赖于 redis-3.0.0。如果,需要同时进行两个项目的开发,则必须:开发项目 A 时,卸载系统中现有的 redis 包,安装 redis-3.5.3;开发项目 B 时,卸载系统中现有的 redis 包,安装 redis-3.0.0。在两个项目之间切换时,用户需要频繁的安装和卸载 redis 包,显然是很不合理的。那么,这种不合理应该如何解决呢?在 Python 开发中有个神器叫做 virtual 就是专门用来解决问题的,下面我们就来看下 virtual 这个神器到底神在哪里?

Maven 仓库

在之前的章节中,我们分别介绍了 Maven 中的工程对象模型(POM)以及 Maven 的依赖管理,但是,这个时候,我们势必会有一个疑问,当我找到一个依赖的坐标后,只需要将该坐标放入到我项目的 POM 文件当中,这个依赖就算是被引入了,那这个依赖是从哪里来的呢?在本节中,我们就带着这个疑问来学习 Maven 的仓库,了解如何使用 Maven 仓库。

3. indexOf () 的问题

indexOf() 在查询数组中元素时存在一些问题,下面我们就来看看为什么 ES6 要引入 includes() 方法。在 ES5 中使用 indexOf() 方法在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回 -1。但是查找数组时存在一定缺陷,indexOf 不能判断数组中是否有 NaN,对于数组中的空项也不能判断。var arr1 = [,,,,,];var arr2 = [null, undefined, NaN];console.log(arr1[0], arr1[1]) // undefined undefinedarr1.indexOf(undefined) // -1arr2.indexOf(NaN); // -1上面的代码可以看到,在第 1 行中数组的每一项都是空的, 使用 indexOf() 查找返回的结果为 -1,没有查到 undefined 值,但从第 3 行打印的结果可以看到其实空数组的每一项都是 undefined。另外,还有个问题 indexOf() 不能解决,数组中有 NaN 时查询不了,返回的结果也是 -1。ES6 的includes() 可以完美解决上面的问题,看如下示例:[,,,,,].includes(undefined) // true[null, undefined, NaN].includes(NaN)] // true从上面的代码可以看出,使用 includes() 查询可以得到正确的结果。indexOf 返回的是数值型的,而 includes 返回的是布尔型的,方便逻辑判断。如下实例:var arr = ['imooc', 'ES6', 'wiki'];if (arr.includes('ES6')) { // todo}if (arr.indexOf('ES6') !== -1) { // todo}

2.2 allprojects{} 闭包

这个闭包里面的是我们项目运行所需要的的依赖,往往和上面的repositories是相对应的。buildscript { repositories { //注释1 maven { url "http://maven.aliyun.com/nexus/content/groups/public/" } google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.5.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files //注意:不要将您的应用程序依赖项放在这里; 它们属于单独的模块build.gradle文件 }}allprojects { repositories { //注释2 maven { url "http://maven.aliyun.com/nexus/content/groups/public/" } google() jcenter() }}task clean(type: Delete) { delete rootProject.buildDir}这里我们需要注意代码中的注释1和注释2处的 repositories 闭包,往往我们添加一个 maven 库的依赖时,需要两个闭包中都添加一遍。Tips: 我们添加 Maven 库时可以需要两个都添加,比如国外 Maven 访问太慢,我们可以加入国内阿里云的 Maven 库。

6. ABA 问题

ABA 问题描述:假设有两个线程,线程 1 和线程 2,线程 1 工作时间需要 10 秒,线程 2 工作需要 2 秒;主内存值为 A,第一轮线程 1 和线程 2 都把 A 拿到自己的工作内存;第 2 秒,线程 2 开始执行,线程 2 工作完成把 A 改成了 B ;第 4 秒,线程 2 把 B 又改成了 A,然后就线程 2 进入休眠状态;第 10 秒,线程 1 工作完成,看到期望为 A 真实值也是 A 认为没有人动过,其实 A 已经经过了修改,只不过又改了回去,然后线程 1 进行 CAS 操作。ABA 问题解决:为了解决这个问题,在每次进行操作的时候加上一个版本号或者是时间戳即可。

1.1 下载 Maven 安装包

首先在 Maven 官网上,找到下载地址,并下载该版本apache-maven-3.6.3-bin.zip,如下图所示:

过拟合问题

在我们之前的学习之中,我们或多或少都会遇到一些训练时间的问题。比如“训练时间越长是不是最后的结果就会越好?”等问题。答案当然是否定的,这是因为在训练的过程之中会遭遇到“过拟合”的问题,这是一种随着训练时间不断加长而产生的问题,那么这节课我们就来学习一下什么是过拟合,同时了解一下 TensorFlow 之中的避免过拟合的简单的方法。这节课之中,我们使用之前学习过的猫狗分类的例子进行示例演示。

3.2 isNaN () 的问题

默认情况全局下存在方法 isNaN () 用了判断是否为 NaN 值,它要求接收的是数值类型的参数,但是当参数不是 Number 类型, isNaN 函数会首先尝试将这个参数转换为数值,然后才会对转换后的结果是否是 NaN 进行判断。实例:isNaN(NaN); // trueisNaN(undefined); // trueisNaN('undefined')// trueisNaN({}); // trueisNaN(true); // falseisNaN(null); // falseisNaN(37); // false// stringsisNaN("37"); // false: 可以被转换成数值37isNaN("37.37"); // false: 可以被转换成数值37.37isNaN("37,5"); // trueisNaN('123ABC'); // true: parseInt("123ABC")的结果是 123, 但是Number("123ABC")结果是 NaNisNaN(""); // false: 空字符串被转换成0isNaN(" "); // false: 包含空格的字符串被转换成0// datesisNaN(new Date()); // falseisNaN(new Date().toString()); // trueisNaN("imooc") // true: "blabla"不能转换成数值 // 转换成数值失败, 返回NaN结合上面 NaN 是如何产生的例子的结果可以看出,使用 isNaN 来判断返回的是 true,这显然不是我们想要的结果。针对这样的问题,ES6 做了修补,下面我们看 ES6 中的 isNaN 方法。

2.3 第三步:使用 Swagger Codegen 生成服务端和客户端代码

在将 Swagger Codegen 的依赖引入到 Spring Boot 中去后,我们就可以使用 Maven 自带的命令来将上述配置信息分别生成服务端和客户端代码,命令如下:首先,将上述配置好的文件利用 Swagger Codegen 来生成服务端和客户端代码 java -jar swagger-codegen-cli.jar generate -i swagger.yaml -c swaggerConfig.json -l spring -o server代码解释:第一行,使用 generate 命令来将配置在 swagger.yaml 文件中的服务端代码进行生成。第一行,使用 -c 参数,表明使用 json 配置文件,并且该配置文件的名称为 swaggerConfig.json。第二行,使用 -l 参数,表明客户端所使用的语言为 spring 。第二行,使用 -o 参数来指定代码最终的存放位置,server 表示将生成的代码存放到名为 server 的文件夹下。然后我们使用 cd 命令来进到我们生成代码后所存放的目录: cd server最后我们将生成的代码打成 Jar 包: mvn package这是 Maven 自带的打包命令,执行该命令之后,Maven 会默认读取项目中的 pom 文件中配置的打包规则,即 packaging 节点,如果该节点没有配置任何规则,则 Maven 会默认打成 Jar 包 (这里我们配置了 Jar)。这样我们就可以在项目的 target 目录下,找到我们利用 Swagger Codegen 所生成的服务端和客户端代码的 Jar 包了,我们可以把该 Jar 包放到其他环境中使用,也可以供其他项目使用,这就是我们利用 Swagger Codegen 所生成的服务端和客户端代码的最终使用目的。

2. 定位问题SQL

定位 MySQL 的问题 SQL,主要有两种方法,查看当前线程(show processlist)和慢日志。一般来说,当前发生的问题用到 show processlit,事后分析用到慢日志。

1. 问题的产生

访问关系数据库的传统方式是:拼接 SQL 语句。例如,向数据库中插入一条数据,根据要插入的数据拼接一条 SQL INSERT 语句,下面的 Python 程序使用 SQL 语句向数据库中插入一条学生的信息:sno = '20201916'name = '张三'age = 20gender = 'male'sql = 'INSERT INTO students(sno, name, age, gender) VALUES("%s", "%s", %d, "%s")' % (sno, name, age, gender)rows = cursor.execute(sql)在第 5 行,Python 程序使用字符串运算符 % 根据参数 sno、name、age 和 gender 最终生成一条 SQL 语句:INSERT INTO students(sno, name, age, gender) VALUES("", "张三", 20, "male");随着项目越来越大,通过拼接 SQL 语句访问数据库存在如下的问题:1. 繁琐易错在上面的例子中,第 5 行代码用于拼接 INSERT 语句,INSERT 语句需要插入 4 个字段,该行代码较长,无法在一行显示。在实际的软件开发中,INSERT 语句可能需要插入 10 个以上的字段,那么拼接 INSERT 语句的代码则非常的繁琐易错。下面的 SQL 语句来自于一个实际的项目:sql = "INSERT INTO Flights(FlightID, AircraftModel, RegisterID, Direction, ExpectApronTime, RunwayID, ApronID, AirwayID, TaxiwayTimes, AirwayTimes, Rank) VALUES('%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', %d)" % (flightID, aircraftModel, registerID, direction, expectApronTime, runwayID, apronID, airwayID, taxiwayTimes, airwayTimes, rank)要插入的数据包含有 11 个字段,造成 SQL 语句非常的冗长,需要在多行中才能完全显示,程序的可读性极差。2. SQL 语句重复利用率低越复杂的 SQL 语句条件越多、代码越长,在实际的项目中,会出现很多很相近的 SQL 语句。3. Web 安全漏洞直接使用 SQL 语句存在有 Web 安全漏洞的问题:通过把 SQL 命令插入到页面请求的查询字符串,最终达到欺骗服务器执行恶意的 SQL 命令。下面的 SQL 语句根据页面请求中的用户名和密码查询数据库:username = 从页面请求中获取用户名password = 从页面请求中获取密码sql = 'select * from users where username = "%s" and password = "%s"' % (username, password)在第 3 行的 SELECT 语句中,where 条件进行权限检查,只有 username 和 password 与数据库表 users 中的数据匹配时,才返回有效数据,因此,只有用户输入正确的用户名和密码才可以获取数据。这条 SQL 语句存在有安全漏洞,假设用户在页面中输入的用户名为 admin"# (共 7 个字符,前 5 个字符是 admin,后面 2 个字符是 " 和 #),密码为 123456,则最终拼接的 SQL 语句如下:select * from users where username = "admin"#" and password = "123456"在 SQL 中,# 是行注释,因此上述 SQL 语句相当于:select * from users where username = "admin"只要数据库表 users 中有 admin 这条记录,执行该条 SQL 语句就会返回数据,这样对 password 的检查就彻底失效了。

3.2 添加依赖包

项目创建成功后,会发现项目上有红色的错误提示,这个不用紧张。因为项目自动创建了一个 jsp 文件,而 jsp 所依赖的 servlet 包我们还没有加进来。打开项目中的 pom.xml 文件,在文件中添加项目所需要的依赖 jar 包:javax.servlet-api: servlet 规范包;spring-context: spring 最基础、最重要的核心包。Maven 有一个依赖传递功能,会自动添加 spring-context 所依赖的其它包;spring-web: spring 对 web 项目的支持包,这个不用解释,肯定不能少;spring-webmvc: 从名字上看,知道它应该是主角,Spring MVC 核心包。完整的依赖信息如下:<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.5</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.13.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.1.13.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.13.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency></dependencies>Maven 会自动从远程仓库下载这些依赖包,项目中也可以看到下载下来的依赖包:大家会看到,除了在 pom.xml 文件中指定的依赖包外,还有其它的包,这个就是 Maven 的依赖传递功能实现的。好了! 有了这些包后,就可以使用 Spring 提供的 WEB MVC API 了。

Maven 使用 Profile 构建

上一节,我们讲到了如何使用 Maven 自动化的进行单元测试,那测试通过之后,我们就要进行构建,并且将构建好的程序包,放到对应的服务器上去运行。这个时候,问题就出现了,对于不同环境,我们需要不同的配置文件,那我们构建的之前,就需要将配置文件改为对应环境的配置文件,之后才能进行构建。总而言之,很麻烦,而且,万一忘记改配置,那么构建出来的包就是错的。Profile 则让不同环境之间可移植性的构建成为可能。它使我们在构建项目的时候,可以很轻松的在不同环境中进行构建,也可以称之为“开箱即用”。

分号导致的问题

在 JavaScript 中分号是可选的,解释器会自动对分号进行补全。如果选择不写分号,需要注意一些使用上的问题。不写分号,相当于将插入分号的权利递交给解释器,对于某些情况,可能会出现非预期的效果:

2. SpringBoot 集成 Swagger-UI 的准备工作

我们知道,使用 Maven 来创建的项目会有专门的一个 pom.xml 文件,这个文件是我们项目中所有用到的工具包的一个列表,在 java 中被称作 jar 包。在 Maven 中通过引入不同的 jar 包坐标配置来将相应的工具集成到我们的项目中。所以当我们需要在项目中集成某种工具时,我们需要将该工具对应的坐标放到 Maven 的 pom.xml 文件中去。通过访问 Maven 的中央仓库我们可以搜索到 Swagger-UI 对应 SpringBoot 框架适合的坐标数据,如下 Maven 坐标所示:<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.6.1</version></dependency><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.6.1</version></dependency>在上述 Maven 坐标中,第一个 springfox-swagger2 依赖,为 Swagger 2 的核心依赖,即我们如果想使用 Swagger 工具,则必须要在项目中引入该依赖,如果我们没有引入该依赖,那么我们是不能在项目中使用 Swagger 的。而 springfox-swagger-ui 这一依赖,就是我们本文所介绍的 Swagger-UI 的依赖,如果我们不引入该依赖,我们是不会看到 Swagger 的 API 管理界面的。在将上述两个 Swagger 的坐标数据放到我们项目的 pom.xml 文件中去之后,我们就完成了集成 Swagger-UI 的准备工作。这样引入的 Swagger-UI 我们只能使用它的注解,而这时所产生的 Swagger-ui 界面我们是看不懂的,因为我们还没有对界面增加我们的规定,所以接下来让我们完成 Swagger-UI 的一些基本配置。

首页上一页1234567下一页尾页
直播
查看课程详情
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号