使用Gitee中的CI/CD来完成代码的自动部署与发布(使用内网穿透把本地电脑当作服务器使用)

news2024/12/27 4:15:24

📚目录

  • 📚简介:
  • ⚙️ 所需工具:
  • 💨内网穿透配置
    • 💭工具介绍
    • ✨命令安装
    • 🎊配置Cpolar
    • 🕳️关闭防火墙
    • 🥛防火墙端口放行规则(关闭防火墙可以忽略)
    • 🍬小章总结
  • 🚀项目创建提交Giee
    • 🏡idea创建工程
    • ✍️编写代码
    • 💭城市天气获取接口
      • 💫主要代码
      • 💨运行项目
      • 💨接口测试
      • 🚀推送代码到远程
    • 🍬小章总结
  • 🎄CI/CD配置使用
    • 🎃创建CI/CD流水线
    • 🌈流水线代码
    • 🖥成功一半
    • 📃优化流水线配置
    • ⚡自动化效果
  • ⛄程序结合内网穿透
    • 🌈启动Cpolar
    • 🌠启动java程序
    • 🌄内网穿透接口测试
  • 🎉总结:

📚简介:

       使用gitee来存储代码,我们修改或者增加新功能时,就不需要把本地的jar编译好上传服务器,直接使用CI/CD来完成部署,里面已经支持Maven的构建与上传到远程服务器上完成项目的部署。这一次的记录,不需要你们买服务器,虽说服务器新用户一年也就八九十块钱,但是我们也可以不花钱学会,因为我打算使用本地电脑虚拟机新建一个Linux,然后搭配免费的内外穿透工具来完成本次的教学.

⚙️ 所需工具:

  1. 本地Linux:本次教学不涉及虚拟机Linux的安装如需购买可以看往期教程购买一台服务器安装 青龙面版 撸京豆
  2. gitee的账号去注册gitee账号
  3. 映射工具(cpolar)下载Linux的版本

💨内网穿透配置

💭工具介绍

Cpolar官网下载,Linux版本

在这里插入图片描述

我们去下载Linux版本

在这里插入图片描述

可以看官网已经列举出来Linux的安装步骤

在这里插入图片描述

✨命令安装

我这使用Xshell连接本地虚拟机中的Linux

在这里插入图片描述

输入下载代码使用Curl方式

curl -L https://www.cpolar.com/static/downloads/install-release-cpolar.sh | sudo bash

在这里插入图片描述

查看版本号

cpolar version

在这里插入图片描述

🎊配置Cpolar

登录cpolar官网后台,点击左侧的验证,查看自己的认证token,之后将token贴在命令行里

在这里插入图片描述

cpolar authtoken 自己的Authtoken

在这里插入图片描述
在这里插入图片描述

设置Cpolar开机自启

sudo systemctl enable cpolar

在这里插入图片描述

现在我们启动Cpolar,实现内网穿透,我们先开启一个http的8080端口

cpolar http 8080

在这里插入图片描述
       如果我们使用接口软件来访问该地址,我们正好有java的8080端口程序在运行,则会接收到请求信息。(前提是本地Linux开启了对应端口号的防火墙)
注意:ctrl+c是退出Cpolar,每一次退出启动Cpolar的域名都会变

在这里插入图片描述

Cpolar的后台也可以看到对应的url地址

在这里插入图片描述

🕳️关闭防火墙

防火墙设置

service iptables status 查看防火墙状态
service iptables stop 关闭防火墙
service iptables start 启动防火墙

防火墙状态是启动的

在这里插入图片描述
我们需要关闭防火墙

在这里插入图片描述

🥛防火墙端口放行规则(关闭防火墙可以忽略)

查看防火墙放行的端口号(上面直接关闭防火墙可以不需要以下操作)

iptables -L -n

在这里插入图片描述

可以看出当前并没有放行8080的防火墙端口号,我们需要放行端口才能通过映射访问本地服务器

Linux 放行防火墙端口号,用于外界访问

## 开启
iptables -A INPUT -p tcp --dport 端口号 -j ACCEPT
## 保存配置
service iptables save
## 重启
service iptables restart

在这里插入图片描述

🍬小章总结

       到这里内网穿透的基本就配置完成了,由于开启了Cpolar后Xshell就不能输入命令行,所以你们可以在开一个新的选项卡。

在这里插入图片描述
在这里插入图片描述
       由于我们还没有写java程序,所以访问Cpolar的地址显示没有运行网站服务器,后续我们把代码上到本地服务器来看效果就直观了

在这里插入图片描述

🚀项目创建提交Giee

创建好Gitee账号后,我们点击右上角的加号进行新建仓库

在这里插入图片描述

创建自己的仓库,仓库名称使用英文

在这里插入图片描述

仓库创建好后,我们需要把仓库拉取到本地

在这里插入图片描述

       我们在本地选择好文件夹目录,使用英文的目录,然后使用命令拉取下来,提示拉取一个空的仓库,我们到时候会把这个目录当做IDEA的开发目录,到时候代码就可以推送到远程上

在这里插入图片描述

该目录只有一个.git,里面存放着当前仓库git的一些配置信息

在这里插入图片描述

🏡idea创建工程

在这里插入图片描述
在这里插入图片描述

我们创建一个web服务我们先勾选,Spring web依赖,没有勾选也没事,到时候在pom.xml中添加依赖也行

在这里插入图片描述

       创建好工程后,我们看下界面是否有git的图标,没有就去下载个git插件,这样我们就可以可视化的拉取代码,推送代码到远程分支,和切换分支等操作。

在这里插入图片描述

由于我这个版本所有捆绑git插件所以不需要下载,有关git的插件,如果你们的IDEA没有git插件可以去插件市场里面下载git插件

在这里插入图片描述

直接去下载安装git插件,然后重启IDEA,这样插件才能生效,可以看往期文章 IDEA工具插件(持续更新中…)

在这里插入图片描述

       红色文件的是没被git管理的文件,绿色的文件是添加到git管理的文件,这样我们提交推送远程的时候就可以把绿色文件推送到远程

在这里插入图片描述

选择好需要添加的文件,我们右键选择添加到 VCS

在这里插入图片描述
在这里插入图片描述

✍️编写代码

application.properties名称修改成application.yml

在这里插入图片描述

# 应用服务 WEB 访问端口
server:
  port: 8080

在这里插入图片描述

💭城市天气获取接口

       至于写什么呢?要不用我以前写的,传递对应城市返回对应城市的天气消息,这样项目也不会那么无味,因为之前接口什么的已经分析好了,我直接请求接口就可以获取对应城市的天气信息,如果对如何分析天气接口感兴趣的可以前往往期文章【手把手教你】如何获取中国天气网,获取想要城市的天气-图文并茂-分析代码

💫主要代码

层级结构

  • 控制层:用于接收请求,编写接口的类
  • 响应返回对象
  • 全局异常处理类,对发送错误的数据封装好回调给调用方
  • 服务层:控制层调用服务层,服务层调用mapper层(持久层操作数据库的层),
    因为我们这个不需要连接数据库所以省略,该类提供了传递城市返回城市天气的详细数据

在这里插入图片描述

ApiController 代码

/**
 * @Author itmei
 * @Date 2023/12/20 20:33
 * @description: 控制层
 * @Title: ApiController
 * @Package com.itmei.cicddemo.demos.controller
 */
@RestController
@RequestMapping("/api")
public class ApiController {
    @Resource
    private ApiService apiService;
    /**
     *
     * @return
     */
    @GetMapping("/cityWeatherDetails")
    public ResultData cityWeatherDetails(String city) {
        JSONObject realWeather = apiService.getRealWeather(city);
        return ResultData.success(realWeather);
    }
}


ResultData 代码

/**
 * @Author itmei
 * @Date 2022/4/10 11:38
 * @Version 1.0
 */
public class ResultData extends HashMap<String, Object> {
    private static final long serialVersionUID = 1L;
    /**
     * 异常Code
     */
    private static final Integer HTTP_STATUS_ERROR = 500;
    /**
     * 成功Code
     */
    private static final Integer HTTP_STATUS_SUCCESS = 200;
    /**
     * 状态码
     */
    public static final String CODE_TAG = "code";
    /**
     * 提示信息
     */
    public static final String MSG_TAG = "msg";
    /**
     * 具体内容
     */
    public static final String DATA_TAG = "data";

    /**
     * token
     */
    public static final String TOKEN_TAG = "token";

    /**
     * 返回空数据
     */
    public ResultData() {
    }

    /**
     * 初始化一个新创建的 ResultData 对象
     *
     * @param code 状态码
     * @param msg  返回内容
     */
    public ResultData(int code, String msg) {
        this.put(CODE_TAG, code);
        this.put(MSG_TAG, msg);
    }

    /**
     * 初始化一个新创建的 ResultData 对象
     *
     * @param code 状态码
     * @param msg  返回内容
     * @param data 数据对象
     */
    public ResultData(int code, String msg, Object data) {
        this.put(CODE_TAG, code);
        this.put(MSG_TAG, msg);
        /**
         * 判断是否有数据
         */
        if (data != null && !"".equals(data)) {
            this.put(DATA_TAG, data);
        }
    }

    /**
     * 返回成功消息
     *
     * @param code 状态码
     * @param msg  返回内容
     * @param data 数据对象
     * @return ResultData
     */
    public static ResultData success(int code, String msg, Object data) {
        return new ResultData(code, msg, data);
    }

    /**
     * 返回成功消息
     *
     * @param msg  成功提示信息
     * @param data 数据对象
     * @return
     */
    public static ResultData success(String msg, Object data) {
        return new ResultData(HTTP_STATUS_SUCCESS, msg, data);
    }


    /**
     * 返回成功提示信息
     *
     * @param msg 成功提示信息
     * @return
     */
    public static ResultData success(String msg) {
        return ResultData.success(msg, null);
    }

    public static ResultData success(Object data) {
        return ResultData.success("操作成功" , data);
    }

    public static ResultData success() {
        return ResultData.success("操作成功");
    }

    /**
     * 错误提示
     *
     * @return
     */
    public static ResultData error() {
        return error(HTTP_STATUS_ERROR, "操作失败");
    }

    /**
     * 错误提示
     *
     * @param msg 数据内容
     * @return
     */
    public static ResultData error(String msg) {
        return error(HTTP_STATUS_ERROR, msg);
    }

    /**
     * 返回错误信息
     *
     * @param msg  返回内容
     * @param data 数据对象
     * @return
     */
    public static ResultData error(String msg, Object data) {
        return new ResultData(HTTP_STATUS_ERROR, msg, data);
    }

    /**
     * 返回错误消息
     *
     * @param code
     * @param msg
     * @return
     */
    public static ResultData error(int code, String msg) {
        return new ResultData(code, msg, null);
    }

    /**
     * 方便链式调用
     *
     * @param key
     * @param value
     * @return
     */
    @Override
    public ResultData put(String key, Object value) {
        super.put(key, value);
        return this;
    }
}

GlobalExceptionHandler 代码

/**
 * @Author itmei
 * @Date 2023/12/20 20:58
 * @description: 全局异常捕获类
 * @Title: GlobalExceptionHandler
 * @Package com.itmei.cicddemo.demos.exception
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    /**
     * 全局异常
     */
    @ExceptionHandler(Exception.class)
    public ResultData handleException(Exception e, HttpServletRequest request)
    {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',发生系统异常.", requestURI, e);
        return ResultData.error(e.getMessage());
    }
}

ApiService 代码


/**
 * @Author itmei
 * @Date 2023/12/20 20:34
 * @description: 服务层
 * @Title: ApiService
 * @Package com.itmei.cicddemo.demos.service
 */
@Service
public class ApiService {
    private static Map<String,Long> cityAreaIdMap = new HashMap<>();
    /**
     * 项目启动后会调用该方法
     * 获取所有城市AreaId
     *
     * @return
     */
    @PostConstruct
    public void getCity() {
        String cityJs = "https://j.i8tq.com/weather2020/search/city.js";
        //发送请求获取数据
        String cityStr = HttpUtil.createGet(cityJs).header("Referer", "http://www.weather.com.cn/").execute().body();
        //需要解析数据
        String cityJson = cityStr.replace("var city_data =", "");
        //创建集合存储数据
        //使用 NAMECN:AREAID
        JSONObject entries = JSONUtil.parseObj(cityJson);
        Set<String> keys = entries.keySet();
        for (String key : keys) {
            //System.out.println("第一层 省" + key);
            Set<String> citys = entries.getJSONObject(key).keySet();
            for (String city : citys) {
                //System.out.println("--第二层 城市" + city);
                Set<String> areas = entries.getJSONObject(key).getJSONObject(city).keySet();
                for (String area : areas) {
                    //System.out.println("---第三层 区:" + area);
                    JSONObject jsonObject = entries.getJSONObject(key).getJSONObject(city).getJSONObject(area);
                    //System.out.println(jsonObject.toString());
                    cityAreaIdMap.put(jsonObject.getStr("NAMECN"), jsonObject.getLong("AREAID"));
                }
            }
        }
    }

    private Long cityAreaIdMap(String city) {
        Long areaId = cityAreaIdMap.get(city);
        if (ObjectUtil.isEmpty(areaId)) {
             throw new RuntimeException("查询 "+ city +" 城市异常,确认城市是否正确!");
        }
        return areaId;
    }

    /**
     * 获取实时城市天气
     *
     * @param city
     * @return
     */
    public JSONObject getRealWeather(String city) {
        //取出对应城市的areaid
        Long areaId = cityAreaIdMap(city);
        //实时天气的地址
        String REALWEATHER_URL = "http://d1.weather.com.cn/sk_2d/";
        //拼接请求地址
        String uri = REALWEATHER_URL + areaId + ".html";
        String res = HttpUtil.createGet(uri).timeout(10000).header("Referer", "http://www.weather.com.cn/").execute().body();
        //替换数据不然会影响json的解析
        String json = res.replace("var dataSK=", "");
        return JSONUtil.parseObj(json);
    }

}

完整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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.itmei</groupId>
    <artifactId>cicd-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cicd-demo</name>
    <description>
        用于演示gitee的CI/CD的Spring Boot项目,该项目的功能定义用于获取对应城市的天气消息等功能
    </description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.6.13</spring-boot.version>
        <hutool.version>5.8.0.M2</hutool.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--java常用工具-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>${hutool.version}</version>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <!--添加打包的名称-->
        <finalName>cicd-weather</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <mainClass>com.itmei.cicddemo.CicdDemoApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

💨运行项目

在这里插入图片描述
启动成功后,打印程序端口号以及启动时间2.5秒

在这里插入图片描述

💨接口测试

使用你们自己熟悉的接口工具如ApiFox,ApiPost,PostMan等

请求接口:/api/cityWeatherDetails?city=福州

在这里插入图片描述

响应结果:

{
	"msg": "操作成功",
	"code": 200,
	"data": {
		"nameen": "fuzhou",
		"cityname": "福州",
		"city": "101230101",
		"temp": "8.3",
		"tempf": "46.9",
		"WD": "西北风",
		"wde": "NW",
		"WS": "2级",
		"wse": "5km/h",
		"SD": "93%",
		"sd": "93%",
		"qy": "1018",
		"njd": "16km",
		"time": "21:30",
		"rain": "0",
		"rain24h": "0",
		"aqi": "20",
		"aqi_pm25": "20",
		"weather": "多云",
		"weathere": "Cloudy",
		"weathercode": "d01",
		"limitnumber": "",
		"date": "12月20日(星期三)"
	}
}

在这里插入图片描述

传递错误测试查看错误效果

在这里插入图片描述

响应结果:

{
	"msg": "查询 奥尔良 城市异常,确认城市是否正确!",
	"code": 500
}

🚀推送代码到远程

现在确定代码没问题了,我们可以通过IDEA的可视化界面操作git,把代码推送gitee的仓库中了。

选择需要提交的文件,怎么选择多个文件呢,你按着Shift+文件就会被多选,然后我们右键点击提交文件

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
需要注意的是当前提交的是本地git仓库,远程现在还是没有代码的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

点完这个推送后代码就会推送到远程gitee的仓库中

在这里插入图片描述

增加项目打jar包的名称,记得推送到远程哦

在这里插入图片描述

🍬小章总结

       到这里我们就完成了代码的编写和git的代码推送。看到这里了给自己加加油吧,因为你也可以通过传递不同的城市,获取对应城市天气详情数据,动手敲起来,你一定可以得到收获的。

🎄CI/CD配置使用

🎃创建CI/CD流水线

在我们的仓库中选择,流水线

在这里插入图片描述
在这里插入图片描述
选择不自动创建,我们自己创建

在这里插入图片描述

我们自己点击创建流水线

在这里插入图片描述

在这里插入图片描述

把配置项添加进去,需要注意的是里面的cicd-demo你们都替换成GiteeGo应用名吧,然后需要注意的是./target/cicd-weather.jar这个是git进行maven编译时需要帮他指定在那个目录下,不然找jar的位置

在这里插入图片描述

🌈流水线代码

version: '1.0'
name: master-pipeline
displayName: MasterCi
triggers:
  trigger: auto
  push:
    branches:
      include:
        - master
stages:
  - name: compile
    displayName: 编译
    strategy: naturally
    trigger: auto
    steps:
      - step: build@maven
        name: build_maven
        displayName: Maven 构建
        jdkVersion: 8
        mavenVersion: 3.3.9
        commands:
          - '# mvn -B clean package -Dmaven.test.skip=true'
          - ''
          - mvn clean package -Dmaven.test.skip=true -U -e -X -B
        artifacts:
          - name: BUILD_ARTIFACT
            path:
              - ./target/cicd-weather.jar
        caches:
          - ~/.m2
        strategy: {}
      - step: publish@general_artifacts
        name: publish_general_artifacts
        displayName: 上传制品
        dependArtifact: BUILD_ARTIFACT
        artifactName: cicd-demo
        strategy: {}
        dependsOn: build_maven
  - name: release
    displayName: 发布
    strategy: naturally
    trigger: auto
    steps:
      - step: deploy@agent
        name: deploy_agent
        displayName: 主机部署
        hostGroupID:
          ID: 192.168.0.45
          hostID:
            - 76f3
        deployArtifact:
          - name: cicd-demo
            target: ~/gitee_go/deploy
            source: build
            dependArtifact: BUILD_ARTIFACT
        script:
          - '# 功能:部署脚本会在部署主机组的每台机器上执行'
          - '# 修改APP_NAME为GiteeGo应用名'
          - APP_NAME=cicd-demo
          - 'APP_HOME_DIR=/home/giteeAuto/giteeJar/${APP_NAME}        # 存放jar包放到这个目录下'
          - 'APP_HOME_BACK_DIR=/home/giteeAuto/giteeJar/${APP_NAME}/back        # 把之前存在的jar备份到该目录下'
          - 'APP_HOME_DIR_TARGET=${APP_HOME_DIR}/ #解压后的包名称需要提取里面的jar'
          - 'APP_HOME_DIR_TARGET_NAME=cicd-weather #解压后的包名称'
          - ''
          - mkdir -p ${APP_HOME_DIR}
          - mkdir -p ${APP_HOME_BACK_DIR}
          - ''
          - ''
          - 'JAR_NAME=${APP_HOME_DIR}/${APP_HOME_DIR_TARGET_NAME}.jar    # jar包的路径名字'
          - 'JAR_BACK_NAME=${APP_HOME_BACK_DIR}/${APP_HOME_DIR_TARGET_NAME}.jar    # 备份jar包的路径名字'
          - ''
          - ''
          - echo 'Gitee自动化开始运行 备份之前jar包'
          - ''
          - if [ -f ${JAR_NAME} ];then
          - echo "文件存在则移动文件到备份中"
          - mv ${JAR_NAME} ${JAR_BACK_NAME}_`date '+%Y%m%d_%H.%M.%S'`
          - else
          - echo "文件不存在忽略"
          - fi
          - ''
          - echo 'Gitee自动化开始运行 解压到指定目录中'
          - tar zxvf ~/gitee_go/deploy/${APP_NAME}.tar.gz -C ${APP_HOME_DIR}
          - echo '-----解压完成----'
          - ''
          - cd ${APP_HOME_DIR}/
          - ./deploy.sh restart
          - ''
          - echo '-----项目重启完成----'
          - ''
        notify: []
        strategy:
          retry: '0'

需要改动的地方

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

添加Linux主机

在这里插入图片描述
在这里插入图片描述

复制下来,粘贴到我们本地内网穿透的服务器命令行中

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

回到gitee的页面,可以看到我们本地的电脑已经在线了,这个时候在去配置我们的流水线

在这里插入图片描述
在这里插入图片描述

点击保存,并确认创建流水线

在这里插入图片描述
在这里插入图片描述

我们可以看到,创建后自动给我们执行了流水线并且完成了Maven的编译,和成品的上传

在这里插入图片描述
       但是在发布到我们本地服务时发生了异常,出现问题不可怕,可怕的是今天写的有点晚了,都快11点了,保命要紧今天就先写到这,明天再出来解决错误问题。

在这里插入图片描述

错误提示没有wget命令导致的,我们回到本地Linux 命令行查看是否也提示没有这个命令

在这里插入图片描述
可以看出的确没有这个命令,提示-bash: wget: command not found,那我们我们要安装wget命令
在这里插入图片描述

使用yum 命令进行安装

yum -y install wget

在这里插入图片描述

可以看到又出现其他问题了,你们没有出现的可以忽略,这个是因为我的虚拟磁盘已经满了,需要清理下

## 查看根目录下的所有大于100M的文件并输出
find / -size +100M -type f -exec ls -l {} \;
rm -

在这里插入图片描述

       然后cd 到需要输出的文件下使用rm命令进行删除,可别再根目录使用rm -rf *删除哦不然你就完犊子了,保守一点你们还是用 rm -rf 文件名称 进行删除,删除完成后/dev/sda3 释放了2.3g的内存,我们接着使用命令安装wget

在这里插入图片描述

安装成功wget后的日志输出

在这里插入图片描述

回到流水线,我们点击失败的发布,然后点击重新执行,看看效果

在这里插入图片描述

🖥成功一半

       其实到这一步了,并不是真正意义上的失败,因为我们还有一个启动程序Linux的sh脚本没有上传到本地服务器上,但是对应流水线来说的确是失败的,因为没有./deploy.sh 文件

在这里插入图片描述

现在我们在看下我们本地的linux服务是不是创建了对应的文件,和把对应的jar包解压到对应的位置上

在这里插入图片描述
       本地服务器已经有正常的文件了,这一步是流水线自动把打包好的jar包拉取到本地,然后按照我们的linux命令进行执行的,是不是就很方便了。
在这里插入图片描述

📃优化流水线配置

       因为这个流水线配置是比较早的版本,当时是有优化了下这个流水线配置,直接把运行的脚本添加到项目中,然后通过我们设置的命令运行启动脚本,我现在才想起来,所以就不去动之前的流水线配置了,不然有些读者可能会看懵了,配置和流水线输出的结果不一致,产生迷惑。

我们在代码中新建bin目录并且把运行脚本添加进去,创建的bin目录是和src同级的,不要搞错了,还有记得修改脚本中的运行jar名称

在这里插入图片描述

我们先更新远程的代码,本次拉取远程的代码是流水线的配置文件会拉到我们的工程中.

在这里插入图片描述

该目录下的存放着我们的流水线配置,我们可以直接在这上面修改流水线配置,我们把流水线配置下然后再一起推送到远程

在这里插入图片描述

添加三处位置

在这里插入图片描述

              - ./bin/deploy.sh

在这里插入图片描述

          - 'DEPLOY_NAME=deploy.sh #运行脚本文件'

在这里插入图片描述

          - 'echo ''########## Gitee自动化开始运行 服务重启 ##########'''
          - cd ${APP_HOME_DIR}/
          - '#增加可执行权限'
          - chmod +x ${DEPLOY_NAME}
          - ./${DEPLOY_NAME} restart

提交git

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

由于我这个流水线设置的是有推送就会,自动运行流水线,完成代码的编译和发布

在这里插入图片描述

这里截图给你们看下代码配置,在git 的图形视图中的关系

在这里插入图片描述

⚡自动化效果

       到这里,流水线的自动编译和发布远程,就完成了,但是我们严谨一点,我们看下本地的程序是否正常运行,边写文章边写代码,就没有顺利过,都要踩踩坑,把你们可能出现的问题都列举出来,并解决,这个问题是提示没有主类进行加载,
这一步问题出现在打包上

在这里插入图片描述

pom.xml 去除 <skip>true</skip>,我已经把前面的pom.xml代码已经去除了,你们应该不会发生这个错误了

<skip>true</skip> 这个配置用来控制是否跳过该插件的执行,
默认值是 false,即不跳过。设置为 true 可以跳过 spring-boot-maven-plugin 插件的执行,
这意味着 Maven 不会对项目进行打包和构建,也不会生成可执行的 JAR 文件。

提交git自动执行流水线

在这里插入图片描述

见证奇迹的时候到了,运行命令查看jar的运行情况

在这里插入图片描述
非常好执行成功,接下来我们就配合Cpolar内网穿透实现接口的请求

⛄程序结合内网穿透

🌈启动Cpolar

由于开启了Cpolar后Xshell就不能输入命令行,所以你们可以在开一个新的选项卡

cpolar http 8080

在这里插入图片描述

🌠启动java程序

确保我们的java程序,正在运行中,然后再一个内网穿透来映射我们的本地java服务

在这里插入图片描述

🌄内网穿透接口测试

使用你们自己熟悉的接口工具如ApiFox,ApiPost,PostMan等

在这里插入图片描述

复制域名添加到接口请求工具中

请求地址:
http://66ae370d.r9.cpolar.top/api/cityWeatherDetails?city=福州

在这里插入图片描述
在这里插入图片描述
       可以看出,内网穿透调用了我们的服务并且返回了数据给我们,这里使用内网穿透,所以会更慢一点点,因为要多走一个Cpolar的服务器,在转发到我们这个,但是问题也不大。

🎉总结:

       终于在第三个晚上完成了这篇,巨多东西要总结,零零散散的知识点也多,不知不觉每个晚上都要写2~3个小时之间,现在距离我写总结已经是晚上10点半了,由于工作的原因,这一年写的博客没有去年的一半多,所以希望我写的文章可以帮助一些人,因为谁都是从不会到会的,依稀记得之前学校读书,当时小白的我虽说把代码写好了,本地IDEA也可以跑起来,但是网页就是打不开,我还在CSDN寻求帮助,可惜没有热度看到的人也微乎其微,当时我就下定决心,把最近学习的,可能帮助到读者的知识点写下来,也增强了知识点,学的东西多了,忘的也多了,回过头想想之前好像这个知识点我有总结,也可以回顾之前写的文章。今年2023年也到尾声了离2024年也就不到十几天的时间,希望新的一年可以多做些有意义的事情,大家一起加油🥳。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1327025.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【python】作用域与闭包 || global与nonlocal

python作用域 其他语言的作用域&#xff1a;块级、函数、类、模块、包等由小到大的级别但是python没有块级&#xff08;if语句块、for语句块&#xff09;&#xff0c;所以if中定义的变量&#xff0c;相当于普通语句 >>> if True: # if语句块没有作用域x …

华为云之ECS云产品快速入门

华为云之ECS云产品快速入门 一、ECS云服务器介绍二、本次实践目标三、创建虚拟私有云VPC1.虚拟私有云VPC介绍2.进入虚拟私有云VPC管理页面3.创建虚拟私有云4.查看创建的VPC 四、创建弹性云服务器ECS——Linux1.进入ECS购买界面2.创建弹性云服务器(Linux)——基础配置步骤3.创建…

如何使用 templ 在 Go 中编写 HTML 用户界面?

关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等&#xff0c;您的关注将是我的更新动力&#xff01; 简介 templ 是一个在 Go 中编写 HTML 用户界面的语言。使用 templ&#xff0c;我们可以创建可呈现 HTML 片段的组件&#xff0c…

基于改进YOLOv7的绝缘子缺陷检测算法

摘要 现有的检测方法面临着巨大的挑战&#xff0c;在识别绝缘子的微小缺陷时&#xff0c;针对输电线路图像与复杂的背景。为保证输电线路的安全运行&#xff0c;提出一种改进的YOLOv 7模型&#xff0c;以提高检测结果。 首先&#xff0c;基于K-means对绝缘子数据集的目标盒进…

Redis“垃圾”过期死键管理与优化

【作者】付磊 Redis死键的定义不尽相同&#xff0c;通常有两种&#xff1a; 写到Redis里后&#xff0c;由于过期时间过长或者压根没有过期时间&#xff0c;加之长期不访问&#xff0c;这类key可以被称为死键。 明明已经过了过期时间&#xff0c;但还占用Redis内存&#xff08…

利用tf-idf对特征进行提取

TF-IDF是一种文本特征提取的方法&#xff0c;用于评估一个词在一组文档中的重要性。 一、代码 from sklearn.feature_extraction.text import TfidfVectorizer import numpy as npdef print_tfidf_words(documents):"""打印TF-IDF矩阵中每个文档中非零值对应…

Nacos-服务发现与配置管理v1.0

Nacos - 服务发现和配置管理 教学目标 1&#xff09;能够理解微服务架构的特点 2&#xff09;能够理解服务发现的流程 3&#xff09;能够说出Nacos的功能 4&#xff09;掌握Nacos的安装方法 5&#xff09;掌握RESTful服务发现开发方法 6&#xff09;掌握Dubbo服务发现开…

AIGC绘画关键词 - 神兽类(一)

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

JNI学习(二)

静态注册 接着上篇博客学习 JNI函数 JNIEXPORT void JNICALL Java_com_example_jnidemo_TextDemo_setText(JNIEnv *env, jobject this, jstring string){ __android_log_print(ANDROID_LOG_ERROR, "test", "invoke set from C\n");char* str (char*)(*e…

每日一题——链表的回文结构

链表的回文结构 1. 题目描述 对于一个链表&#xff0c;请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法&#xff0c;判断其是否为回文结构。 给定一个链表的头指针A&#xff0c;请返回一个bool值&#xff0c;代表其是否为回文结构。保证链表长度小于等于900。 测试…

SpringBoot集成swagger-ui

1.引入依赖&#xff1a; <!--swagger--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.7.0</version></dependency><dependency><groupId>io.sprin…

回归预测 | MATLAB实现GWO-DHKELM基于灰狼算法优化深度混合核极限学习机的数据回归预测 (多指标,多图)

回归预测 | MATLAB实现GWO-DHKELM基于灰狼算法优化深度混合核极限学习机的数据回归预测 &#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现GWO-DHKELM基于灰狼算法优化深度混合核极限学习机的数据回归预测 &#xff08;多指标&#xff0c;多图&#…

查找算法——二分查找

笔记&#xff1a;二分查找算法 | 数据结构与算法 系列教程&#xff08;笔记&#xff09; 题目描述 请对一个 有序数组 进行二分查找 {1,8, 10, 89, 1000, 1234}&#xff0c;输入一个数看看该数组是否存在此数&#xff0c;并且求出下 标&#xff0c;如果没有就提示「没有这个数…

前端ICON库

前端ICON库 1.mingcute mingcute 2.lordicon lordicon 3.字节iconpark&#xff08;推荐&#xff09; 字节iconpark 4.iconbuddy iconbuddy.app/ 5.商标寻找youicons 免费下载数百万个徽标以获得设计灵感 | YouIcons.com 还有一堆工具

一键转换,将HTML智能转换为PDF,轻松解决文档转换需求

在数字时代&#xff0c;HTML网页是我们获取信息的主要来源之一。然而&#xff0c;有时候我们可能需要将网页内容以PDF格式保存&#xff0c;以便于离线阅读、打印或分享。这时&#xff0c;将HTML转换为PDF就变得尤为重要。 首先&#xff0c;我们要进入首助编辑高手主页面&#x…

华为数通方向HCIP-DataCom H12-831题库(多选题:181-200)

第181题 如图所示,R1、R2、R3、R4都部署为SPF区域0,链路的cost值如图中标识。R1、R2R3、R4的Loopback0通告入OSPF。R1、R2、R3与R4使用Loopback0作为连接接口,建立BGP对等体关系,其中R4为RR设备,R1、R2、R3是R4的客户端。当R4的直连地址172.20,1,4/32通告入BGP后,以下关R…

单细胞转录组揭示杨树维管组织结构与发育

之前我们有一篇PC的文章&#xff0c;专门介绍了通过单细胞转录组分析杨树茎中初生和次生生长组织中形成层细胞分化的分子轨迹&#xff08;文章回顾&#xff1a;植物单细胞转录组 | 杨树初生生长和次生生长中形成层细胞分化的分子轨迹&#xff09;。2023年发表于《Molecular Pla…

mysql区分度不高的字段建索引一定没用吗?

建立索引的目的是提高数据库查询的性能&#xff0c;通过索引可以快速定位到符合查询条件的数据。然而&#xff0c;对于区分度不高的字段来说&#xff0c;建立索引可能会带来一些问题。 当字段的区分度很低时&#xff0c;即字段中的唯一值或不同值的数量相对较少&#xff0c;建立…

AI代码翻译神器,用AI翻译代码,轻松学习不同编程语言,已开源!

体验地址&#xff0c;github地址和部署地址在文章底部 AI代码翻译器的优势 近年来&#xff0c;随着技术的快速进步&#xff0c;人工智能技术展现出了在各个领域发挥作用的巨大潜力。AI代码翻译器作为一项创新技术&#xff0c;为开发者带来了全新的可能性。这项技术运用人工智…

FreeSWITCH 1.10 源码阅读(7)-uuid_bridge 命令原理解析

文章目录 1. uuid_bridge 命令执行2. 源码分析3. uuid_bridge 问题处理 1. uuid_bridge 命令执行 uuid_bridge 命令用于将两条腿桥接在一起&#xff0c;以实现双方的通话。下图是该命令在 FreeSWITCH 中的处理流程&#xff0c;大致的流程可以分成以下几个步骤&#xff1a; uui…