芝法酱学习笔记(0.4)——SpringBoot多模块项目打包,resource分离,lib分离,启动脚本

news2024/11/17 17:49:10

前言

上期讲了如何在windows平台搭建Java后端的开发环境,并给出了一个简单的hello world级别的多模块代码示例。但上期仅仅是在IDEA中运行,和正式的生产环境完全不同。
本期将讲解,如何配置SpringBoot多模块项目的maven打包,并分离出lib和resource。

真实的项目,不可能是运行在IDEA里的。实际的生产,一般有两种模式。一则把写好的项目打包成Jar包,通过命令启动jar包;另一种则是把项目打包成一个docker镜像,使用镜像启动。我们这里先讨论Jar包启动的情况。

一、打包配置

1.1 默认情况

我们直接在根目录点击package,会在各自模块生成一个target的文件夹,里面就有我们打包好的包。
在这里插入图片描述
我们随便找一个包,打开看看,会发现我们打的包异常的小,只有几十k。
拿我们的主业务模块general-test来说,包只包含3个模块,我们的代码,maven相关配置以及静态资源。application.yml放在最外层。
在这里插入图片描述
毫无疑问,这样的包是无法直接通过java -jar命令运行的。

1.2 springboot 打包插件

在根pom中,添加打包插件的版本引用

<build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>${spring-boot.version}</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

而后,在general-test的pom下,添加如下内容

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

再次clean,package后,观察现象。我们首先可以看到,包的大小已经正常了
在这里插入图片描述
使用winRar打开,可以发现如下目录
在这里插入图片描述
org中,放了SpringFramework的相关内容,
META-INF放了maven的pom引用以及jar包服务信息
BOOT-INF下结构如下
在这里插入图片描述
lib放置了项目引用需要的包,包括自己写的core-common,core-enum-memo
而classes下,则放着本包的代码。
我们在打好包的位置,单击右键,打开命令行。
java -jar general-test-1.0.0.jar
即可启动服务器。
如果出现找不到favicon.ico的错误,可以在resources/static下放一个你喜欢的美少女头像,记得转成ico格式哦。

1.3 资源和配置文件的分离

2.2这样做,我们就会发现一个问题,配置文件被打到jar包里,运维人员无法轻易的修改配置文件。那样,配置文件的意义在哪里呢?还不如直接写到Java文件里。
在生产上,一般有2种做法。一种是使用配置中心,不过这要整上一套SpringCloud的东西(当然用K8S也可以实现)。我们这里讲一个简单的方法,通过修改打包方式来解决。

首先,在Resource中,把想要分离的文件拷出去:

<build>
        <resources>
            <!--打包时,把这些文件拷贝到外面-->
            <resource>
                <directory>src/main/java/indi/zhifa/study2024/class002/busy/generalTest/business/report</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <targetPath>${project.build.directory}/resources/mybatis</targetPath>
            </resource>
            <resource>
                <directory>src/main/resources/static</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
                <targetPath>${project.build.directory}/resources/static</targetPath>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>*.yml</include>
                    <include>*.properties</include>
                </includes>
                <targetPath>${project.build.directory}/config</targetPath>
            </resource>

            <!--打包时,为了idea能启动,还要向classes里拷贝一份-->

            <resource>
                <directory>src/main/java/indi/zhifa/study2024/class002/busy/generalTest/business/report</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <targetPath>${project.build.directory}/classes/mybatis</targetPath>
            </resource>
            <resource>
                <directory>src/main/resources/static</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
                <targetPath>${project.build.directory}/classes/static</targetPath>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>*.yml</include>
                    <include>*.properties</include>
                </includes>
                <targetPath>${project.build.directory}/classes</targetPath>
            </resource>
        </resources>
        ......
 </build>

这样打包已经实现了需求,但把包解压开后发现,资源仍然存在于包中(相当于浪费了空间)
那,我们再加个打包的配置,排除这些文件

<build>
	<plugins>
		<plugin>
        	<groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
            	<finalName>${jar-name}</finalName><!--主义properties里定义该变量,打包后jar包的名字-->
                <!--排除掉配置,资源等,毕竟放到外面了-->
                <excludes>
                        <exclude>*.yml</exclude>
                        <exclude>*.properties</exclude>
                        <exclude>mybatis/**/*.xml</exclude>
                        <exclude>static/**/*</exclude>
                        <exclude>templates/**/*</exclude>
                    </excludes>
                </configuration>
            </plugin>
            <!--把${jar-name}包再打进包含springframework的包中-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <finalName>${jar-name}</finalName>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
	</plugins>
</build>

如此,我们再点击package,打包出的内容就会如图所示:
在这里插入图片描述

1.4 启动jar包

把jar包,config文件夹,resources文件夹站到linux系统的相应位置,我这里是/WORK/APP/study2024-class003
在这里插入图片描述

打开8080~8089的防火墙

ufw allow 8080/tcp
...

输入启动命令

java -jar nbr.jar --spring.config.additional-location=config/ study2024-class003-001

可以看出,程序启动成功了。
访问192.168.0.64/doc.html,即可看到swagger页面,查询一个报表接口,发现没有问题。

1.5 把lib包分离

其实有一说一,把lib包分离在实际的生产中,意义其实没有那么大。唯一的作用就是在公司的测试部署机放在外网,减少打包部署的带宽消耗。但这也会造个坑,就是当我们升级包时,可能会忘记把更新的包拷过去,导致莫名其妙的报错,这非常搞心态。
pom做如下修改:

	<plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <finalName>${jar-name}</finalName>
                    <addResources>true</addResources>
                    <includes>
                        <include>
                            <groupId>nothing</groupId>
                            <artifactId>nothing</artifactId>
                        </include>
                    </includes>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <finalName>${jar-name}</finalName>
                    <archive>
                        <!-- 指定资源文件目录,与打包的jar文件同级目录 -->
                        <manifestEntries>
                            <Class-Path>resources/</Class-Path>
                        </manifestEntries>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                        </manifest>
                    </archive>
                    <!--排除掉配置,资源等,毕竟放到外面了-->
                    <excludes>
                        <exclude>*.yml</exclude>
                        <exclude>*.properties</exclude>
                        <exclude>mybatis/**/*.xml</exclude>
                        <exclude>static/**/*</exclude>
                        <exclude>templates/**/*</exclude>
                    </excludes>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/lib/</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>

再进行打包,观察现象
在这里插入图片描述
我们看到,我们的包重新变小了。
把新打的包重新拷到相应的地方。而后再输入如下命令:

java -jar nbr.jar -D loader.path=./lib --spring.config.additional-location=config/ --logging.config=config/logback.xml study2024-class003-001

发现毫无问题。

二、部署环境

2.1 通常的4种环境

不考虑那种有中台的千人大厂情况,一般开发团队,通常会有4套部署环境。

  • local
    本地开发环境,即IDEA的环境,用户个人调试
  • dev
    开发环境,部署在公司内部的开发服务器中,用于前后端联调。该分支服务通常不稳定,经常发生代码变更。
    更严谨点的做法,dev也可以认为是一个测试环境,公司内部服务器部署dev,dev-feature1,dev-feature2…feature表示某个新增功能,通常有1个或几个程序员共同开发。测试先测试通过feature分支,而后把feature合并到dev上。当测试发现dev上有bug,则即刻要求开发进行修复,拉取部署bugfix分支,交由测试测试通过后,合并到dev分支上。
    但测试的最终验收,以test分支为主。
    dev环境下所用的数据库等中间件地址,很多时候是与我们本地开发不同的。但有时候为了方便,也采用相同的数据。
  • test
    测试环境,部署在公司内部的测试服务器中,也可以直接部署在外网的云服务器上。该服务用于交付测试,代码不经常变动。测试通过后打tag,可发到线上环境。
    该环境的数据库等中间件,与dev环境也不同。
    个人观点,这个环境下的数据,不要让开发人员污染。放有意义的测试数据。最好由专业的测试人员提供录入。
  • prod
    线上部署环境。通常,线上环境所用的数据库等中间件,与测试环境也是不同的。

2.2 profile配置

正因为不同的环境,可能有不同的配置。打包时要自动区分这点,所以通常会在pom文件中声明这4种环境。
由于我们这里是学习配置,只保留local和test,local表示在IDEA里跑,test表示放linux机器上(没linux的可以用WSL,我前面的文章介绍过)

<profiles>
        <!--本地-->
        <profile>
            <id>local</id>
            <properties>
                <!-- 环境标识,需要与配置文件的名称相对应 -->
                <spring.profiles.active>local</spring.profiles.active>
            </properties>
            <activation>
                <!-- 默认环境 -->
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <!--测试-->
        <profile>
            <id>test</id>
            <properties>
                <spring.profiles.active>test</spring.profiles.active>
            </properties>
        </profile>
    </profiles>

2.3 把先前的yml配置文件和日志xml分环境

我们现在把这种配置文件这样
在这里插入图片描述
为了能够正常运行,以及把对应文件拷到外面的config文件夹中,xml可以做如下配置

			<resource>
                <directory>src/main/config/${spring.profiles.active}</directory>
                <includes>
                    <include>*.yml</include>
                    <include>*.properties</include>
                    <include>logback.xml</include>
                </includes>
                <targetPath>${project.build.directory}/config</targetPath>
            </resource>

			<resource>
                <directory>src/main/config/${spring.profiles.active}</directory>
                <includes>
                    <include>*.yml</include>
                    <include>*.properties</include>
                    <include>logback.xml</include>
                </includes>
                <targetPath>${project.build.directory}/classes</targetPath>
            </resource>

点击compile,观察现象
在这里插入图片描述
我想,这样就实现了

三、maven打包命令

实际开发时,可不会在IDEA里打包,而是在jenkins中,在linux下使用命令打包。
我们先在windows中尝试一下:

mvn clean package -pl busy/general-test -am -Ptest

嗯,这就成功了。

四、创建一个启动和关闭脚本

实际开发中,我们不可能用java -jar来启动服务。另外,同一个jar包,可能会部署多个实例。这时,我们可以写一个shell脚本来做启动和关闭。
在如图位置创建这俩脚本
在这里插入图片描述
在resource的配置中,添加拷贝脚本的配置

            <resource>
                <directory>src/main/bin/${spring.profiles.active}</directory>
                <includes>
                    <include>*.sh</include>
                    <include>*.bat</include>
                </includes>
                <targetPath>${project.build.directory}/bin</targetPath>
            </resource>

4.1 启动脚本startup.sh

#!/bin/bash

cygwin=false
darwin=false
os400=false
case "`uname`" in
CYGWIN*) cygwin=true;;
Darwin*) darwin=true;;
OS400*) os400=true;;
esac
error_exit ()
{
    echo "ERROR: $1 !!"
    exit 1
}

#参数解析
VERSION=''
appName=''
PORT='8081'
ARGS=`getopt -o v:a:p: --long version:,appName:,port: -n "$0" -- "$@"`
if [ $? != 0 ]; then
    echo "Terminating..."
    exit 1
fi
echo ARGS=[$ARGS]
eval set -- "${ARGS}"

while true
do
    case "$1" in
        -v|--version)
            case "$2" in
              "")
                VERSION=''
                shift 1;
                ;;
              *)
                VERSION=$2
                shift 2;
                ;;
             esac
            ;;
        -a|--appName)
            case "$2" in
              "")
                 appName='main'
                 shift 1;
                 ;;
              *)
                appName=$2
                shift 2;
                ;;
            esac
            ;;
        -p|--port)
          case "$2" in
            "")
               PORT='8081'
               shift 1;
               ;;
           *)
               PORT=$2
               shift 2;
               ;;
             esac
             ;;
        --) shift ; break ;;
        *) echo "Internal error!" ; exit 1 ;;
    esac
done



SERVER="nbr"
if [[ -z "$VERSION" ]]; then
    SERVER_JAR="$SERVER.jar"
else
    SERVER_JAR="$SERVER-$VERSION.jar"
fi

SPACE="study2024"
SERV_NAME="general-test"
PROFILE="test"

which java
JAVA="$JAVA_HOME/bin/java"
echo $JAVA

BASE_DIR=`cd $(dirname $0)/..; pwd`
CUSTOM_SEARCH_LOCATIONS=file:${BASE_DIR}/config/

#===========================================================================================
# JVM Configuration
#===========================================================================================
#JAVA_OPT="${JAVA_OPT} -Xms512m -Xmx512m -Xss128k -XX:MaxGCPauseMillis=300 -Xlog:gc:../logs/gc.log"
JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}"
JAVA_OPT="${JAVA_OPT} -jar ${BASE_DIR}/${SERVER_JAR}"
JAVA_OPT="${JAVA_OPT} -D loader.path=./lib"
JAVA_OPT="${JAVA_OPT} --spring.profiles.active=${PROFILE}"
JAVA_OPT="${JAVA_OPT} --server.port=${PORT}"
JAVA_OPT="${JAVA_OPT} --spring.config.additional-location=${CUSTOM_SEARCH_LOCATIONS}"
JAVA_OPT="${JAVA_OPT} --logging.config=${BASE_DIR}/config/logback.xml"


JAVA_MAJOR_VERSION=$($JAVA -version 2>&1 | sed -E -n 's/.* version "([0-9]*).*$/\1/p')


if [ ! -d "${BASE_DIR}/logs" ]; then
  mkdir ${BASE_DIR}/logs
fi

echo "$JAVA ${JAVA_OPT}"


# start
echo "$JAVA ${JAVA_OPT}" > ${BASE_DIR}/logs/start.out 2>&1 &
nohup $JAVA ${JAVA_OPT} ${SPACE}.${SERV_NAME}-${appName} >> ${BASE_DIR}/logs/start.out 2>&1 &
echo "${SPACE}.${SERV_NAME}-${appName} is starting,you can check the ${BASE_DIR}/logs/start.out"
echo $! > pid.txt

4.2 关闭脚本shutdown.sh

#!/bin/bash

SPACE="study2024"
SERV_NAME="general-test"
PROFILE="test"

#参数解析
appName='app001'
ARGS=`getopt -o a: --long appName: -n "$0" -- "$@"`
if [ $? != 0 ]; then
    echo "Terminating..."
    exit 1
fi
#echo ARGS=[$ARGS]
eval set -- "${ARGS}"
#echo formatted parameters=[$@]

while true
do
    case "$1" in
        -a|--appName)
            case "$2" in
              "")
                 appName='main'
                 shift 1;
                 ;;
              *)
                appName=$2
                shift 2;
                ;;
            esac
            ;;
        --) shift ; break ;;
        *) echo "Internal error!" ; exit 1 ;;
    esac
done

#cd `dirname $0`/..
target_dir=`pwd`

pid=$(cat "$target_dir/pid.txt")

if [[ -z "$pid" ]]; then
  pid=`ps ax | grep -i "$SPACE.$SERV_NAME-${appName}" | grep ${target_dir} | grep java | grep -v grep | awk '{print $1}'`
fi

if [ -z "$pid" ] ; then
        echo "No $SPACE.$SERV_NAME-${appName} running."
        exit 0;
fi

rm pid.txt

echo "The ${SPACE}.${SERV_NAME}-${appName}(${pid}) is running..."
kill ${pid}
echo "Send shutdown request to ${SPACE}.${SERV_NAME}-${appName}(${pid}) OK"

4.3 启动关闭实验

把该脚本拖到linux,如图所示
在这里插入图片描述
cd进bin中,把这俩脚本赋予可执行权限

cd bin
chmod +x startup.sh
chmod +x shutdown.sh

启动命令

./startup -p 8083

查看是否启动成功

lsof -i:8083

在这里插入图片描述
可见,程序启动成功了。
关闭程序

./shutdown.sh

再次查看是否进程还在

lsof -i:8083

观察到已经没有。

五、代码展示

不多讲,还是移步我的码云吧

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

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

相关文章

Ubuntu22.04安装VMware Tools

目录 1. 问题2. 在线安装2.1. 更新软件源列表2.2. 更新软件2.3. 下载安装 open-vm-tools-desktop 3. 网络配置3.1 配置网络连接模式3.2 配置静态IP3.3 配置应用3.4 检查IP 1. 问题 安装好 Ubuntu 系统后&#xff0c;想要适配桌面大小等其它功能就需要安装 VMware Tools 这个工…

Linux 文件 IO 管理(第三讲:文件系统)

Linux 文件 IO 管理&#xff08;第三讲&#xff1a;文件系统&#xff09; 进程为什么默认要打开文件描述符为 0&#xff0c;1 和 2 的文件呢&#xff1f;文件系统物理磁盘简单认识存储结构对磁盘存储进行逻辑抽象分组 —— 文件系统Block Bitmapinode Tableinode BitmapGDT(Gro…

Android 利用OSMdroid开发GIS

1、地址 Github地址&#xff1a;https://gitee.com/mirrors/osmdroid Git地址&#xff1a; GitCode - 全球开发者的开源社区,开源代码托管平台 Git下载包地址&#xff1a;Releases osmdroid/osmdroid GitHub 新建项目 osmdroid在线&#xff1a; &#xff08;1&#xff09…

将Mixamo的模型和动画导入UE5

首先进入Mixamo的官网 , 点击 Character 选择一个模型 (当然你也可以自己上传模型/绑定动画) 然后点击下载 , 这个作为带骨骼的模型 选择FBX格式 , T Pose 直接下载 点击 Animations 选择动画 , 搜索 idle 默认站立动画 点击下载 , 格式选择 FBX , 不带模型只要骨骼 , 帧数选6…

低功耗TF卡:录音笔、领夹麦、电池门铃优选

概述 TF卡&#xff0c;也称为Micro SD卡或TransFlash卡&#xff0c;是一种流行的小型存储卡&#xff0c;广泛应用于手机、平板电脑、相机和其他便携式设备。TF卡的尺寸非常小&#xff0c;便于携带和使用&#xff0c;不会占用太多设备空间。而且TF卡提供多种容量选择&#xff0…

Go基础编程 - 15 - 延迟调用(defer)

延迟调用 defer 1. 特性2. 常用用途3. defer 执行顺序&#xff1a;同函数内先进后出4. defer 闭包5. defer 陷阱 上一篇&#xff1a;泛型 1. 特性 1. 关键字 defer 用于注册延迟调用。 2. defer 调用直到 return 前才被执行。 3. 同函数内多个 defer 语句&#xff0c;按先进后…

第17章 协同式任务切换

第17章 协同式任务切换 在多任务系统中&#xff0c;每个任务都有各自的局部描述符表(LDT)和任务状态段(TSS)。 从任务切换的时机来讲&#xff0c;有两种基本的策略&#xff1a; 协同式&#xff1a;从一个任务切换到另一个任务。需要当前任务主动地请求暂时放弃执行权&#x…

好看的首页展示

代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>/* RESET…

气膜游泳馆:舒适恒温,寒冷季节中的理想游泳场所—轻空间

随着天气逐渐转凉&#xff0c;许多人在秋冬季节减少了户外活动&#xff0c;尤其是游泳。然而&#xff0c;气膜游泳馆为您提供了一种全新的选择&#xff0c;让您即使在寒冷的季节&#xff0c;也能享受畅游的乐趣。凭借其独特的恒温设计和舒适的环境&#xff0c;气膜游泳馆成为了…

计算机毕业设计宠物领养网站我的发布领养领养用户信息/springboot/javaWEB/J2EE/MYSQL数据库/vue前后分离小程序

目录 1.课题背景 2.课题意义 ‌ 3.技术介绍 4.技术性需求 4.1后端服务‌&#xff1a; 4.2 前端展示‌ 5.数据库设计‌&#xff1a; 6.系统性能‌&#xff1a; 7.安全性‌&#xff1a; 8. 功能介绍&#xff1a; 9. 部分代码 1.课题背景 近年来&#xff0c;随着宠物饲养数量…

TDEngine在煤矿综采管控平台中的应用

一、行业背景 智能综采管控平台&#xff0c;是将煤矿综采工作面传感器数据采集&#xff0c;通过可视化界面展示。实现综采工作面的透明化展示&#xff0c;并基于历史的传感器数据进行机器学习的训练&#xff0c;了解工作面周期来压&#xff0c;设备故障检测等数据应用。因此针…

AIGC引领数智未来:企业架构演进的深度解析与实践路径,The Open Group 2024生态系统架构·可持续发展年度大会专题报道

随着人工智能技术的迅猛发展&#xff0c;特别是以ChatGPT、Sora等为代表的AIGC&#xff08;人工智能生成内容&#xff09;技术的爆发&#xff0c;我们正处于通用人工智能&#xff08;AGI&#xff09;时代的前夜。AIGC技术在多个领域展现出近乎甚至超越人类的能力&#xff0c;已…

【LeetCode】动态规划—最小路径和(附完整Python/C++代码)

动态规划—64. 最小路径和 前言题目描述基本思路1. 问题定义:2. 理解问题和递推关系:3. 解决方法:3.1. 初始化:3.2. 边界条件:3.3. 填充 dp 数组:3.4. 返回结果: 4. 进一步优化:5. 小总结: 代码实现Python3代码实现Python 代码解释C代码实现C 代码解释 总结: 前言 给定一个包含…

liunx系统虚拟机

https://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/ 下载地址 DVD版本 安装vm软件12通过vm软件来创建一个虚拟机空间通过vm软件在创建好的虚拟机空间上&#xff0c;安装我们的centos操作系统使用centos你得需要将鼠标点击进入界面中&#xff0c;但是鼠标会消失&#xf…

杨辉三角-C语言

1.问题&#xff1a; 输出杨辉三角。 2.解答&#xff1a; 对有特点的数&#xff08;每行开头和结束的数都是1&#xff09;进行赋值&#xff0c;给中间的数进行赋值&#xff0c;把上面赋值后的二维数组&#xff0c;遍历输出。 3.代码&#xff1a; #include<stdio.h>//头…

基于SSM商铺租赁系统JAVA|VUE|SSM计算机毕业设计源代码+数据库+LW文档+开题报告+答辩稿+部署教+代码讲解

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿 部署教程代码讲解代码时间修改教程 一、开发工具、运行环境、开发技术 开发工具 1、操作系统&#xff1a;Window操作系统 2、开发工具&#xff1a;IntelliJ IDEA或者Eclipse 3、数据库存储&#xff1a…

使用session来实现验证码发送功能

一、什么是session&#xff1f; Session由服务器创建&#xff0c;并为每一次会话分配一个Session对象。同一个浏览器发起的多次请求&#xff0c;同属于一次会话&#xff08;Session&#xff09;。首次使用到Session时&#xff0c;服务器会自动创建Session&#xff0c;并创建Co…

大觅网之自动化部署(Automated Deployment of Da Mi Network)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…

前端大模型入门:Transformer.js 和 Xenova-引领浏览器端的机器学习变革

除了调用别人的api接口使用transformer技术&#xff0c;你是否想过将大模型在浏览器中运行呢&#xff1f;尤其是WebGPU的出现&#xff0c;性能比WebGL高不少&#xff0c;很多小任务真的不再需要在一个中心运行了。 不少同学买课学python了&#xff0c;但我还是在坚持用js尝试&a…

【Linux实践】实验九:Shell流程控制语句

【Linux实践】实验九&#xff1a;Shell流程控制语句 实验目的实验内容实验步骤及结果1. 变量的定义和使用2. 条件3. 运算4. if 语句5. case 语句6. for 语句7. while 语句8. until 语句9. 遍历复制10. 计算平方 实验目的 1、掌握条件判断语句&#xff0c;如if语句、case语句。…