打包部署也这么内卷--springboot项目的打包及一键服务器部署

2023-11-06

一、环境准备

1.cenos7服务器一台
2.更换yum源 
    yum install -y wget
    mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
    wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
    yum -y install  epel-release
    rm -rf /etc/yum.repos.d/epel*
    wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
    yum clean all
    yum makecache
3.安装Java
    ##安装java
    mkdir /usr/local/java
    cd /usr/local/java
    wget http://zjxianlin.com:8082/files/jdk-8u141-linux-x64.tar.gz
    tar zxvf jdk-8u141-linux-x64.tar.gz
    
    #编辑配置文件
    vi /etc/profile
    #填入以下内容
    export JAVA_HOME=/usr/local/java/jdk1.8.0_141
    export PATH=$JAVA_HOME/bin:$PATH 
    export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar 
    
    #刷新环境变量
    source /etc/profile
    #验证java是否安装成功
    java -version
4.安装docker
    ##安装docker
    yum install -y yum-utils device-mapper-persistent-data lvm2
    yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    yum install docker-ce -y
    ##启动并加入开机启动
    systemctl start docker
    systemctl enable docker
    ##验证安装是否成功
    docker version
5.安装docker-compose 
    ##安装docker-compose
    wget  -O /usr/local/bin/docker-compose   http://zjxianlin.com:8082/files/docker-compose-Linux-x86_64
    chmod +x /usr/local/bin/docker-compose
6.其它安装
   ##安装文件编码转换
   yum install -y dos2unix
7.按需安装mysql,redis,mq等开发组件
8.环境搭建完毕,如果是云服务器,请确认服务端口是否在安全组内开放。如果是虚拟机,请确认防火墙是否关闭。否则,无法远程连接。

二、部署规范

1.所有jar包,tar包服务部署在/opt目录下,以目标客户对象分组。如:仙林版本管理服务,仙林文件管理服务部署如下:
    /opt/shining/shining-version-starter/shining-version-starter.jar       (jar包)
    /opt/shining/shining-file-starter/       (tar包)
    面向千琪无印系列的的项目部署目录如下:
    /opt/wy/wylp/      (tar包)
    面向盈狐云系列的项目部署目录如下:
    /opt/yh/yh-customer/yh-customer.jar    (jar包)
    
2.所有docker-compose文件放在/usr/local/docker-run/enable/目录下

3.项目目录规范
                      模块根目录
                                ├─bin   启停脚本文件
                                ├─deploy  部署文件
                                │  ├─docker-compose
                                │  └─sh
                                ├─install  打包文件
                                ├─src  源码目录
                                └─target 打包结果目录

三、服务打包

Java服务打包成可运行程序的形式有很多种,且都依赖于maven或者gradle:
    这里介绍maven的三种:
        1.springboot jar包
        2.依赖配置分离的tar包
        3.docker形式
ps:在以下脚本中 SERVICE_NAME为项目启动类所在模块的artifactId

(一).springboot-jar包

1.在服务Application启动类所在模块的根路径建立以下文件:
    bin/jar-service.sh (服务启停文件)
    deploy/sh/deploy-jar.sh (服务部署脚本)
    install/assembly-jar.xml (项目打包配置)
2.jar-service.sh(模板)
    #!/bin/sh
    # --------------------声明 start--------------------------------------
    # jar包部署后专用启动、停止、重启脚本
    # 使用方式 sh jar-service.sh start, sh jar-service.sh stop ,sh jar-service.sh restart
    # 该shell脚本文件在项目的的存放位置-${project.basedir}/bin
    # ${project.basedir}为springboot项目Application启动类所在模块的根目录
    # 在该文件目录下的../install/assembly-jar.xml会扫描该文件并将该文件加入部署包
    # --------------------声明 end----------------------------------------
    #
    #
    #----------------------- 不同项目需要修改的部分 start--------------------
    # 服务名称
    # springboot项目请修改为Application启动类所在模块的artifactId
    SERVICE_NAME="wy-start-service"
    # 服务部署目录
    DEPLOY_PATH="/opt/wy"
    # gc日志文件目录
    # 建议项目中logback.xml配置的目录相同
    GCLogHome="/var/logs/wy/wy-start-service"
    #----------------------- 不同项目需要修改的部分 end---------------------
    #
    ##
    echo "服务名称:$SERVICE_NAME"
    echo "文件所在目录:$DEPLOY_PATH"
    echo "GC日志目录:$GCLogHome"
    GCCommand="-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintHeapAtGC     -XX:+PrintReferenceGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintSafepointStatistics     -XX:PrintSafepointStatisticsCount=1 -Xloggc:$GCLogHome/gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=14     -XX:GCLogFileSize=100M"
    # shellcheck disable=SC1009
    # shellcheck disable=SC2112
    function startService() {
      # shellcheck disable=SC2061
      FIND_JAR_CMD="find $DEPLOY_PATH/$SERVICE_NAME/ -maxdepth 1 -name '$SERVICE_NAME*.jar'|grep -v   $SERVICE_NAME*sources.jar "
      echo "判断$DEPLOY_PATH/$SERVICE_NAME/路径下是否存在执行jar包"
      echo "$FIND_JAR_CMD"
      service_jar_path=$(eval $FIND_JAR_CMD)
      # shellcheck disable=SC2236
      if  [ ! $service_jar_path ] ;then
        echo "$DEPLOY_PATH/$SERVICE_NAME/下没有找到执行jar包"
      else
          echo "找到jar包,路径为:$service_jar_path"
          if [ ! -n "${MY_JAVA_OPTS}" ]; then
            START_CMD="nohup java -jar $GCCommand $service_jar_path >/dev/null 2>&1 &"
            echo "没有找到JVM参数,无参启动:$START_CMD"
            eval $START_CMD
          else
            START_CMD="nohup java ${MY_JAVA_OPTS} -jar $GCCommand $service_jar_path >/dev/null 2>&1 &"
            echo "jvm参数:${MY_JAVA_OPTS},开始启动:$START_CMD"
            eval $START_CMD
          fi
      fi
      # shellcheck disable=SC2152
      return 1
    }
    
    # shellcheck disable=SC2112
    function stopService() {
      # shellcheck disable=SC2009
      service_process=$(ps -ef | grep "$SERVICE_NAME" | grep -v grep | grep .jar | grep java | awk '{print $2}')
      # shellcheck disable=SC2236
      if [ ! -n "$service_process" ]; then
        echo '没有找到进程'
      else
        echo "进程号为:$service_process"
        echo "开始kill..."
        kill -9 "$service_process"
      fi
      return 1
    }
    
    # jar包部署专用启动、停止、重启脚本
    echo "服务名称:$SERVICE_NAME"
    command_line=$1
    # shellcheck disable=SC2236
    if [ ! -n "$command_line" ]; then
      echo "请输入要执行的动作:start stop restart"
    elif [ "$command_line" = "start" ]; then
      echo "开始启动服务$SERVICE_NAME"
      startService
    elif [ "$command_line" = "stop" ]; then
      echo "开始停止服务$SERVICE_NAME"
      stopService
    elif [ "$command_line" = "restart" ]; then
      echo "开始重启服务$SERVICE_NAME"
      stopService
      startService
    fi
    exit 0
3.deploy-jar.sh(模板)
    #!/bin/sh
    # --------------------声明 start--------------------------------------
    # jar包形式部署时专用
    # 使用方式 sh deploy-jar.sh
    # ${project.basedir}为springboot项目Application启动类所在模块的根目录
    # 该shell脚本文件在项目的的存放位置-${project.basedir}/deploy/sh
    # 在该位置下的../../install/assembly-jar.xml会扫描该文件并将该文件加入部署包
    # --------------------声明 end----------------------------------------
    #
    #----------------------- 不同项目需要修改的部分 start--------------------
    # 服务名称
    # springboot项目请修改为Application启动类所在模块的artifactId
    SERVICE_NAME="wy-start-service"
    # 部署目录
    # jar包形式默认部署在/opt目录且已目标客户或者业务线区分如/wy,/shining
    DEPLOY_PATH="/opt/wy"
    #----------------------- 不同项目需要修改的部分 end--------------------
    #
    ##
    echo "要部署的服务名称:$SERVICE_NAME"
    echo "要部署的目标目录:$DEPLOY_PATH"
    currentPath=$(cd ./; pwd)
    echo "当前目录:$currentPath"
    echo "部署开始..."
    serviceBasePath="$DEPLOY_PATH/$SERVICE_NAME"
    if [ ! -d "$serviceBasePath" ]; then
      mkdir -p $serviceBasePath
    fi
    echo "固定部署目录为$serviceBasePath"
    # shellcheck disable=SC1009
    if  [[$currentPath -ef $serviceBasePath ]] ;then
      echo "当前目录就是部署目录,直接启动"
    else
      CLEAR_CMD="rm -rf $serviceBasePath/*"
      CP_CMD="cp -rf $currentPath/* $serviceBasePath/"
      echo "当前目录不是部署目录,开始迁移:"
      echo $CLEAR_CMD
      echo $CP_CMD
      eval $CLEAR_CMD
      eval $CP_CMD
    fi
    DOS2UNIX="dos2unix $DEPLOY_PATH/$SERVICE_NAME/*.sh"
    echo "服务部署完毕,开始脚本编码转换:$DOS2UNIX"
    eval $DOS2UNIX
    START_CMD="nohup sh $DEPLOY_PATH/$SERVICE_NAME/jar-service.sh restart >/dev/null 2>&1 &"
    echo "开始启动:$START_CMD"
    eval $START_CMD
    exit 0
4.assembly-jar.xml
    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2   http://maven.apache.org/xsd/assembly-1.1.2.xsd
    http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 ">
      <id>jar-deploy</id><!--id 标识符,添加到生成文件名称的后缀符。可以不指定-->
    
      <formats>
        <!--打包方式,支持写多个包括(zip、tar、tar.gz (or tgz)、tar.bz2 (or tbz2)、jar、dir、war)-->
        <format>zip</format>
      </formats>
      <includeBaseDirectory>true</includeBaseDirectory>
      <fileSets>
        <!--获取启动jar包-->
        <fileSet>
          <directory>${project.basedir}/target</directory>
          <includes>
            <include>${project.artifactId}-${project.version}.jar</include>
          </includes>
          <outputDirectory>./</outputDirectory>
        </fileSet>
        <!--获取启动脚本-->
        <fileSet>
          <directory>${project.basedir}/bin</directory>
          <includes>
            <include>jar-service.sh</include>
          </includes>
          <outputDirectory>./</outputDirectory>
        </fileSet>
        <!--获取部署脚本-->
        <fileSet>
          <directory>${project.basedir}/deploy/sh</directory>
          <includes>
            <include>deploy-jar.sh</include>
          </includes>
          <outputDirectory>./</outputDirectory>
        </fileSet>
      </fileSets>
    </assembly>
6.修改Application类所在模块的pom.xml
<properties>
    <mainClass>你的Application启动类的全限定名</mainClass>
</properties>
<build>
    <resources>
      <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties,.xml文件都会扫描到-->
          <include>**/*</include>
        </includes>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <includes><!--包括目录下的.properties,.xml文件都会扫描到-->
          <include>**/*</include>
        </includes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <mainClass>${mainClass}</mainClass>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>repackage</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <executions>
          <execution>
            <id>make-dir</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
            <configuration>
              <finalName>${project.artifactId}</finalName>
              <descriptors>
                <descriptor>install/assembly-jar.xml</descriptor>
              </descriptors>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
7.开始打包
然后运行mvn clean package 
之后 在服务Application启动类所在模块的target目录下就可以找到相应的zip包
上传至服务器unzip ***.zip
然后进入解压目录
dos2unix *.sh
sh deploy-jar.sh
项目则会开始自动部署启动

其它命名:
sh jar-service.sh start 
sh jar-service.sh stop
sh jar-service.sh restart

(二).依赖配置分离的tar包

1.在服务Application启动类所在模块的根路径建立以下文件:
bin/tar-service.sh (服务启停文件)
deploy/sh/deploy-tar.sh (服务部署脚本)
install/assembly-tar.xml (项目打包配置)
2.tar-service.sh(模板)
    #!/bin/sh
    # --------------------声明 start--------------------------------------
    # tar包部署后专用启动、停止、重启脚本
    # 使用方式 sh tar-service.sh start, sh tar-service.sh stop ,sh tar-service.sh restart
    # 该shell脚本文件在项目的的存放位置-${project.basedir}/bin
    # ${project.basedir}为springboot项目Application启动类所在模块的根目录
    # 在该文件目录下的../install/assembly-tar.xml会扫描该文件并将该文件加入部署包
    # --------------------声明 end----------------------------------------
    #
    #
    #----------------------- 不同项目需要修改的部分 start--------------------
    # 服务名称
    # springboot项目请修改为Application启动类所在模块的artifactId
    SERVICE_NAME="wy-start-service"
    # 服务部署目录
    DEPLOY_PATH="/opt/wy"
    # gc日志文件目录
    # 建议项目中logback.xml配置的目录相同
    GCLogHome="/var/logs/wy/wy-start-service"
    #----------------------- 不同项目需要修改的部分 end---------------------
    #
    ##
    echo "服务名称:$SERVICE_NAME"
    echo "文件所在目录:$DEPLOY_PATH"
    echo "GC日志目录:$GCLogHome"
    GCCommand="-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintHeapAtGC     -XX:+PrintReferenceGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintSafepointStatistics     -XX:PrintSafepointStatisticsCount=1 -Xloggc:$GCLogHome/gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=14     -XX:GCLogFileSize=100M"
    # shellcheck disable=SC1009
    # shellcheck disable=SC2112
    function startService() {
      # shellcheck disable=SC2061
      FIND_JAR_CMD="find $DEPLOY_PATH/$SERVICE_NAME/ -name '$SERVICE_NAME*.jar'|grep -v $SERVICE_NAME*sources.jar "
      echo "判断$DEPLOY_PATH/$SERVICE_NAME/路径下是否存在执行jar包"
      echo "$FIND_JAR_CMD"
      service_jar_path=$(eval $FIND_JAR_CMD)
      # shellcheck disable=SC2236
      if [ ! $service_jar_path ]; then
        echo "$DEPLOY_PATH/$SERVICE_NAME/下没有找到执行jar包"
      else
        echo "找到jar包,路径为:$service_jar_path"
        if [ ! -n "${MY_JAVA_OPTS}" ]; then
          START_CMD="java -jar $GCCommand $service_jar_path"
          echo "没有找到JVM参数,无参启动:$START_CMD"
          eval $START_CMD
        else
          START_CMD="java ${MY_JAVA_OPTS} -jar $GCCommand $service_jar_path"
          echo "jvm参数:${MY_JAVA_OPTS},开始启动:$START_CMD"
          eval $START_CMD
        fi
      fi
      return 1
    }
    
    # shellcheck disable=SC2112
    function stopService() {
      # shellcheck disable=SC2009
      service_process=$(ps -ef | grep $SERVICE_NAME | grep -v grep | grep .jar | grep java | awk '{print $2}')
      # shellcheck disable=SC2236
      if [ ! -n "$service_process" ]; then
        echo '没有找到进程'
      else
        echo "进程号为:$service_process"
        kill -9 "$service_process"
      fi
      return 1
    }
    
    command_line=$1
    # shellcheck disable=SC2236
    if [ ! -n "$command_line" ]; then
      echo "请输入要执行的动作:start stop restart"
    elif [ "$command_line" = "start" ]; then
      echo "开始启动服务$SERVICE_NAME"
      startService
    elif [ "$command_line" = "stop" ]; then
      echo "开始停止服务$SERVICE_NAME"
      stopService
    elif [ "$command_line" = "restart" ]; then
      echo "开始重启服务$SERVICE_NAME"
      stopService
      startService
    fi
    exit 0
3.deploy-tar.sh(模板)
    #!/bin/sh
    # --------------------声明 start--------------------------------------
    # tar包形式部署时专用
    # 使用方式 sh deploy-tar.sh
    # ${project.basedir}为springboot项目Application启动类所在模块的根目录
    # 该shell脚本文件在项目的的存放位置-${project.basedir}/deploy/sh
    # 在该位置下的../../install/assembly-tar.xml会扫描该文件并将该文件加入部署包
    # --------------------声明 end----------------------------------------
    #
    #----------------------- 不同项目需要修改的部分 start--------------------
    # 服务名称
    # springboot项目请修改为Application启动类所在模块的artifactId
    SERVICE_NAME="wy-start-service"
    # 部署目录
    # tar包形式默认部署在/opt目录且已目标客户或者业务线区分如/wy,/shining
    DEPLOY_PATH="/opt/wy"
    #----------------------- 不同项目需要修改的部分 end--------------------
    #
    ##
    echo "服务名称:$SERVICE_NAME"
    serviceBasePath="$DEPLOY_PATH/$SERVICE_NAME"
    currentPath=$(pwd)
    # shellcheck disable=SC1009
    if  [ "$currentPath" = "$serviceBasePath" ] ;then
      echo "当前目录就是部署目录,直接启动"
    else
      if  [ ! -d "$DEPLOY_PATH/" ] ; then
        mkdir -p "$DEPLOY_PATH/"
      fi
      if  [ ! -d "$serviceBasePath" ] ; then
        echo "目录不存在,开始新建:$serviceBasePath"
        mkdir -p "$serviceBasePath"
      fi
      CLEAR_CMD="rm -rf $serviceBasePath/*"
      CP_CMD="cp -rf $currentPath/* $serviceBasePath/"
      echo "当前目录不是部署目录,开始迁移:"
      echo $CLEAR_CMD
      echo $CP_CMD
      eval $CLEAR_CMD
      eval $CP_CMD
    fi
    DOS2UNIX="dos2unix $DEPLOY_PATH/$SERVICE_NAME/bin/*.sh"
    echo "服务部署完毕,开始脚本编码转换:$DOS2UNIX"
    eval $DOS2UNIX
    START_CMD="nohup sh $DEPLOY_PATH/$SERVICE_NAME/bin/tar-service.sh restart >/dev/null 2>&1 &"
    echo "开始启动:$START_CMD"
    eval $START_CMD
    exit 0
4.assembly-tar.xml
    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2   http://maven.apache.org/xsd/assembly-1.1.2.xsd
    http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 ">
      <id>${project.version}</id><!--id 标识符,添加到生成文件名称的后缀符。可以不指定-->
    
      <formats>
        <!--打包方式,支持写多个包括(zip、tar、tar.gz (or tgz)、tar.bz2 (or tbz2)、jar、dir、war)-->
        <format>tar.gz</format>
      </formats>
      <includeBaseDirectory>true</includeBaseDirectory>
      <fileSets>
        <!--将所有resources文件下的文件打包在conf目录下-->
        <fileSet>
          <directory>${project.basedir}/src/main/resources</directory>
          <outputDirectory>conf</outputDirectory>
        </fileSet>
        <!--将启动脚本打包在bin目录下-->
        <fileSet>
          <directory>${project.basedir}/bin</directory>
          <includes>
            <include>*.sh</include>
          </includes>
          <outputDirectory>bin</outputDirectory>
        </fileSet>
        <!--你还可以将初始化sql文件等打包在init目录下-->
        <fileSet>
          <directory>${project.basedir}/deploy/sh</directory>
          <includes>
            <include>deploy-tar.sh</include>
          </includes>
          <outputDirectory>./</outputDirectory>
        </fileSet>
        <fileSet>
          <directory>${project.basedir}/lib</directory>
          <outputDirectory>lib</outputDirectory>
        </fileSet>
      </fileSets>
      <dependencySets>
        <dependencySet>
          <useProjectArtifact>true</useProjectArtifact>
          <outputDirectory>lib</outputDirectory>
          <!-- 将scope为runtime的依赖包打包到lib目录下。 -->
          <scope>runtime</scope>
        </dependencySet>
      </dependencySets>
    </assembly>
5.修改pom
    <properties>
        <mainClass>你的Application启动类的全限定名</mainClass>
    </properties>
    
    <build>
        <resources>
          <resource>
            <directory>src/main/java</directory><!--所在的目录-->
            <includes><!--包括目录下的.properties,.xml文件都会扫描到-->
              <include>**/*</include>
            </includes>
            <filtering>false</filtering>
          </resource>
        </resources>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <executions>
              <execution>
                <id>default-jar</id>
                <phase>package</phase>
                <goals>
                  <goal>jar</goal>
                </goals>
                <configuration>
                  <archive>
                    <manifest>
                      <mainClass>${mainClass}</mainClass>
                      <addClasspath>true</addClasspath>
                      <classpathPrefix>./</classpathPrefix>
                    </manifest>
                    <manifestEntries>
                      <Class-Path>../conf/</Class-Path>
                    </manifestEntries>
                  </archive>
                  <excludes>
                    <exclude>*</exclude>
                    <exclude>*/*</exclude>
                    <exclude>*/static</exclude>
                  </excludes>
                  <skipIfEmpty>true</skipIfEmpty>
                </configuration>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
            <configuration>
              <skip>true</skip>
            </configuration>
          </plugin>
          <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
              <execution>
                <id>make-dir</id>
                <phase>package</phase>
                <goals>
                  <goal>single</goal>
                </goals>
                <configuration>
                  <finalName>${project.artifactId}</finalName>
                  <descriptors>
                    <descriptor>install/assembly-tar.xml</descriptor>
                  </descriptors>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
6.开始打包
运行mvn clean package
之后在Application所在模块的target目录下可以找到相关的tar.gz文件
上传到服务器后 tar zxvf ***.tar.gz
进入解压目录:
dos2unix *.sh
dos2unix bin/*.sh
sh deploy-tar.sh
项目则开始自动化部署运行

其它命令:
sh tar-service.sh start
sh tar-service.sh stop
sh tar-service.sh restart

ps:依赖配置分离的好处在于:
   1、可以在外部修改配置文件或者替换单个的依赖jar包。
   2、在docker部署时可以将配置文件进行外部映射。
   3、在其它模块引用时,可以避免jar包体积过大。

(三).DockerFile部署

1.说明
DockerFile部署其实就是在打包的基础上,进行一次docker容器的封装.要求本地具备docker环境,如果本地不具备。则需要一些特殊手段。

1.ubuntu,mac以及部分windows10可以本地安装docker。

如果本地没有安装docker,则需要远程登录其它已安装的docker主机,远程操作。例如:借用本地虚拟机或者云服务器。

远程的docker主机如何开放远程端口可以见教程:https://blog.csdn.net/qq_33517844/article/details/97639230。

ps:docker-2375端口存在未授权漏洞,建议改用其它10000以上的端口,不易被发现。或者采用信任文件的形式进行校验。(虚拟机忽略该条)

操作完之后,本地主机设置环境变量:DOCKER_HOST=tcp://[远程docker服务器ip]:[远程docker开发的端口]

2.在你使用的Docker的那台服务器上登录docker镜像仓库。
    首先:
        停止docker
        
    然后:
        cenos系统: 
                vi /etc/docker/daemon.json
                
        写入以下内容:
        
                {
                 "registry-mirrors": ["https://unwchefq.mirror.aliyuncs.com"]
                }
                
                
                systemctl daemon-reload
                service docker restart
        ubuntu系统:
        
                vi /lib/systemd/system/docker.service 
                
                找到“ExecStart”这一行末尾添加:
                    --insecure-registry zjxianlin.com:41532
                    
                sudo systemctl daemon-reload
                sudo service docker restart
                
        windows10:
        
                找到:C:/Users/[当前用户]/.docker/config.json
                没有则新建一个
                
                写入以下内容:
                
                {
                	"auths": {
                		"registry.cn-hangzhou.aliyuncs.com": {}
                	},
                	"credsStore": "wincred"
                }
                
                重启电脑和docker
    最后:
         docker login **镜像仓库
         输入用户名: admin
         密码:***
2.在服务Application启动类所在模块的根路径建立以下文件:
    bin/docker-service.sh (服务启停文件)
    deploy/sh/deploy-docker.sh (服务部署脚本)
    install/assembly-docker.xml (部署文件打包配置)
    install/assembly-tar.xml (项目打包配置)
    Dockerfile (容器打包文件)
    deploy/docker-compose/docker-compose.yml (docker容器配置文件)
3.docker-service.sh
    #!/bin/sh
    # --------------------声明 start--------------------------------------
    # docker部署后专用启动脚本
    # 使用方式 docker容器启动时内部调用,服务停启请通过docker命令
    # ${project.basedir}为springboot项目Application启动类所在模块的根目录
    # 该shell脚本文件在项目的的存放位置-${project.basedir}/bin
    # 在该文件目录下的../install/assembly-docker.xml会扫描该文件并将在docker镜像构建时加入镜像服务
    # --------------------声明 end----------------------------------------
    #
    #
    #----------------------- 不同项目需要修改的部分 start--------------------
    # 服务名称
    # springboot项目请修改为Application启动类所在模块的artifactId
    SERVICE_NAME="wy-start-service"
    # 服务部署目录
    DEPLOY_PATH="/opt/wy"
    # gc日志文件目录
    # 建议项目中logback.xml配置的目录相同
    GCLogHome="/var/logs/wy/wy-start-service"
    #----------------------- 不同项目需要修改的部分 end---------------------
    #
    ##
    echo "服务名称:$SERVICE_NAME"
    echo "文件所在目录:$DEPLOY_PATH"
    echo "GC日志目录:$GCLogHome"
    GCCommand="-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintHeapAtGC     -XX:+PrintReferenceGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintSafepointStatistics     -XX:PrintSafepointStatisticsCount=1 -Xloggc:$GCLogHome/gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=14     -XX:GCLogFileSize=100M"
    # shellcheck disable=SC2061
    FIND_JAR_CMD="find $DEPLOY_PATH/$SERVICE_NAME/ -name '$SERVICE_NAME*.jar'|grep -v $SERVICE_NAME*sources.jar "
    echo "查找jar包所在目录:$FIND_JAR_CMD"
    service_jar_path=$(eval $FIND_JAR_CMD)
    echo "jar包目录:$service_jar_path"
    # shellcheck disable=SC2236
    if  [ ! -n "$service_jar_path" ] ;then
      echo '没有找到目标路径'
    else
        echo "目标路径为:$service_jar_path"
        if  [ ! -n "${MY_JAVA_OPTS}" ] ;then
          echo "没有找到JVM参数"
          java -jar "$service_jar_path"
        else
          echo "jvm参数:${MY_JAVA_OPTS}"
          java "${MY_JAVA_OPTS}" -jar "$service_jar_path"
        fi
    fi
4.deploy-docker.sh(模板)
    #!/bin/sh
    # --------------------声明 start--------------------------------------
    # docker形式部署时专用
    # 使用方式 sh deploy-docker.sh
    # ${project.basedir}为springboot项目Application启动类所在模块的根目录
    # 该shell脚本文件在项目的的存放位置-${project.basedir}/deploy/sh
    # 在该位置下的../../install/assembly-docker.xml会扫描该文件并将该文件加入部署包
    # --------------------声明 end----------------------------------------
    #
    #----------------------- 不同项目需要修改的部分 start--------------------
    # 服务名称
    # springboot项目请修改为Application启动类所在模块的artifactId
    SERVICE_NAME="wy-start-service"
    # 服务版本
    # springboot项目请修改为Application启动类所在模块的version
    SERVICE_VERSION="1.0-SNAPSHOT"
    #----------------------- 不同项目需要修改的部分 end--------------------
    #
    # docker-compose启动文件的根目录
    # 默认所有docker文件统一在/usr/local/docker-run/enable下以服务名作子文件夹名称区分
    # 例如:/usr/local/docker-run/enable/mysql /usr/local/docker-run/enable/redis
    #
    ##
    DOCKER_COMPOSE_ROOT="/usr/local/docker-run/enable";
    echo "服务名称:$SERVICE_NAME"
    dockerComposeFilePath="docker-compose.yml"
    dockerConfigPath=$(cd ./conf;pwd)
    defaultDirName="$DOCKER_COMPOSE_ROOT/$SERVICE_NAME";
    defaultDockerConfigPath="$DOCKER_COMPOSE_ROOT/$SERVICE_NAME/conf"
    defaultDockerComposeFilePath="$defaultDirName/docker-compose.yml"
    echo "开始部署docker-compose..."
    echo "判断当前路径是否存在docker-compose.yml,如果存在,则强制复制到目标路径$defaultDirName"
    # shellcheck disable=SC2236
    if  [ ! -f "$dockerComposeFilePath" ] ;then
      echo "当前目录未找到docker-compose.yml,使用默认文件$defaultDockerComposeFilePath"
      if  [ ! -f "$defaultDockerComposeFilePath" ] ;then
        echo "默认文件未找到,程序退出,部署失败"
        exit
      fi
    else
      echo "文件存在,开始复制"
      if  [ ! -d "$defaultDirName" ] ;then
        mkdir -p "$defaultDirName"
      fi
      cp -f "$dockerComposeFilePath" "$defaultDirName"
    fi
    echo "docker-compose部署完毕"
    echo "开始部署服务相关配置文件..."
    echo "判断当前路径是否存在conf目录,如果存在,则强制复制到目标路径$defaultDirName"
    # shellcheck disable=SC2236
    if  [ ! -d "$dockerConfigPath" ] ;then
      echo "当前目录未找到conf目录,使用默认目录$defaultDockerConfigPath"
      if  [ ! -d "$defaultDockerConfigPath" ] ;then
        echo "默认目录未找到,程序退出,部署失败"
        exit
      fi
    else
      if  [ ! -d "$defaultDirName" ] ;then
        mkdir -p "$defaultDirName"
      fi
      echo "目录存在,开始复制"
      cp -rf "$dockerConfigPath" "$defaultDirName"
    fi
    echo "config目录部署完毕"
    echo "开始启动服务"
    docker pull zjxianlin.com:41532/library/"$SERVICE_NAME":1.0-SNAPSHOT
    cd "$defaultDirName"&&docker-compose up -d
5. assembly-tar.xml
    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd
    http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 ">
     <id>${project.version}</id><!--id 标识符,添加到生成文件名称的后缀符。可以不指定-->

     <formats>
       <!--打包方式,支持写多个包括(zip、tar、tar.gz (or tgz)、tar.bz2 (or tbz2)、jar、dir、war)-->
       <format>tar.gz</format>
     </formats>
     <includeBaseDirectory>true</includeBaseDirectory>
     <fileSets>
       <!--将所有resources文件下的文件打包在conf目录下-->
       <fileSet>
         <directory>${project.basedir}/src/main/resources</directory>
         <outputDirectory>conf</outputDirectory>
       </fileSet>
       <!--将启动脚本打包在bin目录下-->
       <fileSet>
         <directory>${project.basedir}/bin</directory>
         <includes>
           <include>*.sh</include>
         </includes>
         <outputDirectory>bin</outputDirectory>
       </fileSet>
       <!--你还可以将初始化sql文件等打包在init目录下-->
       <fileSet>
         <directory>${project.basedir}/deploy/sh</directory>
         <includes>
           <include>deploy-tar.sh</include>
         </includes>
         <outputDirectory>./</outputDirectory>
       </fileSet>
       <fileSet>
         <directory>${project.basedir}/lib</directory>
         <outputDirectory>lib</outputDirectory>
       </fileSet>

     </fileSets>

     <dependencySets>
       <dependencySet>
         <useProjectArtifact>true</useProjectArtifact>
         <outputDirectory>lib</outputDirectory>
         <!-- 将scope为runtime的依赖包打包到lib目录下。 -->
         <scope>runtime</scope>
       </dependencySet>
     </dependencySets>


    </assembly>
6. assembly-docker.xml
    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2   http://maven.apache.org/xsd/assembly-1.1.2.xsd
    http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 ">
      <id>docker-deploy</id><!--id 标识符,添加到生成文件名称的后缀符。可以不指定-->
    
      <formats>
        <!--打包方式,支持写多个包括(zip、tar、tar.gz (or tgz)、tar.bz2 (or tbz2)、jar、dir、war)-->
        <format>zip</format>
      </formats>
      <includeBaseDirectory>true</includeBaseDirectory>
      <fileSets>
        <!--将所有resources文件下的文件打包在conf目录下-->
        <fileSet>
          <directory>${project.basedir}/src/main/resources</directory>
          <outputDirectory>conf</outputDirectory>
        </fileSet>
        <!--将启动脚本打包在bin目录下-->
        <fileSet>
          <directory>${project.basedir}/deploy/docker-compose</directory>
          <outputDirectory>./</outputDirectory>
        </fileSet>
        <!--将启动脚本打包在bin目录下-->
        <fileSet>
          <directory>${project.basedir}/deploy/sh</directory>
          <includes>
            <include>deploy-docker.sh</include>
          </includes>
          <outputDirectory>./</outputDirectory>
        </fileSet>
      </fileSets>
    </assembly>
7.Dockerfile 注意替换 /opt/wy部署目录
# This  Dockerfile
# Version 1.0-SNAPSHOT
# Base images 基础镜像
FROM openjdk:8-jdk-alpine
#MAINTAINER 维护者信息
MAINTAINER fengkuangdejava
EXPOSE 8080
ARG SERVICE_NAME
ARG VERSION_NAME
ENV SERVICE_NAME ${SERVICE_NAME}
ENV VERSION_NAME ${VERSION_NAME}
ENV MY_JAVA_OPTS -Xmx512m
ENV ACTIVEPROFILE dev
RUN mkdir -p /opt/wy/
ADD ./target/${SERVICE_NAME}-${VERSION_NAME}.tar.gz /opt/wy/
RUN rm -f /opt/wy/${SERVICE_NAME}-${VERSION_NAME}.tar.gz
RUN cp -r /opt/wy/${SERVICE_NAME}/bin /opt/wy/
RUN cd /opt/wy/${SERVICE_NAME}&&ls
CMD ["sh","/opt/wy/bin/docker-service.sh"]

ps:SERVICE_NAME,VERSION_NAME两个变量maven打包时会pom传入,如果是手动构建,则需要在构建命令 docker build时自己传入build args.
8.docker-compose.yml 注意替换版本号为模块版本
    version: '3'
    services:
      wuyin:
        image: 镜像仓库地址/wy-start-service:1.0-SNAPSHOT
        restart: always
        container_name: wuyin
        volumes:
          - ./conf:/opt/wy/wy-start-service/conf
          - ./log/:/var/logs/wy/wy-start-service
        ports:
          - 8084:8080
        environment:
          - MY_JAVA_OPTS=-Xmx1024m
          - ACTIVEPROFILE=dev
          - serverPort=8080
ps:      
    MY_JAVA_OPTS:docker-service.sh用,用于java启动传参

    ACTIVEPROFILE:因为为在application.yml的写法为:
        spring:
          profiles:
            active: ${ACTIVEPROFILE:dev}
    用于指定容器内部使用哪套application-**.yml配置。
    
    serverPort:因为为在application.yml的写法为:
    
        server:
          port: ${serverPort:8082}
    用于指定容器内部服务启动时的端口,Docker部署时固定8080,以便和dockerFile对应
9.Application启动类所在模块的pom.xml配置
    <properties>
        <mainClass>你的Application启动类的全限定名</mainClass>
    </properties>
    <build>
        <resources>
          <resource>
            <directory>src/main/java</directory><!--所在的目录-->
            <includes><!--包括目录下的.properties,.xml文件都会扫描到-->
              <include>**/*</include>
            </includes>
            <filtering>false</filtering>
          </resource>
        </resources>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <executions>
              <execution>
                <id>default-jar</id>
                <phase>package</phase>
                <goals>
                  <goal>jar</goal>
                </goals>
                <configuration>
                  <archive>
                    <manifest>
                      <mainClass>${mainClass}</mainClass>
                      <addClasspath>true</addClasspath>
                      <classpathPrefix>./</classpathPrefix>
                    </manifest>
                    <manifestEntries>
                      <Class-Path>../conf/</Class-Path>
                    </manifestEntries>
                  </archive>
                  <excludes>
                    <exclude>*</exclude>
                    <exclude>*/*</exclude>
                    <exclude>*/static</exclude>
                  </excludes>
                  <skipIfEmpty>true</skipIfEmpty>
                </configuration>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
            <configuration>
              <skip>true</skip>
            </configuration>
          </plugin>
          <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
              <execution>
                <id>make-tar</id>
                <phase>package</phase>
                <goals>
                  <goal>single</goal>
                </goals>
                <configuration>
                  <finalName>${project.artifactId}</finalName>
                  <descriptors>
                    <descriptor>install/assembly-tar.xml</descriptor>
                  </descriptors>
                </configuration>
              </execution>
              <execution>
                <id>make-deploy</id>
                <phase>package</phase>
                <goals>
                  <goal>single</goal>
                </goals>
                <configuration>
                  <finalName>${project.artifactId}</finalName>
                  <descriptors>
                    <descriptor>install/assembly-docker.xml</descriptor>
                  </descriptors>
                </configuration>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>dockerfile-maven-plugin</artifactId>
            <executions>
              <execution>
                <id>default</id>
                <goals>
                  <!--如果package时不想用docker打包,就注释掉这个goal-->
                  <goal>build</goal>
                  <goal>push</goal>
                </goals>
              </execution>
            </executions>
            <configuration>
              <!-- 上下文路径配置,此处设置为项目根路径 用来读取Dockerfile-->
              <contextDirectory>${project.basedir}</contextDirectory>
              <useMavenSettingsForAuth>true</useMavenSettingsForAuth>
              <!--上传路径/镜像构建名: 私服地址/私服项目名/springboot项目名-->
              <repository>${docker.registry}/${docker.image.prefix}/${project.artifactId}
              </repository>
              <!-- 标记 -->
              <tag>${project.version}</tag>
              <useMavenSettingsForAuth>true</useMavenSettingsForAuth>
              <buildArgs>
                <SERVICE_NAME>${project.artifactId}</SERVICE_NAME>
                <VERSION_NAME>${project.version}</VERSION_NAME>
              </buildArgs>
            </configuration>
          </plugin>
        </plugins>
      </build>
10.开始打包
mvn clean package -DskipTests=true (仅构docker构建镜像不上传镜像到镜像仓库)
mvn clean package deploy -DskipTests=true(构建镜像并上传到镜像仓库)
然后在target目录找到相关tar包
上传至服务器任意目录 tar zxvf ***.tar.gz
然后进入目录:
    dos2unix *.sh
    sh deploy-docker.sh
然后会正式开始部署docker-compose文件,并启动容器

总结

这里讲了3种部署方式,其实三种都可以配置在项目当中。通过maven的Profile来区分。
如下图:

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

 mvn clean package install -Ptar  来指定使用什么打包方式
                           -Pjar
                           -Pdocker
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

打包部署也这么内卷--springboot项目的打包及一键服务器部署 的相关文章

  • Java中反射是如何实现的?

    Java 7 语言规范很早就指出 本规范没有详细描述反射 我只是想知道 反射在Java中是如何实现的 我不是问它是如何使用的 我知道可能没有我正在寻找的具体答案 但任何信息将不胜感激 我在 Stackoverflow 上发现了这个 关于 C
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • JAXb、Hibernate 和 beans

    目前我正在开发一个使用 Spring Web 服务 hibernate 和 JAXb 的项目 1 我已经使用IDE hibernate代码生成 生成了hibernate bean 2 另外 我已经使用maven编译器生成了jaxb bean
  • 是否有 ADB 命令来检查媒体是否正在播放

    我想使用 ADB 命令检查根植于终端的外部设备中是否正在播放音频 视频 我无法找到任何 ADB 命令 如果有 我尝试过 adb shell dumpsys media player 我想要一个命令来指定视频是否正在运行 您可以使用以下命令查
  • 反射找不到对象子类型

    我试图通过使用反射来获取包中的所有类 当我使用具体类的代码 本例中为 A 时 它可以工作并打印子类信息 B 扩展 A 因此它打印 B 信息 但是当我将它与对象类一起使用时 它不起作用 我该如何修复它 这段代码的工作原理 Reflection
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • 禁止的软件包名称:java

    我尝试从数据库名称为 jaane 用户名 Hello 和密码 hello 获取数据 错误 java lang SecurityException Prohibited package name java at java lang Class
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • 如何在 javadoc 中使用“<”和“>”而不进行格式化?

    如果我写
  • Android 中麦克风的后台访问

    是否可以通过 Android 手机上的后台应用程序 服务 持续监控麦克风 我想做的一些想法 不断聆听背景中的声音信号 收到 有趣的 音频信号后 执行一些网络操作 如果前台应用程序需要的话 后台应用程序必须能够智能地放弃对麦克风的访问 除非可
  • 在mockito中使用when进行模拟ContextLoader.getCurrentWebApplicationContext()调用。我该怎么做?

    我试图在使用 mockito 时模拟 ContextLoader getCurrentWebApplicationContext 调用 但它无法模拟 here is my source code Mock org springframewo
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • simpleframework,将空元素反序列化为空字符串而不是 null

    我使用简单框架 http simple sourceforge net http simple sourceforge net 在一个项目中满足我的序列化 反序列化需求 但在处理空 空字符串值时它不能按预期工作 好吧 至少不是我所期望的 如
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 检查帐号是否为数字时出现语法错误

    if account nr 0 9 from account nr 0 9 这是为了检查帐号是否为数字 我收到语法错误 这个问题的早期版本缺少之间的空格if and 实际代码具有所需的空间 它显示以下错误消息 syntax error ac
  • 有没有办法为Java的字符集名称添加别名

    我收到一个异常 埋藏在第 3 方库中 消息如下 java io UnsupportedEncodingException BIG 5 我认为发生这种情况是因为 Java 没有定义这个名称java nio charset Charset Ch
  • 如何修复 JNLP 应用程序中的“缺少代码库、权限和应用程序名称清单属性”?

    随着最近的 Java 更新 许多人都遇到了缺少 Java Web Start 应用程序的问题Codebase Permissions and Application name体现属性 尽管有资源可以帮助您完成此任务 但我找不到任何资源综合的
  • 将 List 转换为 JSON

    Hi guys 有人可以帮助我 如何将我的 HQL 查询结果转换为带有对象列表的 JSON 并通过休息服务获取它 这是我的服务方法 它返回查询结果列表 Override public List

随机推荐

  • NO.15 不得不说的以太坊跟ICO

    随着以太坊的出现 区块链进入了2 0时代 以太坊是个太神奇的东西 没有天才的想法 高超的技术以及黑客的精神是无法如此成功的 它实现了区块链项目的快速开发 快速实施 以太坊这个开发平台本身发行了一种币叫做以太币 ETH 使用此平台开发出来的应
  • APS系统介绍

    APS系统介绍 前言 听说新工作将是做APS系统 之前没接触过 所以查找了一些资料 整理学习记录于此 本文打算从以下几个方面来阐述 APS的概念 前提条件 怎么实现 优化算法 简单示例 APS概念 APS Advanced Planning
  • el-table表单实现点击编辑按钮对内容进行编辑

    el table表单实现点击编辑按钮对内容进行编辑 话不多说 先上效果图 这里我将按钮绑定了dialog对话框 避免直接在原有表行之间进行修改 因为后台管理系统多是响应式布局 使用dialog对话框可以更直观的让用户对内容进行编辑 而对于在
  • 【服务计算】docker实践报告

    docker实践报告 环境说明 准备docker环境 运行第一个容器 Docker基本操作 MySQL与容器化 拉取MySQL镜像 构建docker镜像 MySQL容器使用 Docker compose与多容器应用自动化部署 docker网
  • SpringBoot运行源码分析:Spring应用上下文刷新,java主流框架面试题

    protected void refresh ApplicationContext applicationContext Assert isInstanceOf AbstractApplicationContext class applic
  • 【eNSP】单臂路由+静态路由配置练习

    单臂路由 静态路由配置练习 单臂路由 又名子接口 实际上是一个逻辑接口 并不存在真正物理上的子接口 采用单臂路由 即在路由器上设置多个逻辑子接口 每个子接口都可以单独设置一个IP地址 对应于一个VLAN 由于物理路由接口只有一个 各子接口的
  • Flutter 实体类转String,String转实体类

    实体类转String方式 引用需要转换的包 import dart convert 转换方法 String jsonStr jsonEncode myInfosBeans String转实体类 引用转换包 import dart conve
  • render 怎么使用v-if

    在Vue中使用render函数 有些时候我们需要判断这个元素是否需要渲染 在正常的DOM结构中可以直接使用v if 但是 render函数中有些时候是无法使用v if 来进行判断 这时我们可以使用if 来判断是否添加该元素 render h
  • c++ 理解 关于构造函数和析构函数

    构造函数和析构函数 1 首先 C 有拷贝构造函数 拷贝赋值运算符 移动构造函数 移动赋值运算符和析构函数 构造函数可以先分为 默认构造函数和拷贝构造函数 如果我们在代码中不显示的自己声明构造函数的话 c 的编译器会为我们默认生成默认构造函数
  • STM32之ADC实验

    实验的基本功能 采集PC0引脚的输入电压 通过串口打印出采集的电压值 本实验是使用通道10 采集PC0引脚的输入电压 include stm32f10x h include stm32f10x usart h include
  • mac 卸载idea

    卸载MAC中的IDEA Intellij 首先在应用里面右键移动到垃圾桶 然后使用命令行 cd Users xxx Library 上面的xxx对应你的用户名 然后输入 rm rf Logs IntelliJIdeaxxx rm rf Pr
  • 域名续费怎么才能便宜?2023年腾讯云服务器和域名续费贵怎么续费便宜?

    背景 在腾讯云的有一个域名到期了需要续费 xyz续费居然有79元 真的贵 建议大家在购买域名之前参考我之前的文章 直接买个188元10年的top域名真的香 我是因为小程序都布置好了 如果重新更改域名太累了 所以只能续费 直接续费需要79元
  • 云服务器部署 Web 项目

    一 搭建 Java 部署环境 1 安装 JDK 2 安装 Tomcat 总结 3 安装 MySQL 1 依次安装 2 更改配置 3 启动 4 测试连接 二 部署 web 项目 1 给服务器准备好依赖的数据 2 微调我们的 Java 代码 3
  • Requests模块怎么设置字符编码

    Requests模块在发出网络请求时 支持设置字符编码 主要有以下两种方式 在请求头中设置字符编码 可以通过headers参数设置字符编码 例如 import requests url http www example com header
  • C# SuperSocket 手把手教你入门 傻瓜教程---11(FixedSizeReceiveFilter - 固定请求大小协议)不使用COMMAND

    SuperSocket内置的常用协议实现模版如下 1 TerminatorReceiveFilter SuperSocket SocketBase Protocol TerminatorReceiveFilter SuperSocket S
  • linux命令:修改用户密码

    修改用户密码用passwd命令 假设现在已经用root用户登陆 1 修改root用户密码 在终端直接输入 root armbian passwd New password 输入第一次密码 Retype new password 输入第二次密
  • 3个字节的空txt文本文件

    运行下面代码可以建立一个3个字节的空txt文本文件 想了解其原因的请参考文本文件的编码方式和unicode的具体资料 google上就有很多 System IO FileStream fs new System IO FileStream
  • matlab实现数值积分 【一】(trapz函数)

    目录 总述 函数调用格式 应用举例 例1 梯形法求积分 例2 不同步长对积分结果的影响 总述 数值积分问题是传统数值分析课程中的重要内容 如果被积函数的数学表达式未知 则需要由实测数据通过梯形算法求出积分的近似值 本文将介绍被积函数的数学表
  • 门面设计模式

    github GitHub QiuliangLee pattern 设计模式 1 什么是门面设计模式 门面设计模式是一种软件设计模式 也被称为外观 Facade 模式 它提供了一个简单的接口 让客户端能够访问复杂系统中的一组接口 通过门面模
  • 打包部署也这么内卷--springboot项目的打包及一键服务器部署

    一 环境准备 1 cenos7服务器一台 2 更换yum源 yum install y wget mv etc yum repos d CentOS Base repo etc yum repos d CentOS Base repo ba