DevOps(7)--构建工具
构建工具
1. Maven
maven是主要用于java项目的构建工具。
比如当我们构建一个spring项目时,需要引入大量的jar包,一个项目Jar包的数量之多往往让我们瞠目结舌,并且Jar包之间的关系错综复杂,一个Jar包往往又会引用其他Jar包,缺少任何一个Jar包都会导致项目编译失败。
如果手动引入jar包,那么在没开始写业务之前,光是处理依赖,可能就会花费大量的时间。
Maven就是一款帮助程序员构建项目的工具,我们只需要告诉Maven需要哪些Jar 包,它会帮助我们下载所有的Jar,极大提升开发效率。
Maven不仅是构建工具,还是一个依赖管理工具和项目管理工具,它提供了中央仓库,能帮我们自动下载依赖。
1.1 本地maven安装
学java,必须先会maven,这里我们简单介绍一下
去maven官网下载maven
设置一下环境变量,将Maven安装配置到操作系统环境中,主要就是配置M2_HOME 和PATH两项
打开cmd验证即可
1.2 目录介绍
bin目录: 该目录包含了mvn运行的脚本,这些脚本用来配置java命令,准备好classpath和相关的Java系统属性,然后执行Java命令。
boot目录: 该目录只包含一个文件,该文件为plexus-classworlds-2.5.2.jar。plexus-classworlds是一个类加载器框架,相对于默认的java类加载器,它提供了更加丰富的语法以方便配置,Maven使用该框架加载自己的类库。
conf目录: 该目录包含了一个非常重要的文件settings.xml。直接修改该文件,就能在机器上全局地定制Maven的行为,一般情况下,我们更偏向于复制该文件至/.m2/目录下(表示用户目录),然后修改该文件,在用户范围定制Maven的行为。
lib目录: 该目录包含了所有Maven运行时需要的Java类库,Maven本身是分模块开发的,因此用户能看到诸如maven-core-3.0.jar、maven-model-3.0.jar之类的文件,此外这里还包含一些Maven用到的第三方依赖如commons-cli-1.2.jar、commons-lang-2.6.jar等等。
1.3 常用命令
mvn clean:表示运行清理操作(会默认把target文件夹中的数据清理)。
mvn clean compile:表示先运行清理之后运行编译,会将代码编译到target文件夹中。
mvn clean test:运行清理和测试。
mvn clean package:运行清理和打包。
mvn clean install:运行清理和安装,会将打好的包安装到本地仓库中,以便其他的项目可以调用。
mvn clean deploy:运行清理和发布(发布到私服上面)。
1.4 maven使用
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.test</groupId>
<artifactId>springBootDemo1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springBootDemo1</name>
</project>
代码的第一行是XML头,指定了该xml文档的版本和编码方式。 project是所有pom.xml的根元素,它还声明了一些POM相关的命名空间及xsd元素。 根元素下的第一个子元素modelVersion指定了当前的POM模型的版本,对于Maven3来说,它只能是4.0.0 代码中最重要是包含了groupId,artifactId和version了。这三个元素定义了一个项目基本的坐标,在Maven的世界,任何的jar、pom或者jar都是以基于这些基本的坐标进行区分的。
groupId定义了项目属于哪个组,随意命名,比如谷歌公司的myapp项目,就取名为 com.google.myapp-版本号
artifactId定义了当前Maven项目在组中唯一的ID,比如定义hello-world。
version指定了项目当前的版本0.0.1-SNAPSHOT,SNAPSHOT意为快照,说明该项目还处于开发中,是不稳定的。
name元素生命了一个对于用户更为友好的项目名称,虽然这不是必须的,但还是推荐为每个POM声明name,以方便信息交流
1.4.1 依赖配置
<project>
...
<dependencies>
<dependency>
<groupId>实际项目</groupId>
<artifactId>模块</artifactId>
<version>版本</version>
<type>依赖类型</type>
<scope>依赖范围</scope>
<optional>依赖是否可选</optional>
<!—主要用于排除传递性依赖-->
<exclusions>
<exclusion>
<groupId>…</groupId>
<artifactId>…</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependencies>
...
</project>
根元素project下的dependencies可以包含一个或者多个dependency元素,以声明一个或者多个项目依赖。每个依赖可以包含的元素有:
grounpId、artifactId和version:以来的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven根据坐标才能找到需要的依赖。
type:依赖的类型,对于项目坐标定义的packaging。大部分情况下,该元素不必声明,其默认值为jar
scope:依赖的范围
optional:标记依赖是否可选
exclusions:用来排除传递性依赖
1.4.2 依赖范围
依赖范围就是用来控制依赖和三种classpath(编译classpath,测试classpath、运行classpath)的关系,Maven有如下几种依赖范围:
compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。典型的例子是spring-code,在编译、测试和运行的时候都需要使用该依赖。
test: 测试依赖范围。使用次依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此依赖。典型的例子是Jnuit,它只有在编译测试代码及运行测试的时候才需要。
provided:已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运行时候无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器以及提供,就不需要Maven重复地引入一遍。
runtime:运行时依赖范围。使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。
system:系统依赖范围。该依赖与三种classpath的关系,和provided依赖范围完全一致,但是,使用system范围的依赖时必须通过systemPath元素显示地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能构成构建的不可移植,因此应该谨慎使用。systemPath元素可以引用环境变量,如:
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<Version>2.0</Version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
import:导入依赖范围。该依赖范围不会对三种classpath产生实际的影响。
1.5 仓库
在Maven世界中,任何一个依赖、插件或者项目构建的输出,都可以称为构件。得益于坐标机制,任何Maven项目使用任何一个构件的方式都是完全相同的。在此基础上,Maven可以在某个位置统一存储所有Maven项目共享的构件,这个统一的位置就是仓库。
实际的Maven项目将不再各自存储其依赖文件,它们只需要声明这些依赖的坐标,在需要的时候(例如,编译项目的时候需要将依赖加入到classpath中),Maven会自动根据坐标找到仓库中的构件,并使用它们。
为了实现重用,项目构建完毕后可生成的构件也可以安装或者部署到仓库中,供其他项目使用。
任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存储路径,这便是Maven的仓库布局方式。 该路经与坐标对应关系为groupId/artifactId/version/artifactId-version.packaging。 举个例子,比如下面这个分页插件依赖如下:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
那他对应的仓库的路径就是这样:
1.5.1 仓库分类
本地仓库
默认情况下,不管在Window还是Linux下,每个用户在自己用户目录下都有一个路径名为.m2/repository/的仓库目录。 如果你想自定义本地仓库目录地址。你可以编辑文件~/.m2/settings.xml,设置localRepository元素的值为想要的仓库地址
<settings> <localRepository>D:\java\repository\</localRepository> </settings>
本地仓库就是初次构建时会从远程仓库中下载依赖,并将其存储在本地,下次构建时直接从本地仓库获取
远程仓库
由于最原始的本地仓库是空的,Maven必须知道至少一个可用的远程仓库,才能在执行Maven命令的时候下载到需要的构件。中央仓库就是这样一个默认的远程仓库,Maven的安装文件自带了中央仓库的配置。
私服
私服就是在局域网搭建的maven仓库服务,企业中的通用使用方式,私服会配置远程仓库地址,通过私服下载的依赖会存储在私服中。
1.5.2 镜像
如果仓库X可以提供仓库Y存储的所有内容,那么就可以认为X是Y的一个镜像。用过Maven的都知道,国外的中央仓库用起来太慢了,所以选择一个国内的镜像就很有必要,我推荐国内的阿里云镜像。 阿里云镜像:配置很简单,修改conf文件夹下的settings.xml文件,添加如下镜像配置:
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
上例子中,的值为central,表示该配置为中央库的镜像,任何对于中央仓库的请求都会转至该镜像,用户也可以用同样的方法配置其他仓库的镜像
这里介绍下<mirrorOf>
配置的各种选项
<mirrorOf>*<mirrorOf>
:匹配所有远程仓库。<mirrorOf>external:*<mirrorOf>
:匹配所有远程仓库,使用localhost的除外,使用file://协议的除外。也就是说,匹配所有不在本机上的远程仓库。<mirrorOf>repo1,repo2<mirrorOf>
:匹配仓库repo1h和repo2,使用逗号分隔多个远程仓库。<mirrorOf>*,!repo1<mirrorOf>
:匹配所有远程仓库,repo1除外,使用感叹号将仓库从匹配中排除。
需要注意的是,由于镜像仓库完全屏蔽了被镜像仓库,当镜像仓库不稳定或者停止服务的时候,Maven仍将无法访问被镜像仓库,因而将无法下载构件。
1.6 私服
maven的私服最常使用的就是Nexus,地址:https://help.sonatype.com/repomanager3/product-information/download
下载安装即可,当然也可以使用docker或者k8s进行安装。
地址:https://hub.docker.com/r/sonatype/nexus3/
1.7 jenkins集成maven
流水线的构建:
上传git
代码扫描
打包 build
生成镜像
上传harbor仓库
运行
第一步,我们先准备一个示例工程
package com.example.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class HelloController {
@RequestMapping("/hello")
public Map sayHello(String name){
Map m = new HashMap<>();
m.put("code",200);
m.put("msg","hello "+name);
return m;
}
}
第二步打开jenkins新建一个流水线
第三步配置maven环境
第四步编写Jenkinsfile
pipeline {
// 指定任务在哪个集群节点中执行,any表示任意节点
agent any
stages {
stage('maven构建') {
steps {
script{
mavenHome = tool 'maven'
}
sh "${mavenHome}/bin/mvn clean package -Dmaven.test.skip=true"
}
}
}
}
接下来做的事情和部署go项目一样了,构建镜像,上传harbor,部署k8s即可。
2. Gradle
Gradle是一个开源的项目自动化构建工具,和上面讲的Maven是一样的,但是它比Maven的构建速度要快,其引入了基于Groovy的特定邻域语言(DSL)。
需要说明的是,Gradle是支持使用Maven的仓库的。
Gradle逐渐普及,比如spring源码就是gradle构建的,但是Gradle不如Maven简单,学习成本高,目前还是Maven用的多一些。
2.1 本地安装
解压配置环境变量即可
配置GRADLE_USER_HOME环境变量,为仓库地址,可以配置和maven一致
2.2 gradle项目目录介绍
用gradle init可以初始化一个gradle项目
当然一般情况下,创建java项目直接使用idea自带的初始化工具即可。
注意:springboot使用的jdk版本要和gradle匹配。
2.3 常用命令
gradle clean: 情况build目录
gradle classes:编译业务代码和配置文件
gradle test: 编译测试代码,生成测试报告
gradle build: 构建项目
gradle build -x test : 构建项目跳过测试
2.4 修改下载源
在gradle的init.d目录下创建以.gradle结尾的文件,.gradle文件可以实现在build开始之前执行,所以你可以在这个文件配置一些你想预先加载的操作。
allprojects :针对所有的功能
repositories :下载项目指定jar包
buildscript:构建脚本使用
allprojects {
repositories {
mavenLocal()
maven { name "Alibaba" ; url "https://maven.aliyun.com/repository/public" }
maven { name "Bstek" ; url "https://nexus.bsdn.org/content/groups/public/" }
mavenCentral()
}
buildscript {
repositories {
maven { name "Alibaba" ; url 'https://maven.aliyun.com/repository/public' }
maven { name "Bstek" ; url 'https://nexus.bsdn.org/content/groups/public/' }
maven { name "M2" ; url 'https://plugins.gradle.org/m2/' }
}
}
}
启用init.gradle文件的方法有
在命令行指定文件,例如:gradle --init-script yourdir/init.gradle -q taskName。你可以多次输入此命令来指定多个init文件
把init.gradle文件放GRADLE_USER_HOME/.gradle/ 目录下
把以.gradle结尾的文件放到 GRADLE_USER_HOME/.gradle/init.d/ 目录下
把以.gradle结尾的文件放到 GRADLE_HOME/init.d/ 目录下
2.5 jenkins集成gradle
第一步,我们先准备一个示例工程
第二步打开jenkins新建一个流水线
第三步配置gradle环境
第四步编写Jenkinsfile
pipeline {
// 指定任务在哪个集群节点中执行,any表示任意节点
agent any
stages {
stage('gradle构建') {
steps {
script{
gradleHome = tool 'gradle'
}
sh "${gradleHome}/bin/gradle build -x test"
}
}
}
}
3. NPM
npm是前端的构建工具,需要下载nodejs,地址:https://nodejs.org/en/download/
3.1 常用命令
npm install <moduleName> -g 包安装到全局
npm list:查看当前已安装的包。
npm config set registry https://registry.npm.taobao.org 设置淘宝源
npm config set cache "/opt/npmcache/" 设置缓存路径
npm run build 构建项目
npm run serve 运行项目
3.2 创建前端vue项目
D:\git\github\mszlu\npm\demo>npm install -g vue
D:\git\github\mszlu\npm\demo>npm init vue@latest
npx: installed 1 in 2.13s
Vue.js - The Progressive JavaScript Framework
√ Project name: ... vuedemo
√ Add TypeScript? ... No / Yes
√ Add JSX Support? ... No / Yes
√ Add Vue Router for Single Page Application development? ... No / Yes
√ Add Pinia for state management? ... No / Yes
√ Add Vitest for Unit Testing? ... No / Yes
√ Add an End-to-End Testing Solution? » No
√ Add ESLint for code quality? ... No / Yes
Scaffolding project in D:\git\github\mszlu\npm\demo\vuedemo...
Done. Now run:
cd vuedemo
npm install
npm run dev
D:\git\github\mszlu\npm\demo\vuedemo>npm install
D:\git\github\mszlu\npm\demo\vuedemo>npm run dev
> vuedemo@0.0.0 dev D:\git\github\mszlu\npm\demo\vuedemo
> vite
VITE v4.1.1 ready in 396 ms
➜ Local: http://127.0.0.1:5173/
➜ Network: use --host to expose
➜ press h to show help
ok, 示例工程创建完成,将其上传到git上
3.3 jenkins集成npm
第一步,我们先准备一个示例工程
第二步创建流水线任务
第三步安装nodejs插件并配置nodejs
第四步 编写Jenkinsfile
pipeline {
// 指定任务在哪个集群节点中执行,any表示任意节点
agent any
stages {
stage('npm构建') {
steps {
script{
nodeHome = tool 'node'
}
sh "rm -rf /usr/bin/node"
sh "ln -s ${nodeHome}/bin/node /usr/bin/node"
sh "${nodeHome}/bin/npm install"
sh "${nodeHome}/bin/npm run build"
}
}
}
}