操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    1 開發(fā)的熱部署

    1.1 熱部署/熱加載

    熱部署(Hot Deploy):

    熱部署針對的是容器或者是整個應(yīng)用,部署了新的資源或者修改了一些代碼,需要在不停機的情況下的重新加載整個應(yīng)用。

    熱加載(Hot Swap):

    熱加載針對的是單個字節(jié)碼]文件,指的是重新編譯后,不需要停機,應(yīng)用程序就可以加載使用新的class文件。

    1.2 spring boot 熱部署原理

    springBoot熱部署原理是:當我們使用編譯器啟動項目后,在編譯器上修改了代碼后,編譯器會將最新的代碼編譯成新的.class文件放到classpath下;而引入的spring-boot-devtools插件,插件會監(jiān)控classpath下的資源,當classpath下的資源改變后,插件會觸發(fā)重啟;

    而重啟為什么速度快于我們自己啟動呢?

    我們自己啟動的時候,是加載項目中所有的文件(自己編寫的文件 + 所有項目依賴的jar)

    而加入了spring-boot-devtools插件依賴后,我們自己編寫的文件的類加載器為org.springframework.boot.devtools.restart.classloader.RestartClassLoader,是這個工具包自定義的類加載器, 項目依賴的jar使用的是JDK中的類加載器(AppClassLoader\ExtClassLoader\引導(dǎo)類加載器)

    在插件觸發(fā)的重啟中,只會使用RestartClassLoader來進行加載(即:只加載我們自己編寫的文件部分)

    1.2.1 spring-boot-devtools

    這是SpringBoot提供的熱部署工具,添加依賴:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional> 
    </dependency>

    實現(xiàn)資源修改后的自動重啟等功能。啟動應(yīng)用程序時,DevTools會自動配置熱部署,并在保存文件時重新啟動應(yīng)用程序。DevTools還提供了其他功能,如自動重新啟動、自動刷新頁面等,以提高開發(fā)效率。

    1.2.2 使用Spring Loaded

    Spring LoadedSpring的熱部署程序,實現(xiàn)修改類后的自動重載。實現(xiàn)原理是使用自定義ClassLoader,可以實現(xiàn)代碼熱替換。具體實現(xiàn)如下:

    (1)在pom.xml文件中添加Spring Loaded的依賴:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>springloaded</artifactId>
        <version>1.2.8.RELEASE</version>
    </dependency>

    (2)在IDE或編譯器中配置項目的自動構(gòu)建功能。確保在保存文件時自動重新構(gòu)建項目

    (3)啟動應(yīng)用程序時,添加以下JVM參數(shù):

    -javaagent:/path/to/springloaded.jar -noverify

    其中/path/to/springloaded.jar是Spring Loaded JAR文件的路徑,根據(jù)你的實際情況進行相應(yīng)的修改。

    (4)啟動應(yīng)用程序并進行開發(fā)

    每當保存文件時,Spring Loaded會自動檢測到更改并重新加載修改后的類,使得你的更改能夠立即生效。

    需要注意的是,Spring Loaded是一個第三方庫,使用它可能會有一些限制和不穩(wěn)定性。Spring官方已經(jīng)不再維護Spring Loaded

    1.2.3 JRebel插件

    JRebel收費的熱部署軟件,需要添加JRebel插件,可以實現(xiàn)代碼熱部署。效果非常好,但是需要付費使用。

    1.2.4 Spring Boot Maven插件該插件

    可以監(jiān)控代碼變動,自動重啟應(yīng)用。

    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <fork>true</fork>
        </configuration>
    </plugin>

    1.2.5 在IntelliJ IDEA中設(shè)置Spring Boot項目的熱部署

    (1)在IntelliJ IDEA中打開你的Spring Boot項目。

    (2)確保已經(jīng)安裝了Spring Boot DevTools插件。可以通過 File -> Settings -> Plugins 進入插件管理頁面,搜索并安裝Spring Boot DevTools插件。

    (3)在IntelliJ IDEA的頂部菜單欄中,選擇 Run -> Edit Configurations

    (4)在彈出的Run/Debug Configurations對話框中,選擇左側(cè)的 Spring Boot

    (5)在右側(cè)的 Spring Boot 配置窗口中,將 On-frame deactivationOn-update action 選項設(shè)置為 Update classes and resources

    • On-frame deactivation:當你切換到其他窗口時,配置的更新策略。
    • On-update action:當檢測到文件更改時,配置的更新策略。

    這樣設(shè)置后,當你切換到其他窗口時,應(yīng)用程序會在后臺重新啟動,同時當檢測到文件更改時,應(yīng)用程序會更新相關(guān)的類和資源。

    (6)點擊 ApplyOK 按鈕保存配置。

    (7)點擊IntelliJ IDEA的頂部菜單欄中的 Build -> Build Project 來構(gòu)建你的項目。

    (8)在構(gòu)建完成后,點擊工具欄上的綠色箭頭圖標或使用快捷鍵 Shift + F10 來運行你的Spring Boot應(yīng)用程序。

    現(xiàn)在,當你修改代碼并保存文件時,IntelliJ IDEA會自動將更改的類和資源重新加載到運行的應(yīng)用程序中,實現(xiàn)熱部署。

    請注意,熱部署只適用于開發(fā)環(huán)境,并且對于某些修改,可能需要重啟應(yīng)用程序才能生效。因此,在生產(chǎn)環(huán)境中不建議使用熱部署。

    2 常規(guī)部署

    2.1 jar形式

    傳統(tǒng)的Web應(yīng)用進行打包部署,通常會打成war包形式,然后將War包部署到Tomcat等服務(wù)器中。

    在Spring Boot項目在開發(fā)完成后,確實既支持打包成JAR文件也支持打包成WAR文件。然而,官方通常推薦將Spring Boot項目打包成JAR文件,這是因為Spring Boot內(nèi)置了一個嵌入式的Tomcat服務(wù)器,使得應(yīng)用能夠作為一個獨立的可執(zhí)行JAR文件運行,無需部署到外部的Servlet容器中。

    雖然Spring Boot也支持打包成WAR文件并部署到外部的Servlet容器中,但這種方式通常不是首選,因為它增加了額外的部署復(fù)雜性,并且可能無法充分利用Spring Boot提供的一些自動配置和簡化功能。

    (1)插件完整配置,在pom.xml文件中添加配置

         <build>
            <plugins>
    
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version><!-- 配置中的版本號 -->
                    <configuration>
                        <source>1.8</source><!-- 設(shè)置源代碼的JDK版本 -->
                        <target>1.8</target><!-- 設(shè)置目標代碼的JDK版本 -->
                        <encoding>UTF-8</encoding><!-- 設(shè)置編碼方式 -->
                    </configuration>
                </plugin>
                <!--maven 打包插件-->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                    <configuration>
                        <mainClass>com.example.demo.DemoApplication</mainClass><!-- 配置啟動類 -->
                        <skip>false</skip><!--是否忽略啟動類-->
                    </configuration>
                    <executions>
                        <execution>
                            <id>repackage</id>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
    
            </plugins>
        </build>

    maven-compiler-plugin是Maven的一個插件,主要用于代碼編譯,并提供了很多可配置的選項來優(yōu)化編譯過程。主要作用:

    • 指定JDK版本:可以明確指定項目源代碼所使用的JDK版本,以及編譯后的類庫擬運行的JVM版本,從而確保項目在不同環(huán)境中的一致性和穩(wěn)定性。
    • 設(shè)置編碼方式:允許設(shè)置源代碼和目標代碼的編碼方式,以防止因編碼不一致而導(dǎo)致的編譯錯誤或亂碼問題。
    • 優(yōu)化編譯過程:可以對編譯過程進行細粒度的控制。例如,可以設(shè)置是否使用增量編譯、是否生成調(diào)試信息等,以提高編譯效率和代碼質(zhì)量。
    • spring-boot-maven-plugin是一個用于Spring Boot項目的Maven插件,它在項目的構(gòu)建和打包過程中發(fā)揮著關(guān)鍵作用。主要作用:
    • 打包可執(zhí)行JAR/WAR文件:該插件可以將Spring Boot應(yīng)用程序打包成一個可執(zhí)行的JAR或WAR文件。
    • 指定執(zhí)行類:該插件可以指定要執(zhí)行的類,如果未指定也能夠自動檢測項目中的main函數(shù),并啟動SpringBoot容器。

    (2)然后在命令行或IDE中執(zhí)行打包命令:

    mvn clean package

    這將清理舊的構(gòu)建產(chǎn)物,編譯項目,執(zhí)行測試(如果有),并最終打包成一個可執(zhí)行的JAR文件。生成的JAR通常位于target目錄下,文件名格式為your-project-name-<version>.jar

    這將完成同樣的清理、編譯、測試和打包過程,生成的JAR文件同樣位于build/libs目錄下,文件名類似your-project-name-<version>.jar

    (3)部署JAR文件

    要運行打包好的JAR文件,只需在命令行中使用java -jar命令:

    java -jar target/your-project-name-<version>.jar

    根據(jù)需要,可以指定各種運行參數(shù)、環(huán)境變量或配置文件位置。例如:

    java -Dserver.port=8081 -jar your-project-name.jar --spring.config.location=file:/path/to/application.properties

    (4)打包本地jar包

    引入本地jar

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <includeSystemScope>true</includeSystemScope>
                </configuration>
            </plugin>
        </plugins>
    </build>

    配置Maven插件:為了確保本地JAR包在打包時能夠被正確識別和包含,需要配置spring-boot-maven-plugin插件。在pom.xml中添加以下配置:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <includeSystemScope>true</includeSystemScope>
                </configuration>
            </plugin>
        </plugins>
    </build>

    這段配置中的<includeSystemScope>元素設(shè)置為true,以確保在依賴項解析過程中包括system作用域的依賴項。

    或者更改 pom.xml 中的 <build> 新增或修改 <resources> 標簽

    <resources>
        <resource>
            <!-- 因為新增或修改,會覆蓋原有配置,需要配置上默認的 resources 目錄 -->
            <directory>src/main/resources</directory>
        </resource>
        <resource>
            <!-- 上面創(chuàng)建的用于放置第三方 jar 包的文件夾名稱 -->
            <directory>libs</directory>
            <!-- 指定在最終的 jar 包中所在的目錄 -->
            <targetPath>BOOT-INF/lib</targetPath>
            <!-- 需要打包的文件 -->
            <includes>
                <include>**/*.jar</include>
            </includes>
        </resource>
    </resources>

    maven clean package 然后在 target 目錄中找到打包好的 jar 包文件,解壓可查看已經(jīng)打包進去第三方 jar 包。

    2.2 注冊為Linux的服務(wù)

    Linux將Spring Boot項目的Jar包注冊為開機自啟動系統(tǒng)服務(wù)的操作方法

    1)目錄結(jié)構(gòu)

    以下是目錄結(jié)構(gòu),jar文件是從maven package打包出來的,config/application.yml是原先在項目的resources文件夾里,外置出來方便適配開發(fā)環(huán)境和正式環(huán)境。static目錄用來存放靜態(tài)資源,比如vue前端或者上傳目錄。所有的.sh文件都是本文后續(xù)要寫的。

    /data
    	/start.sh 						   // 啟動腳本
    	/stop.sh						   // 關(guān)閉腳本
    	/serviceStart.sh				   // 服務(wù)啟動腳本
    	/serviceStop.sh 				   // 服務(wù)關(guān)閉腳本
    	/YumeisoftDemo-0.0.1-SNAPSHOT.jar  // 打包的項目Jar包
    	/config							   // 配置文件目錄
    		/application.yml			   // 項目配置文件
    	/jdk							   // jdk目錄
    	/static							   // 靜態(tài)資源目錄

    2)編寫Service調(diào)用的腳本

    配置腳本/data/config.sh,如果改包名,直接改這個文件即可

    #!/bin/sh
    # 配置JAR文件名,把它改成你的Jar文件名
    SPRING_JARFILE=YumeisoftDemo-0.0.1-SNAPSHOT.jar
    # 日志文件位置
    LOG_FILE=system.log
    # 獲取.sh所在路徑
    INSTALL_DIR=$(cd $(dirname $0);pwd)
    # 配置JDK路徑
    JAVA_HOME=$INSTALL_DIR/jdk
    # 設(shè)定PATH,不設(shè)會無法使用java命令
    PATH=$JAVA_HOME/bin:$PATH

    手動啟動服務(wù)腳本/data/start.sh,其中system.log是日志文件名

    #!/bin/sh
    # 讀取config.sh定義的內(nèi)容
    source $INSTALL_DIR/config.sh
    # 后臺方式運行jar包
    nohup java -jar $INSTALL_DIR/$SPRING_JARFILE > $INSTALL_DIR/$LOG_FILE 2>&1 &
    # 顯示日志
    tail -f $INSTALL_DIR/$LOG_FILE

    手動關(guān)閉服務(wù)腳本/data/stop.sh

    #!/bin/sh
    # 讀取config.sh定義的內(nèi)容
    source $INSTALL_DIR/config.sh
    # 獲取當前項目運行的進程ID
    PID=$(ps -ef | grep "java -jar $INSTALL_DIR/$SPRING_JARFILE" | grep -v grep | awk '{print $2}')
    
    if [ -z "$PID" ]; then
    	# 如果沒找到則提示未運行
        echo "Spring Boot應(yīng)用未在運行中."
    else
    	# 如果找到了,正常終止進程
        kill $PID
        # 顯示日志
        tail -f $INSTALL_DIR/$LOG_FILE
        echo "Spring Boot應(yīng)用已停止."
    fi

    服務(wù)啟動腳本/data/serviceStart.sh

    #!/bin/sh
    # 讀取config.sh定義的內(nèi)容
    source $INSTALL_DIR/config.sh
    # 后臺方式運行jar包
    nohup java -jar $INSTALL_DIR/$SPRING_JARFILE > $INSTALL_DIR/$LOG_FILE 2>&1 &

    服務(wù)關(guān)閉腳本/data/serviceStop.sh

    #!/bin/sh
    # 讀取config.sh定義的內(nèi)容
    source $INSTALL_DIR/config.sh
    # 獲取當前項目運行的進程ID
    PID=$(ps -ef | grep "java -jar $INSTALL_DIR/$SPRING_JARFILE" | grep -v grep | awk '{print $2}')
    
    if [ -z "$PID" ]; then
    	# 如果沒找到則提示未運行
        echo "Spring Boot應(yīng)用未在運行中."
    else
    	# 如果找到了,正常終止進程
        kill $PID
        echo "Spring Boot應(yīng)用已停止."
    fi

    3)賦權(quán)

    不賦權(quán)是無法運行的,所以我們要執(zhí)行以下命令:

    chmod a+x /data/*.sh

    4)創(chuàng)建一個Service

    接下來我們把這個項目注冊為系統(tǒng)服務(wù),myService改成你要改成的服務(wù)名:

    vim /etc/systemd/system/myService.service

    因為之前沒有這個系統(tǒng)服務(wù),會創(chuàng)建一個新文件,這個文件就是系統(tǒng)服務(wù)的啟停配置文件,按一下a進入編輯模式,把下面的代碼粘貼上去,然后按下Esc、冒號、輸入wq、回車。

    [Unit]
    Description=MyService
    After=network.target
    [Service]
    Type=forking
    ExecStart=/data/serviceStart.sh
    ExecStop=/data/serviceStop.sh
    PrivateTmp=true
    [Install]
    WantedBy=multi-user.target

    這里面的ExecStart和ExecStop都是服務(wù)啟動和服務(wù)停止腳本的絕對路徑。Description是指服務(wù)的描述信息,這里可以填中文,其他的不要改動。

    5)啟用并使用Service

    做完以上步驟你就可以在服務(wù)器里執(zhí)行systemctl enable myService命令,即可啟用myService服務(wù),然后使用systemctl start myService即可啟動服務(wù),systemctl stop myService即可關(guān)停服務(wù),system status myService命令可以看到服務(wù)的狀態(tài)。

    2.3 啟動或關(guān)閉腳本

    2.3.1 Windows

    2.3.1.1 啟動腳本

    startup.bat

    @echo off
    
    title Spring Boot Demo
    java -jar spring-boot-demo.jar --server.config=application.yml
    
    @pause

    2.3.1.2 關(guān)閉腳本

    shutdown.bat

    @echo off
    
    set port=8090
    for /f "tokens=1-5" %%i in ('netstat -ano^|findstr ":%port%"') do (
        echo kill the process %%m who use the port %port%
        taskkill /pid %%m -t -f
    )

    2.3.1.3 重啟腳本

    restart.bat

    @echo off
    
    call ./shutdown.bat
    call ./startup.bat
    
    @pause

    @echo off
    
    set port=8090
    for /f "tokens=1-5" %%i in ('netstat -ano^|findstr ":%port%"') do (
        echo kill the process %%m who use the port 
        taskkill /pid %%m -t -f
        goto start
    )
    
    cd %~dp0
    start java -jar spring-boot-demo.jar --server.config=application.yml
    exit
    :start
    start java -jar spring-boot-demo.jar --server.config=application.yml
    exit
    
    @pause

    2.3.2 Linux

    2.3.2.1 啟動/重啟腳本

    startup.sh

    startTime=`date +'%Y-%m-%d %H:%M:%S'`
    
    #jar包文件路徑
    APP_PATH=/home/demo
    
    #jar包文件名稱
    APP_NAME=$APP_PATH/spring-boot-demo.jar
    
    #日志文件名稱
    LOG_FILE=$APP_PATH/spring-boot-demo_out.log
    
    rm -rf $LOG_FILE
    
    echo "開始停止服務(wù)"
    
    #查詢進程,并殺掉當前jar/java程序
    pid=`ps -ef|grep $APP_NAME | grep -v grep | awk '{print $2}'`
    if [ $pid ];then
      echo "pid: $pid"
      kill -9 $pid
      echo "服務(wù)停止成功"
    fi
    
    sleep 2
    
    #判斷jar包文件是否存在,如果存在啟動jar包,并實時查看啟動日志
    if test -e $APP_NAME;then
      echo '文件存在,開始啟動服務(wù)'
    
      #啟動jar包,指向日志文件,2>&1 & 表示打開或指向同一個日志文件
      nohup java -jar -Duser.timezone=GMT+08 $APP_NAME --server.config=application.yml > spring-boot-demo_out.log 2>&1 &
      echo "服務(wù)啟動中"
      sleep 10s
    
      #通過檢測日志來判斷
      while [ -f $LOG_FILE ]
      do
          success=`grep "Started SpringBootDemoApplication in " $LOG_FILE`
          if [[ "$success" !="" ]]
          then
              break
          else
              sleep 1s
          fi
    
          #開始檢測啟動失敗標記
          fail=`grep "Fail" $LOG_FILE`
          if [[ "$fail" !="" ]]
          then
              echo "服務(wù)啟動失敗"
              tail -f $LOG_FILE
              break
          else
              sleep 1s
          fi
      done
      echo "服務(wù)啟動成功"
    
      endTime=`date +'%Y-%m-%d %H:%M:%S'`
      startSecond=$(date --date="$startTime" +%s);
      endSecond=$(date --date="$endTime" +%s);
    
      total=$((endSecond-startSecond))
      echo "運行時間:"$total"s"
      echo "當前時間:"$endTime
    else
      echo $APP_NAME ' 文件不存在'
    fi

    2.3.2.2 關(guān)閉腳本

    shutdown.sh

    #jar包文件名稱
    APP_NAME=/data/demo/spring-boot-demo.jar
    
    echo "開始停止服務(wù)"
    
    #查詢進程,并殺掉當前jar/java程序
    pid=`ps -ef|grep $APP_NAME | grep -v grep | awk '{print $2}'`
    
    echo "pid: $pid "
    
    if [ $pid ];then
      echo "pid: $pid"
      kill -9 $pid
      echo "服務(wù)停止成功"
    else
      echo "未找到對應(yīng)服務(wù)"
    fi

    2.4 war形式

    正常情況下,我們開發(fā) SpringBoot 項目,由于內(nèi)置了Tomcat,所以項目可以直接啟動,部署到服務(wù)器的時候,直接打成 jar 包,就可以運行了。

    有時我們會需要打包成 war 包,放入外置的 Tomcat 中進行運行,或者使用工具idea直接啟動,便于開發(fā)調(diào)試。

    2.4.1 實現(xiàn)步驟

    (1)將pom文件打包方式更改為 war

    <packaging>war</packaging>

    (2)排除內(nèi)置 Tomcat

    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-web</artifactId>
    	<!-- 排除內(nèi)置的tomcat -->
    	<exclusions>
    		<exclusion>
    			<artifactId>org.springframework.boot</artifactId>
    			<groupId>spring-boot-starter-tomcat</groupId>
    		</exclusion>
    	</exclusions>
    </dependency>

    (3)添加tomcat依賴,需要用到 servlet-api 的相關(guān) jar 包

    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-tomcat</artifactId>
    	<!-- tomcat范圍改成provided,否則后面就會出問題,tomcat無法解析jsp -->
    	<scope>provided</scope>
    </dependency>

    (4)繼承 SpringBootServletInitializer 并重寫 configure 方法

    新建文件文件名隨意,或者直接修改啟動類繼承 SpringBootServletInitializer 并重寫 configure 方法,也是一樣的。

    package com.test;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
    /**
     * 注意,使用war方式部署,需要開啟此類
     *
     */
    public class ServletInitializer extends SpringBootServletInitializer {
        @Override  
        protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {  
            return application.sources(ApplicationMain.class);  
        }
    } 

    2.4.2 部署方式:

    (1)使用外部tomcat啟動

    1)利用maven命令打包



    2)將打的war包,復(fù)制粘貼到tomcat的webapps目錄下(不用解壓,啟動tomcat自動解壓)



    3)啟動tomcat

    在tomcat安裝目錄下的bin目錄下面找到startup.bat命令,啟動tomcat



    4)啟動結(jié)果

    war包自動解壓了



    5)測試結(jié)果,訪問swagger頁面:

    訪問路徑這里需要注意,原來我們在application.properties配置的訪問路徑已經(jīng)不生效了。

    這是原來訪問路徑:http://localhost:8080/testservice/swagger-ui.html

    #已經(jīng)不生效了 server.servlet.context-path=/testservice

    現(xiàn)在的訪問路徑:

    http://localhost:[端口號]/[打包項目名]/

    (2)方式二:使用工具idea直接啟動

    1)配置web.xml文件

    點擊File->Project Structure



    創(chuàng)建src/main/webapp和web.xml



    此時項目結(jié)構(gòu)圖如下:



    2)配置artifacts

    配置完后,tomcat啟動才能找到這個war包,會生成out目錄輸出文件。

    當然你也可以選擇target下面已經(jīng)打包好的war包,但是這樣有個缺點,就是每次改文件你都需要用maven重新打包,輸出到target目錄下,不方便開發(fā)。





    3)配置tomcat

    在IDEA右上角的項目運行列表中選中 Edit Configurations



    進入新的窗口點擊"+",找到Toncat Server中的Local進行點擊,配置Tomcat路徑



    4)tomcat 選擇啟動的war包

    這里注意選擇exploded結(jié)尾的,才是out目錄輸出的



    Application context上下文配置訪問路徑

    訪問路徑這里需要注意,原來我們在application.properties配置的訪問路徑已經(jīng)不生效了。

    #已經(jīng)不生效了
    server.servlet.context-path=/testservice

    現(xiàn)在的訪問路徑:

    http://localhost:8080/testservice/swagger-ui.html

    testservice是我Application context上下文配置的訪問路徑 ,這個可以改的。

    5)配置tomcat啟動默認打開的頁面



    6)啟動結(jié)果

    點擊啟動



    3 云部署-基于Docker的部署

    3.1 Dockerfile

    3.1.1 Dockerfile詳解

    Dockerfile是一個組合映像命令的文本;可以使用在命令行中調(diào)用任何命令;Docker通過dockerfile中的指令自動生成鏡像。

    通過docker build -t repository:tag ./ 即可構(gòu)建,要求:./下存在Dockerfile文件

    之前我們聊的鏡像分層,這個層怎么分的,就是由Dockerfile中的每一條指令構(gòu)成

    3.1.2 編寫規(guī)則

    • 文件名必須是 Dockerfile
    • Dockerfile中所用的所有文件一定要和Dockerfile文件在同一級父目錄下
    • Dockerfile中相對路徑默認都是Dockerfile所在的目錄
    • Dockerfile中一能寫到一行的指令,一定要寫到一行,因為每條指令都被視為一層,層多了執(zhí)行效率就慢
    • Dockerfile中指令大小寫不敏感,但指令都用大寫(約定俗成)
    • Dockerfile 非注釋行第一行必須是 FROM
    • Dockerfile 工作空間目錄下支持隱藏文件(.dockeringore),類似于git的.gitingore

    3.1.3 指令詳解

    FROM:基礎(chǔ)鏡像

    FROM <image>:<tag> [as other_name]      # tag可選;不寫默認是latest版
    • FROM是Dockerfile文件開篇第一個非注釋行代碼
    • 用于為鏡像文件構(gòu)建過程指定基礎(chǔ)鏡像,后續(xù)的指令都基于該基礎(chǔ)鏡像環(huán)境運行
    • 基礎(chǔ)鏡像可以是任何一個鏡像文件
    • as other_name是可選的,通常用于多階段構(gòu)建(有利于減少鏡像大小)
    • 使用是通過--from other_name使用,例如COPY --from other_name

    LABEL:鏡像描述信息

    LABEL author="zp wang <test@qq.com>"
    LABEL describe="test image"
    
    # 或
    LABEL author="zp wang <test@qq.com>" describe="test image"
    
    # 或
    LABEL author="zp wang <test@qq.com>" \
          describe="test image"
    • LABEL指令用來給鏡像以鍵值對的形式添加一些元數(shù)據(jù)信息
    • 可以替代MAINTAINER指令
    • 會集成基礎(chǔ)鏡像中的LABEL,key相同會被覆蓋

    MAINTAINER:添加作者信息

    MAINTAINER zp wang <test@163.com>

    COPY:從構(gòu)建主機復(fù)制文件到鏡像中

    COPY <src> <dest>
    
    COPY ["<src>", "<src>", ... "<dest>"]
    • <src>:要復(fù)制的源文件或目錄,支持通配符 <src>必須在build所在路徑或子路徑下,不能是其父目錄 <src>是目錄。其內(nèi)部的文件和子目錄都會遞歸復(fù)制,但<src>目錄本身不會被復(fù)制 如果指定了多個<src>或使用了通配符,這<dest>必須是一個目錄,且必須以/結(jié)尾
    • <dest>:目標路徑,即鏡像中文件系統(tǒng)的路徑 <dest>如果不存在會自動創(chuàng)建,包含其父目錄路徑也會被創(chuàng)建
    # 拷貝一個文件
    COPY testFile /opt/
    
    # 拷貝一個目錄
    COPY testDir /opt/testDir

    testDir下所有文件和目錄都會被遞歸復(fù)制

    目標路徑要寫testDir,否則會復(fù)制到/opt下

    ADD:從構(gòu)建宿主機復(fù)制文件到鏡像中

    類似于COPY指令,但ADD支持tar文件還讓URL路徑

    ADD <src> <dest>
    
    ADD ["<src>","<src>"... "<dest>"]
    • <src>如果是一個壓縮文件(tar),被被解壓為一個目錄,如果是通過URL下載一個文件不會被解壓
    • <src>如果是多個,或使用了通配符,則<dest>必須是以/結(jié)尾的目錄,否則<src>會被作為一個普通文件,<src>的內(nèi)容將被寫入到<dest>

    WORKDIR:設(shè)置工作目錄

    類似于cd命令,為了改變當前的目錄域

    此后RUN、CMD、ENTRYPOINT、COPY、ADD等命令都在此目錄下作為當前工作目錄

    WORKDIR /opt
    • 如果設(shè)置的目錄不存在會自動創(chuàng)建,包括他的父目錄
    • 一個Dockerfile中WORKDIR可以出現(xiàn)多次,其路徑也可以為相對路徑,相對路徑是基于前一個WORKDIR路徑
    • WORKDIR也可以調(diào)用ENV指定的變量

    ENV:設(shè)置鏡像中的環(huán)境變量

    # 一次設(shè)置一個
    ENV <key> <value>
    
    # 一次設(shè)置多個
    ENV <key>=<value> <key1>=<value1> <key2>=<value2> .....

    使用環(huán)境變量的方式

    $varname
    ${varname}
    ${varname:-default value}           # 設(shè)置一個默認值,如果varname未被設(shè)置,值為默認值
    ${varname:+default value}           # 設(shè)置默認值;不管值存不存在都使用默認值

    USER:設(shè)置啟動容器的用戶

    # 使用用戶名
    USER testuser
    
    # 使用用戶的UID
    USER UID

    RUN:鏡像構(gòu)建時執(zhí)行的命令

    # 語法1,shell 形式
    RUN command1 && command2
    
    # 語法2,exec 形式
    RUN ["executable","param1","[aram2]"]
    
    
    # 示例
    RUN echo 1 && echo 2 
    
    RUN echo 1 && echo 2 \
        echo 3 && echo 4
    
    RUN ["/bin/bash","-c","echo hello world"]
    • RUN 在下一次建構(gòu)期間,會優(yōu)先查找本地緩存,若不想使用緩存可以通過--no-cache解除
      • docker build --no-cache
    • RUN 指令指定的命令是否可以執(zhí)行取決于 基礎(chǔ)鏡像
    • shell形式
      • 默認使用/bin/sh -c 執(zhí)行后面的command
      • 可以使用 &&\ 連接多個命令
    • exec形式
      • exec形式被解析為JSON序列,這意味著必須使用雙引號 ""
      • 與 shell 形式不同,exec 形式不會調(diào)用shell解析。但exec形式可以運行在不包含shell命令的基礎(chǔ)鏡像中
      • 例如:RUN ["echo","$HOME"] ;這樣的指令 $HOME并不會被解析,必須RUN ["/bin/sh","-c","echo $HOME"]

    EXPOSE:為容器打開指定的監(jiān)聽端口以實現(xiàn)與外部通信

    EXPOSE <port>/<protocol>
    
    EXPOSE 80
    EXPOSE 80/http
    EXPOSE 2379/tcp
    • <port>:端口號
    • <protocol>:協(xié)議類型,默認TCP協(xié)議,tcp/udp/http/https
    • 并不會直接暴露出去,docker run時還需要-P指定才可以,這里更像是一個說明

    VOLUME:實現(xiàn)掛載功能,將宿主機目錄掛載到容器中

    VOLUME ["/data"]                    # [“/data”]可以是一個JsonArray ,也可以是多個值
    
    VOLUME /var/log 
    VOLUME /var/log /opt
    • 三種寫法都是正確的
    • VOLUME類似于docker run -v /host_data /container_data 。
    • 一般不需要在Dockerfile中寫明,且在Kubernetes場景幾乎沒用

    CMD:為容器設(shè)置默認啟動命令或參數(shù)

    # 語法1,shell形式
    CMD command param1 param2 ...
    
    # 語法2,exec形式
    CMD ["executable","param1","param2"]
    
    # 語法3,還是exec形式,不過僅設(shè)置參數(shù)
    CMD ["param1","param2"]
    • CMD運行結(jié)束后容器將終止,CMD可以被docker run后面的命令覆蓋
    • 一個Dockerfile只有順序向下的最后一個CMD生效
    • 語法1,shell形式,默認/bin/sh -c 此時運行為shell的子進程,能使用shell的操作符(if環(huán)境變量? *通配符等) 注意: 進程在容器中的 PID !=1,這意味著該進程并不能接受到外部傳入的停止信號docker stop
    • 語法2,exec形式CMD ["executable","param1","param2"] 不會以/bin/sh -c運行(非shell子進程),因此不支持shell的操作符 若運行的命令依賴shell特性,可以手動啟動CMD ["/bin/sh","-c","executable","param1"...]
    • 語法3,exec形式CMD ["param1","param2"] 一般結(jié)合ENTRYPOINT指令使用

    ENTRYPOINT:用于為容器指定默認運行程序或命令

    與CMD類似,但存在區(qū)別,主要用于指定啟動的父進程,PID=1

    # 語法1,shell形式
    ENTRYPOINT command
    
    # 語法2,exec形式
    ENTRYPOINT ["/bin/bash","param1","param2"]
    • ENTRYPOINT設(shè)置默認命令不會被docker run命令行指定的參數(shù)覆蓋,指定的命令行會被當做參數(shù)傳遞給ENTRYPOINT指定的程序。
    • docker run命令的 --entrypoint選項可以覆蓋ENTRYPOINT指令指定的程序
    • 一個Dockerfile中可以有多個ENTRYPOINT,但只有最后一個生效
    • ENTRYPOINT主要用于啟動父進程,后面跟的參數(shù)被當做子進程來啟動

    CMD和ENTRYPOINT組合情況說明

    具體情況比較多,如表格所示


    No ENTRYPOINT

    ENTRYPOINT exec_entry p1_entry

    ENTRYPOINT ["exec_entry","p1_entry"]

    No CMD

    error,not allowed

    /bin/sh -c exec_entry p1_entry

    exec_entry p1_entry

    CMD ["exec_cmd","p1_cmd"]

    exec_cmd p1_cmd

    /bin/sh -c exec_entry p1_entry

    exec_entry p1_entry exec_cmd p1_cmd

    CMD ["p1_cmd","p2_cmd"]

    p1_cmd p2_cmd

    /bin/sh -c exec_entry p1_entry

    exec_entry p1_entry p1_cmd p2_cmd

    CMD exec_cmd p1_cmd

    exec_cmd p1_cmd

    /bin/sh -c exec_entry p1_entry

    exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

    ARG:指定環(huán)境變量用于構(gòu)建過程

    ARG name[=default value]
    
    ARG test_name
    ARG nother_name=wzp
    • ARG指令定義的參數(shù),在構(gòu)建過程以docker build --build-arg test_name=test 形式賦值
    • ARG中沒有設(shè)置默認值,構(gòu)建時將拋出警告:[Warning] One or more build-args..were not consumed
    • Docker默認存在的ARG 參數(shù),可以在--build-arg時直接使用
      • HTTP_PROXY/http_proxy/HTTPS_PROXY/https_proxy/FTP_PROXY/ftp_proxy/NO_PROXY/no_proxy

    ONBUILD:為鏡像添加觸發(fā)器

    ONBUILD可以為鏡像添加一個觸發(fā)器,其參數(shù)可以是任意一個Dockerfile指令。

    ONBUILD <dockerfile_exec> <param1> <param2>
    
    ONBUILD RUN mkdir mydir
    • 該指令,對于使用該Dockerfile構(gòu)建的鏡像并不會生效,只有當其他Dockerfile以當前鏡像作為基礎(chǔ)鏡像時被觸發(fā)
    • 例如:Dockfile A 構(gòu)建了鏡像A,Dockfile B中設(shè)置FROM A,此時構(gòu)建鏡像B是會運行ONBUILD設(shè)置的指令

    STOPSINGAL:設(shè)置停止時要發(fā)送給PID=1進程的信號

    主要的目的是為了讓容器內(nèi)的應(yīng)用程序在接收到signal之后可以先做一些事情,實現(xiàn)容器的平滑退出,如果不做任何處理,容器將在一段時間之后強制退出,會造成業(yè)務(wù)的強制中斷,這個時間默認是10s。

    STOPSIGNAL signal
    • 默認的停止信號為:SIGTERM,也可以通過docker run -s指定

    HEALTHCHECK:指定容器健康檢查命令

    當在一個鏡像指定了 HEALTHCHECK 指令后,用其啟動容器,初始狀態(tài)會為 starting,在 HEALTHCHECK 指令檢查成功后變?yōu)?healthy,如果連續(xù)一定次數(shù)失敗,則會變?yōu)?unhealthy

    HEALTHCHECK [OPTIONS] CMD command
    
    # 示例
    HEALTHCHECK --interval=5s --timeout=3s \
        CMD curl -fs http://localhost/ || exit 1        # 如果執(zhí)行不成功返回1
    • 出現(xiàn)多次,只有最后一次生效
    • OPTIONS選項
      • --interval=30:兩次健康檢查的間隔,默認為 30 秒;
      • --timeout=30:健康檢查命令運行的超時時間,超過視為失敗,默認30秒;
      • --retries=3:指定失敗多少次視為unhealth,默認3次
    • 返回值
      • 0:成功; 1:失敗; 2:保留

    SHELL:指定shell形式的默認值

    SHELL 指令可以指定 RUN、ENTRYPOINT、CMD 指令的 shell,Linux 中默認為["/bin/sh", "-c"] ,Windows默認["CMD","/S","/C"]

    通常用于構(gòu)建Windows用的鏡像

    SHELL ["/bin/bash","-c"]
    
    SHELL ["powershell", "-command"]
    
    # 示例,比如在Windows時,默認shell是["CMD","/S","/C"]
    RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
    # docker調(diào)用的是cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
    RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
    # 這樣雖然沒有調(diào)用cmd.exe 但寫起來比較麻煩,所以可以通過SHELL  ["powershell", "-command"]

    3.1.4 方式一:直接構(gòu)建jar包運行的鏡像

    • 將打包好程序,上傳到服務(wù)器的指定目錄 例如:/home/www/spring-boot-image/spring-boot-docker-1.0.jar
    • 在該目錄下創(chuàng)建Dockerfile文件
    FROM openjdk:8u312
    MAINTAINER zhangt
    ADD spring-boot-docker-1.0.jar zhangt.jar
    EXPOSE 8520
    ENTRYPOINT ["java","-jar","zhangt.jar"]

    Dockerfile的內(nèi)容解釋:

    FROM openjdk:8u312 這一行指定了基礎(chǔ)鏡像,從openjdk:8u312鏡像構(gòu)建。它使用了OpenJDK 8的版本號為312的鏡像作為基礎(chǔ)。這是一個包含Java運行時環(huán)境的基礎(chǔ)鏡像。

    MAINTAINER zhangt 這一行設(shè)置了維護者信息,盡管在較新版本的Docker中,MAINTAINER已不再建議使用,而可以使用LABEL來添加類似的元數(shù)據(jù)信息。

    ADD spring-boot-docker-1.0.jar zhangt.jar 這一行使用ADD指令將本地的spring-boot-docker-1.0.jar文件復(fù)制到鏡像中,并重命名為zhangt.jar。這個JAR文件包含了Spring Boot應(yīng)用程序的可執(zhí)行代碼。

    EXPOSE 8520 這一行使用EXPOSE指令聲明容器將監(jiān)聽的端口號,這里指定為8520。請注意,這只是一個元數(shù)據(jù)聲明,它不會自動將端口映射到主機上。

    ENTRYPOINT ["java","-jar","zhangt.jar"] 這一行設(shè)置了容器啟動時要執(zhí)行的命令。在這種情況下,容器將以java -jar zhangt.jar命令啟動,這會運行Spring Boot應(yīng)用程序。java命令會啟動Java虛擬機(JVM),并執(zhí)行zhangt.jar中的可執(zhí)行代碼。

    這Dockerfile的作用是基于OpenJDK 8u312鏡像構(gòu)建一個包含Spring Boot應(yīng)用程序的Docker鏡像。一旦構(gòu)建完成,可以使用這個鏡像來運行Spring Boot應(yīng)用程序的容器,容器將監(jiān)聽8520端口,可以通過適當?shù)亩丝谟成鋪碜屚獠吭L問應(yīng)用程序。

    • 創(chuàng)建好Dockerfile文件之后,執(zhí)行命構(gòu)建鏡像
    docker build -t zhangt .

    注意最后的 . 表示Dockerfile在當前文件目錄下。zhangt表示構(gòu)建的鏡像,構(gòu)建成功后可以使用docker images命令查看鏡像。 -t 選項用于指定鏡像的名稱和標簽,你可以將zhangt替換為你想要的名稱和標簽。

    • 鏡像構(gòu)建成功之后,就可以運行容器
    docker run -d --restart=always --name zhangt -p 8520:8520 zhangt

    各個參數(shù)的含義:

    docker run: 用于啟動 Docker 容器的命令。

    -d: 這是一個選項,表示在后臺(守護進程模式)運行容器。容器將在后臺運行,不會占據(jù)終端。

    --restart=always: 這是另一個選項,表示容器在退出時總是重新啟動。即使容器因為錯誤或其他原因而停止,Docker 也會嘗試自動重新啟動容器。

    --name zhangt: 這是用于給容器指定一個名稱的選項。容器的名稱被設(shè)置為 "zhangt"。

    -p 8520:8520: 這是用于將主機端口與容器端口進行映射的選項。這個選項將主機的 8520 端口映射到容器的 8520 端口。這樣,外部可以通過訪問主機的 8520 端口來訪問容器內(nèi)運行的應(yīng)用程序。

    zhangt: 這是容器的名稱或鏡像名稱,表示要運行的容器是基于名為 "zhangt" 的 Docker 鏡像創(chuàng)建的。如果 "zhangt" 是一個鏡像名稱,Docker 將查找該鏡像并在容器中運行它。

    這個命令的目的是在后臺運行一個 Docker 容器,該容器使用 "zhangt" 鏡像創(chuàng)建,并將主機的 8520 端口映射到容器的 8520 端口。容器的名稱設(shè)置為 "zhangt-p",并且如果容器在任何情況下退出,Docker 會自動重新啟動它。這通常用于部署應(yīng)用程序,以確保應(yīng)用程序在意外情況下能夠自動恢復(fù)。

    啟動容器后可以使用 **docker ps**命令查看啟動的容器

    docker logs -f --tail 1000 容器id ,可以查看服務(wù)的日志。

    如果想更新jar包,只需要使用 docker cp spring-boot-docker-1.0.jar 容器ID:/zhangt.jar,就可以將spring-boot-docker-1.0.jar拷貝進容器并重命名,然后 docker restart 容器ID 重啟容器。

    3.15 方式二:基于jdk鏡像運行容器

    • 在服務(wù)器中來取jdk鏡像
    docker pull openjdk:8u181
    • 創(chuàng)建目錄,并將jar包上傳到該目錄
    cd /home/  mkdir www/spring-boot-docker
    • 在Jar放置的同級目錄,編寫shell腳本命名為:start.sh
    #!/bin/bash
    echo -e "\n################ build service start #########################"
    
    # delete docker container
    echo -e "\n1, delete docker container [developer-platform-basic-dev] start ......"
    sudo docker rm -f spring-boot-docker-1.0
    
    # docker run # docker run developer-platform-basic-1.0.0
    echo -e "\n2, docker run build container [spring-boot-docker-1.0] start ......"
    sudo docker run --name spring-boot-docker-1.0 -d -p 8741:8741 \
    -v /home/www/spring-boot-docker:/jar openjdk:8u181 \
    java -jar /jar/spring-boot-docker-1.0.jar --spring.profiles.active=dev
    
    echo -e "\n3, docker ps container [spring-boot-docker-1.0] start ...."
    sudo docker ps -a  | grep spring-boot-docker-1.0
    
    echo -e "\n4, docker logs container [spring-boot-docker-1.0] start ...."
    sudo docker logs -f -t spring-boot-docker-1.0 > ./logs/log_$(date +%Y%m%d).out 2>&1 &
    
    echo -e "\n################ build service end #########################"

    核心腳本解釋:

    1.sudo docker run 這是用于在Docker中運行容器的命令。通常需要使用sudo權(quán)限來執(zhí)行Docker命令,以確保具有足夠的權(quán)限來管理容器。

    --name spring-boot-docker-1.0: 這是為Docker容器指定的名稱,容器的名稱被設(shè)置為"spring-boot-docker-1.0"。

    -d: 這是一個選項,表示在后臺運行容器(即以守護進程模式運行),而不是在前臺交互模式下運行。

    -p 8741:8741: 這個選項用于將主機的端口與容器的端口進行映射。具體來說,將主機的8741端口映射到容器的8741端口,這樣外部可以通過主機的8741端口訪問容器中的應(yīng)用程序。

    -v /home/www/spring-boot-docker:/jar: 這個選項用于將主機的文件系統(tǒng)目錄與容器內(nèi)的目錄進行掛載。在這種情況下,將主機上的/home/www/spring-boot-docker目錄掛載到容器內(nèi)的/jar目錄。這通常用于將應(yīng)用程序的代碼和資源文件從主機復(fù)制到容器中,以便在容器內(nèi)運行應(yīng)用程序。

    openjdk:8u181: 這是要在容器中使用的Docker鏡像的名稱和標簽。在這里,使用的是一個基于OpenJDK 8u181的Java鏡像,該鏡像包含了Java運行時環(huán)境。

    java -jar /jar/spring-boot-docker-1.0.jar --spring.profiles.active=dev: 這是在容器內(nèi)運行的命令。它啟動了Java虛擬機(JVM),并在JVM內(nèi)運行了一個Spring Boot應(yīng)用程序。具體來說,它運行了/jar/spring-boot-docker-1.0.jar這個JAR文件,并通過--spring.profiles.active=dev指定了一個Spring配置文件的激活配置。

    這個腳本的作用是創(chuàng)建一個名為"spring-boot-docker-1.0"的Docker容器,該容器運行一個基于Spring Boot的Java應(yīng)用程序,該應(yīng)用程序監(jiān)聽8741端口,并將主機上的/home/www/spring-boot-docker目錄掛載到容器內(nèi)的/jar目錄,以供應(yīng)用程序使用。這樣,可以通過主機的8741端口訪問運行在容器中的Spring Boot應(yīng)用程序。

    1. 運行腳本 sh start.sh
    2. 以后發(fā)布,只需要把宿主機目錄里的jar包替換掉,重啟容器。

    4 SpringBoot的測試

    4.1 概述

    4.1.1 測試分類

    • 單元測試:測試單個類的功能。
    • 集成測試:測試多個類的協(xié)同工作。
    • 端到端測試:測試整個程序的功能和流程。

    4.1.2 測試分層

    Controller層可以進行單元測試、集成測試(@WebMvcTest)和端到端測試。

    • 在單元測試中,我們可以mock服務(wù)層的行為。
    • 在集成測試中,我們可以使用@MockMvc來模擬HTTP請求。
    • 在端到端測試中,我們則可以測試整個系統(tǒng)的工作流程。

    Service層可以進行單元測試和集成測試。

    • 在單元測試中,我們可以mock Repository層的行為。
    • 在集成測試中,我們則需要確保Service層和其他層之間的交互是正確的。

    Repository層可以進行集成測試(@DataJpaTest)。

    • 在集成測試中,我們通常會使用內(nèi)存數(shù)據(jù)庫以模擬真實數(shù)據(jù)庫的行為。

    工具類可以進行單元測試。

    • 工具類通常是獨立的,我們可以直接進行單元測試,驗證其功能是否正確。

    4.1.3 測試策略

    選擇測試類型

    選擇適當?shù)臏y試類型,根據(jù)需要選擇單元測試、集成測試、端到端測試。

    確定測試目標

    明確你需要測試的具體功能或方法,理解其預(yù)期的行為。

    準備測試環(huán)境和數(shù)據(jù)

    根據(jù)測試需求設(shè)置適當?shù)臏y試環(huán)境。

    • 對于單元測試,你可能需要使用Mockito等庫來創(chuàng)建mock對象,以模擬對其他類或接口的依賴。
    • 對于集成測試,你可能需要配置一個嵌入式的數(shù)據(jù)庫如H2。
    • 對于端到端測試,你可能需要使用Selenium等庫來模擬瀏覽器行為。

    編寫測試用例

    根據(jù)測試目標編寫對應(yīng)的測試用例,包括正常場景、邊界條件和異常場景。

    執(zhí)行測試和結(jié)果驗證

    • 執(zhí)行測試:使用測試框架(如JUnit)運行你的測試。
    • 結(jié)果斷言:利用斷言(assert)功能,驗證你的代碼產(chǎn)生的結(jié)果是否符合預(yù)期。
    • 依賴驗證:如果你的代碼依賴于其他方法或?qū)ο螅阈枰褂胿erify方法來校驗這些依賴項是否被正確地調(diào)用。

    測試報告分析

    評估測試結(jié)果,如果測試失敗,進行bug修復(fù),重新測試,直到所有測試用例都通過。

    重構(gòu)和優(yōu)化

    根據(jù)測試結(jié)果,進行代碼的重構(gòu)和優(yōu)化,提高代碼質(zhì)量。

    測試代碼的維護

    確保測試代碼的可讀性和可維護性,同時保證在項目構(gòu)建過程中能夠自動執(zhí)行測試。

    4.2 單元測試

    4.2.1 定義

    單元測試用于驗證單個類的功能是否正確。

    其特點是獨立于其他類、數(shù)據(jù)庫、網(wǎng)絡(luò)或其他外部資源。

    4.2.2 適用對象

    在實際工作中,通常對Spring Boot中的Controller、Service等類進行單元測試。

    4.2.3 JUnit

    JUnit是Java中最流行的單元測試框架,用于編寫和執(zhí)行單元測試。

    基本注解

    1. @Test: 標記一個測試方法,用于執(zhí)行單元測試。
    2. @Before: 在每個測試方法執(zhí)行之前運行,用于準備測試數(shù)據(jù)或初始化資源。
    3. @After: 在每個測試方法執(zhí)行之后運行,用于清理測試數(shù)據(jù)或釋放資源。
    4. @BeforeClass: 在所有測試方法執(zhí)行前運行,通常用于執(zhí)行一次性的初始化操作。
    5. @AfterClass: 在所有測試方法執(zhí)行后運行,通常用于執(zhí)行一次性的清理操作。
    6. @Ignore: 標記一個測試方法,用于暫時忽略這個測試。
    7. @RunWith(SpringRunner.class)用于運行Spring Boot的測試。

    基本測試

    @Test
    public void testCount() {
        // 測試代碼
    }

    異常測試

    有時候需要測試代碼是否能正確地拋出異常,可以使用@Testexpected屬性:

    @Test(expected=SomeException.class)
    public void testException() {
        // 測試代碼,期望拋出SomeException異常
    }

    超時測試

    有時候需要測試某個操作是否能在規(guī)定時間內(nèi)完成,可以使用@Testtimeout屬性:

    @Test(timeout=1000)
    public void testTimeout() {
        // 測試代碼,期望在1000毫秒內(nèi)執(zhí)行完畢
    }

    忽略測試

    有時候暫時不想執(zhí)行某個測試方法,可以使用@Ignore注解:

    @Ignore("暫時忽略這個測試")
    @Test
    public void testIgnore() {
        // 測試代碼
    }

    4.2.4 Mockito

    Mockito庫用于模擬對象,隔離被測類與其他類的依賴關(guān)系。

    基本概念

    1. Mock對象:使用Mockito創(chuàng)建的模擬對象,用于替代真實對象,以模擬對應(yīng)的行為和返回值。
    2. Stubbing:為Mock對象設(shè)置方法調(diào)用的返回值,以模擬真實對象的行為。
    3. 驗證:Mock對象的方法是否被調(diào)用,以及調(diào)用次數(shù)是否符合預(yù)期。

    常用注解

    1. @Mock: 標記一個模擬對象。
    2. @InjectMocks: 標記一個被測類,用于注入模擬對象。
    3. @RunWith(MockitoJUnitRunner.class): 指定運行器,用于運行Mockito的測試。

    常用方法

    Mockito 提供了一系列方法,用于在單元測試中創(chuàng)建和設(shè)置模擬對象的行為

    • when(mock.method()).thenReturn(value): 設(shè)置當 mock 對象的指定方法被調(diào)用時,返回預(yù)設(shè)的值。
    • any(): 表示任何值,用于 when 或 verify 方法的參數(shù)匹配。
    • doReturn(value).when(mock).method(): 與 when-thenReturn 類似,但適用于無法通過 when-thenReturn 語句模擬的情況,如 void 方法。
    • doThrow(Exception).when(mock).method(): 用于模擬當 mock 對象的指定方法被調(diào)用時,拋出異常。
    • spy(object): 用于創(chuàng)建一個 spy 對象,它是對真實對象的包裝,所有未被 stub 的方法都會調(diào)用真實的方法。

    Mockito 還提供了一系列的方法,用于驗證模擬對象的行為

    • verify(mock).method(): 驗證 mock 對象的指定方法是否被調(diào)用。
    • never(): 驗證 mock 對象的指定方法從未被調(diào)用。
    • times(n): 驗證 mock 對象的指定方法被調(diào)用了 n 次。
    • atLeast(n): 驗證 mock 對象的指定方法至少被調(diào)用了 n 次。
    • atMost(n): 驗證 mock 對象的指定方法最多被調(diào)用了 n 次。

    示例代碼

    @RunWith(MockitoJUnitRunner.class)
    public class TeacherApiTest {
    
        @Mock
        private TeacherService teacherService;
    
        @InjectMocks
        private TeacherApi teacherApi;
    
        @Test
        public void testCount() {
            when(teacherService.countByName("張三")).thenReturn(1);
            TeacherCount result=teacherApi.count("張三");
            verify(teacherService).countByName("張三"); // 驗證方法是否被調(diào)用
            assertEquals(1, result.getCount()); // 驗證返回值是否符合預(yù)期
        }
    }

    4.2.5 AssertJ

    AssertJ庫提供了豐富的斷言方法,可以更簡潔地編寫測試代碼。

    常用斷言

    1. assertThat(actual).isEqualTo(expected): 驗證實際值是否等于預(yù)期值。
    2. assertThat(actual).isNotEqualTo(expected): 驗證實際值是否不等于預(yù)期值。
    3. assertThat(actual).isNotNull(): 驗證實際值是否不為null。
    4. assertThat(actual).isNull(): 驗證實際值是否為null。
    5. assertThat(actual).isTrue(): 驗證實際值是否為true。
    6. assertThat(actual).isFalse(): 驗證實際值是否為false。
    7. assertThat(actual).isInstanceOf(ExpectedClass.class): 驗證實際值是否是指定類的實例。
    8. assertThat(actual).isNotInstanceOf(UnexpectedClass.class): 驗證實際值是否不是指定類的實例。
    9. assertThat(actual).isGreaterThan(expected): 驗證實際值是否大于預(yù)期值。
    10. assertThat(actual).isGreaterThanOrEqualTo(expected): 驗證實際值是否大于等于預(yù)期值。
    11. assertThat(actual).isLessThan(expected): 驗證實際值是否小于預(yù)期值。
    12. assertThat(actual).isLessThanOrEqualTo(expected): 驗證實際值是否小于等于預(yù)期值。
    13. assertThat(actual).contains(expected): 驗證實際值是否包含指定字符串。
    14. assertThat(actualList).contains(expected): 驗證集合是否包含指定元素。
    15. assertThat(actualMap).containsKey(expected): 驗證Map是否包含指定鍵。
    16. assertThat(actualMap).containsValue(expected): 驗證Map是否包含指定值。
    17. assertThat(actualMap).containsEntry(key, value): 驗證Map是否包含指定元素。
    18. assertThat(actualException).isInstanceOf(ExpectedException.class).hasMessage(expectedMessage): 驗證異常是否符合預(yù)期。

    4.2.6 JSONAssert

    JSONAssert庫用于測試JSON字符串是否符合預(yù)期。

    常用方法

    1. assertEquals(expected, actual, strict): 驗證實際的JSON值是否等于預(yù)期的JSON值。這里的strict參數(shù)指定了比較的模式。如果設(shè)置為false,將會使用非嚴格模式比較,這意味著預(yù)期JSON字符串中沒有的字段會被忽略;如果設(shè)置為true,將會使用嚴格模式比較,預(yù)期JSON字符串與實際JSON字符串必須完全匹配。
    2. assertNotEquals(expected, actual, strict): 驗證實際的JSON值是否不等于預(yù)期的JSON值。
    3. assertJSONEquals(expected, actual, jsonComparator): 使用自定義的JSONComparator來驗證實際的JSON值是否等于預(yù)期的JSON值。

    示例代碼

    @Test
    public void testJsonAssert() throws JSONException {
        String expected="{\"id\":1,\"name\":\"張三\"}";
        String actual="{\"id\":1,\"name\":\"張三\"}";
    
        // 使用非嚴格模式進行比較
        JSONAssert.assertEquals(expected, actual, false);
    
        // 使用嚴格模式進行比較,預(yù)期字符串與實際字符串必須嚴格匹配
        JSONAssert.assertEquals(expected, actual, true);
    
        // 驗證實際的JSON值是否不等于預(yù)期的JSON值
        String unexpected="{\"id\":2,\"name\":\"李四\"}";
        JSONAssert.assertNotEquals(unexpected, actual, false);
    
        // 使用自定義的JSONComparator進行比較
        JSONAssert.assertJSONEquals(expected, actual, JSONCompareMode.LENIENT);
    }

    @JsonTest

    SpringBoot的@JsonTest注解用于測試JSON序列化和反序列化。

    示例代碼

    @JsonTest
    public class TeacherJsonTest {
    
        @Autowired
        private JacksonTester<Teacher> json;
    
        String content="{\"id\":1,\"name\":\"張三\"}";
    
        @Test
        public void testSerialize() throws Exception {
            Teacher teacher=new Teacher();
            teacher.id=1L;
            teacher.name="張三";
    
            assertThat(json.write(teacher)).isEqualToJson(content);
        }
    
        @Test
        public void testDeserialize() throws Exception {
            Teacher teacher=new Teacher();
            teacher.id=1L;
            teacher.name="張三";
    
            Teacher teacher1=json.parseObject(content);
    
            assertThat(teacher1.id).isEqualTo(teacher.id);
            assertThat(teacher1.name).isEqualTo(teacher.name);
        }
    }

    4.3 集成測試

    4.3.1 定義

    集成測試驗證Spring Boot應(yīng)用內(nèi)各組件(Controller、Service、Repository等)之間的交互和協(xié)作。

    其特點是需要啟動Spring上下文環(huán)境(不一定需要啟動Web服務(wù)器),以便在測試代碼中直接使用 @Autowired 等注解。

    4.3.2 適用對象

    在實際工作中,通常對Spring Boot項目的各個組件進行集成測試,包括但不限于:

    1. 驗證Controller層能否正確調(diào)用Service層方法,并處理返回的數(shù)據(jù)。
    2. 驗證Service層能否正確地與Repository層交互,實現(xiàn)數(shù)據(jù)庫的讀寫操作。
    3. 驗證Repository層能否正確地與數(shù)據(jù)庫交互,實現(xiàn)數(shù)據(jù)的讀寫操作。

    4.3.3 @SpringBootTest

    @SpringBootTest 注解在測試開始前創(chuàng)建一個完整的Spring應(yīng)用程序上下文。

    示例代碼

    @SpringBootTest
    @ActiveProfiles("test") // 指定運行環(huán)境
    public class TeacherServiceIntegrationTest {
    
        @Autowired
        private TeacherService teacherService; // 注入TeacherService
    
        @Test
        public void testCount() {
            int result=teacherService.countByName("張三"); // 調(diào)用Service的方法
            assertEquals(1, result); // 斷言結(jié)果
        }
    }

    4.3.4 @WebMvcTest

    @WebMvcTest 注解在測試開始前啟動一個針對Spring MVC的測試環(huán)境。

    僅加載指定的Controller,而不會加載應(yīng)用程序的其他組件。如果測試中需要這些其他組件,使用 @MockBean 來模擬這些組件的行為。

    使用 MockMvc 對象模擬發(fā)送HTTP請求,并驗證控制器的響應(yīng)。

    示例代碼

    @WebMvcTest(TeacherApi.class) // 指定需要測試的Controller
    @ActiveProfiles("test") // 指定運行環(huán)境
    public class TeacherApiWebMvcTest {
    
        @Autowired
        private MockMvc mockMvc; // 注入MockMvc
    
        @MockBean
        private TeacherService teacherService; // Mock掉Service層的接口
    
        @Test
        public void testCount() throws Exception {
            when(teacherService.countByName("張三")).thenReturn(1); // Mock掉Service的方法,指定返回值
    
            mockMvc.perform(MockMvcRequestBuilders.get("/api/teacher/count").param("name", "張三")) // 執(zhí)行一個GET請求
                    .andExpect(MockMvcResultMatchers.status().isOk()) // 驗證響應(yīng)狀態(tài)碼為200
                    .andExpect(MockMvcResultMatchers.jsonPath("$.count").value(1)); // 斷言響應(yīng)結(jié)果中JSON屬性"count"的值為1
        }
    }

    MockMvc的常用方法

    1. perform(request): 執(zhí)行一個HTTP請求。
    2. andExpect(status().isOk()): 斷言響應(yīng)狀態(tài)碼為200(HttpStatus.OK)。
    3. andExpect(content().contentType(MediaType.APPLICATION_JSON)): 斷言響應(yīng)內(nèi)容類型為JSON。
    4. andExpect(content().string(containsString("expectedString")): 斷言響應(yīng)內(nèi)容包含指定的字符串。
    5. andExpect(jsonPath("$.key").value("expectedValue")): 斷言響應(yīng)內(nèi)容中JSON屬性"key"的值為"expectedValue"。
    6. andExpect(content().json("expectedJson")): 斷言響應(yīng)內(nèi)容為"expectedJson"。
    7. andReturn(): 獲取MvcResult實例,可以在斷言完成后獲取詳細的響應(yīng)內(nèi)容。
    8. print(): 在控制臺上打印執(zhí)行請求的結(jié)果。

    jsonPath的常用表達式

    1. $.key: 獲取根節(jié)點屬性"key"的值。
    2. $..key: 獲取所有名為"key"的屬性的值,無論它們在哪一層。
    3. $.array[0]: 獲取名為"array"的數(shù)組屬性中的第一個元素的值。
    4. $.array[:2]: 獲取名為"array"的數(shù)組屬性中的前兩個元素的值。
    5. $.array[-1:]: 獲取名為"array"的數(shù)組屬性中的最后一個元素的值。

    4.3.5 @DataJpaTest

    @DataJpaTest注解在測試開始前啟動一個Spring上下文環(huán)境,只加載JPA相關(guān)的組件,如實體、倉庫等。

    配置一個內(nèi)存數(shù)據(jù)庫,以避免對真實數(shù)據(jù)庫的影響,并提高測試的速度。

    默認開啟事務(wù),并在測試完成后回滾事務(wù)。

    示例代碼

    @DataJpaTest
    @ActiveProfiles("test") // 指定運行環(huán)境
    public class TeacherDaoTest {
    
        @Autowired
        private TeacherDao teacherDao; // 注入Repository
    
        @Test
        public void testCount() {
            int result=teacherDao.countByName("張三"); // 調(diào)用Repository的方法
            assertEquals(1, result); // 斷言結(jié)果
        }
    }

    TestEntityManager

    TestEntityManager是Spring提供的一個用于測試的EntityManager,用于在測試中對實體進行增刪改查操作。

    @DataJpaTest
    @ActiveProfiles("test") // 指定運行環(huán)境
    public class TeacherDaoTest {
    
        @Autowired
        private TeacherDao teacherDao; // 注入Repository
    
        @Autowired
        private TestEntityManager entityManager; // 注入TestEntityManager
    
        @Test
        public void testCount() {
            // 使用TestEntityManager創(chuàng)建一個Teacher實體
            Teacher teacher=new Teacher();
            teacher.name="張三";
            teacher.age=20;
            entityManager.persist(teacher);
    
            // 調(diào)用Repository的方法
            int result=teacherDao.countByName("張三");
    
            // 斷言結(jié)果
            assertEquals(1, result);
        }
    }

    4.3.6 測試數(shù)據(jù)庫

    集成測試通常需要使用數(shù)據(jù)庫。

    如果使用真實的數(shù)據(jù)庫,每次測試都會對數(shù)據(jù)庫進行讀寫操作,這樣會導(dǎo)致測試變得緩慢,而且會對數(shù)據(jù)庫造成影響。

    為了解決這個問題,可以使用內(nèi)存數(shù)據(jù)庫。內(nèi)存數(shù)據(jù)庫是一種特殊的數(shù)據(jù)庫,它將數(shù)據(jù)存儲在內(nèi)存中,而不是磁盤上,因此它的讀寫速度非常快,適合用于測試。

    配置

    在Spring Boot項目中使用H2數(shù)據(jù)庫,需要在pom.xml中添加以下依賴:

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>test</scope>
    </dependency>

    使用

    application-test.properties中添加以下配置:

    spring.datasource.url=jdbc:h2:mem:testdb
    spring.datasource.username=sa
    spring.datasource.password=spring.datasource.driver-class-name=org.h2.Driver
    spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
    spring.datasource.schema=classpath:test-schema.sql
    spring.datasource.data=classpath:test-data.sql

    application-test.properties中,指定了H2數(shù)據(jù)庫的連接信息。

    還指定了初始化腳本test-schema.sqltest-data.sql,用于初始化數(shù)據(jù)庫的表結(jié)構(gòu)和數(shù)據(jù)。

    test-schema.sql

    CREATE TABLE teacher (
        id INT PRIMARY KEY AUTO_INCREMENT,
        name VARCHAR(255) NOT NULL,
        age INT NOT NULL
    );

    test-data.sql

    INSERT INTO teacher (name, age) VALUES ('張三', 20);
    INSERT INTO teacher (name, age) VALUES ('李四', 30);

    4.4 端到端測試

    4.4.1 定義

    端到端測試驗證整個程序的功能是否按照預(yù)期工作。

    其特點是需要啟動完整的應(yīng)用程序上下文,并模擬客戶端與HTTP接口進行交互。

    4.4.2 適用對象

    在實際工作中,我們通常對使用SpringBoot開發(fā)的整個應(yīng)用程序進行端到端測試。

    4.4.3 RANDOM_PORT

    端到端測試需要啟動完整的應(yīng)用程序上下文。

    使用@SpringBootTest注解的webEnvironment屬性,將應(yīng)用程序上下文設(shè)置為隨機端口啟動。

    4.4.4 TestRestTemplate

    TestRestTemplate是Spring提供的類,用于發(fā)送HTTP請求并驗證接口的響應(yīng)是否符合預(yù)期。

    示例代碼

    @SpringBootTest(webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT) // 將應(yīng)用上下文設(shè)置為隨機端口啟動
    @ActiveProfiles("test")
    public class TeacherApiEndToEndTest {
    
        @Autowired
        private TestRestTemplate restTemplate;
    
        @Test
        public void testSearchTeacher() {
            // 發(fā)送GET請求,訪問"/teachers?name=John"
            ResponseEntity<TeacherCount> response=restTemplate.getForEntity("/teachers?name=John", TeacherCount.class);
    
            // 驗證響應(yīng)狀態(tài)碼是否為200(HttpStatus.OK)
            Assertions.assertEquals(HttpStatus.OK, response.getStatusCode());
    
            // 驗證響應(yīng)中JSON屬性"count"的值是否為2
            Assertions.assertEquals(2, response.getBody().getCount());
        }
    }

    4.4.5 soup

    Jsoup庫用于HTML解析。

    基本使用

    以下是一些Jsoup的基本使用方法:

    1. 解析HTML字符串:
    String html="<html><head><title>測試頁面</title></head>"
                 + "<body><p>這是一個測試頁面</p></body></html>";
    Document doc=Jsoup.parse(html);
    1. 獲取HTML元素:
    Element titleElement=doc.select("title").first();
    1. 獲取元素的文本內(nèi)容:
    String titleText=titleElement.text();
    1. 獲取元素的屬性值:
    Element linkElement=doc.select("a").first();
    String href=linkElement.attr("href");

    測試網(wǎng)頁

    以下是一個使用Jsoup測試網(wǎng)頁的例子:

    @Test
    public void testHtmlPage() {
        // 測試HTML頁面的標題
        Document doc=Jsoup.connect("http://www.example.com").get();
        String title=doc.title();
        assertThat(title).isEqualTo("Example Domain");
    }

    4.4.6 Selenium

    Selenium用于模擬瀏覽器行為。

    通過Selenium,程序可以自動化地操作瀏覽器,模擬用戶在瀏覽器中的交互行為。

    核心類

    1. WebDriver:用于模擬瀏覽器的行為,如打開網(wǎng)頁、輸入內(nèi)容、點擊按鈕等。
    2. WebElement:用于表示網(wǎng)頁中的元素,如文本框、按鈕等。
    3. By:用于定位網(wǎng)頁中的元素,如根據(jù)ID、CSS選擇器等。

    WebDriver的常用方法

    1. get(url): 打開指定的網(wǎng)頁。
    2. findElement(by): 根據(jù)定位器定位網(wǎng)頁中的元素。
    3. sendKeys(text): 在文本框中輸入文本。
    4. click(): 點擊按鈕。
    5. getText(): 獲取元素的文本內(nèi)容。

    測試網(wǎng)頁

    以下是一個使用Selenium測試網(wǎng)頁的例子:

    public class TeacherSearchFrontendTest {
    
        @Test
        public void testSearchTeacher() {
            // 設(shè)置ChromeDriver的路徑(注意根據(jù)實際情況修改路徑)
            System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
    
            // 創(chuàng)建Chrome瀏覽器的WebDriver
            WebDriver driver=new ChromeDriver();
    
            // 打開目標網(wǎng)頁
            driver.get("http://localhost:8080");
    
            // 找到搜索框并輸入教師姓名
            WebElement searchInput=driver.findElement(By.id("search-input"));
            searchInput.sendKeys("John");
    
            // 找到搜索按鈕并點擊
            WebElement searchButton=driver.findElement(By.id("search-button"));
            searchButton.click();
    
            // 驗證搜索結(jié)果數(shù)量是否符合預(yù)期
            WebElement resultCount=driver.findElement(By.id("result-count"));
            Assertions.assertEquals("Found 2 teachers", resultCount.getText());
    
            // 關(guān)閉瀏覽器
            driver.quit();
        }
    }

    4.5 附:測試思想

    4.5.1 測試金字塔

    • 單元測試:測試金字塔的基礎(chǔ),最為常見也最為頻繁。針對代碼中的最小單元進行測試,如方法和類。單元測試的重點在于找出方法的邏輯錯誤,確保所有的方法達到預(yù)期的結(jié)果。單元測試的粒度應(yīng)保證足夠小,有助于精確定位問題。
    • 集成測試:測試金字塔的中層,數(shù)量通常少于單元測試,多于端對端測試。集成測試的重點是檢查幾個單元組合在一起后是否能正常工作。
    • 端對端測試:測試金字塔的頂層,數(shù)量最少。端對端測試的目的是從用戶的角度模擬完整的應(yīng)用場景,驗證多個單元/模塊是否可以協(xié)同工作。

    4.5.2 測試原則

    • 單一職責:每個測試都應(yīng)當專注于一個具體的功能或者邏輯,避免在一個測試中試圖驗證多個邏輯。
    • 獨立性:每個單元測試都應(yīng)該獨立于其他測試,不能互相調(diào)用,也不能依賴執(zhí)行的順序。
    • 一致性:測試應(yīng)當能夠在任何時間、任何環(huán)境下得出相同的結(jié)果。
    • 全面覆蓋:盡可能覆蓋所有可能的路徑和情況。包括所有正常情況、邊界情況以及可能的錯誤情況。
    • 自動化:測試應(yīng)當是自動化的,可以無人值守地運行。
    • 易于理解:測試代碼也是代碼,應(yīng)當遵循良好的代碼編寫實踐。
    • 快速反饋:優(yōu)秀的測試應(yīng)該可以在短時間內(nèi)完成并給出反饋。
    • BCDE原則:Border,邊界值測試,Correct,正確的輸入,并得到預(yù)期的結(jié)果,Design,與設(shè)計文檔相結(jié)合,來編寫單元測試,Error,強制錯誤信息輸入,以及得到預(yù)期的結(jié)果。
    • 測試數(shù)據(jù):測試數(shù)據(jù)應(yīng)由程序插入或?qū)耄詼蕚鋽?shù)據(jù)。

    Docker 是一種開源的容器化平臺,用于構(gòu)建、發(fā)布和運行應(yīng)用程序。

    它可以將應(yīng)用程序及其依賴項打包到一個獨立的、可移植的容器中,從而實現(xiàn)了應(yīng)用程序在不同環(huán)境中的一致性和可移植性。

    如果本地搭建 docker,我們開發(fā)人員就可以快速構(gòu)建、部署和擴展應(yīng)用程序了,而無需擔心環(huán)境差異或依賴項沖突的問題。

    系統(tǒng)和硬件要求

    • 操作系統(tǒng)要求:系統(tǒng)是 windows10,現(xiàn)在電腦硬件低,大都是64位

    硬件:

    • 處理器:至少是支持硬件虛擬化(Intel VT-x 或 AMD-V)的雙核處理器。
    • 內(nèi)存:建議至少4G
    • 硬盤:至少準備5G的空間
    • 虛擬化支持:在BIOS設(shè)置中啟用了硬件虛擬化技術(shù)(如Intel VT-x 或 AMD-V),下面會詳細介紹

    一、開啟 Hyper-V

    安裝 Docker Desktop 需要啟用 Hyper-V 和 Windows 容器功能。

    【控制面板】-> 【所有控制面板項】-> 【程序和功能】

    打開【啟用或關(guān)閉 Windows 功能】窗口,勾選:

    安裝完成需要重啟才會生效,先不重啟,稍后再重啟。

    二、安裝 docker

    1、下載 docker 安裝程序

    docker 官網(wǎng) windows 版下載地址:https://hub.docker.com/editions/community/docker-ce-desktop-windows

    下載完成后是一個exe文件【Docker for Windows Installer.exe】

    2、安裝 docker

    雙擊安裝文件進行安裝,等待一小段時間,安裝完成后會出現(xiàn)下面的窗口:

    這時候點擊【close and log out】會重啟電腦。

    三、使用 docker

    啟動【Docker for Windows】,啟動命令窗口,輸入命令【docker version】可查看 docker 版本,如:

    3.1 使用 docker 安裝 sql server 數(shù)據(jù)庫

    1.以管理員身份啟動命令窗口,輸入命令【docker search mssql】:

    2.輸入命令【docker pull microsoft/mssql-server-linux】下載鏡像:

    3.創(chuàng)建并運行容器

    輸入命令【docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=Password01!" -p 1445:1433 --name MSSQL_loan -d microsoft/mssql-server-linux】

    4.登錄容器

    輸入命令【docker exec -it MSSQL_loan /bin/bash】:

    5.連接到 sqlcmd

    輸入命令【/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'Password01!'】:

    6.創(chuàng)建數(shù)據(jù)庫并進行測試

    輸入命令【CREATE DATABASE TestDB】創(chuàng)建一個數(shù)據(jù)庫:

    1> CREATE DATABASE TestDB
    2> go
    

    輸入命令【select name,database_id,create_date from sys.Databases】查看已存在的數(shù)據(jù)庫:

    7.使用客戶端 mssms 連接創(chuàng)建的 sqlserver

    服務(wù)器名稱就是你的本地【IP,端口】,如本次前面設(shè)置的是1445,

    3.2 使用 docker 還原 sql server 數(shù)據(jù)庫

    1.在容器內(nèi)創(chuàng)建一個目錄

    如果是繼續(xù)上面的步驟,則先退出【quit】到容器管理中:

    如果沒有登錄容器,則先登錄容器【docker exec -it MSSQL_loan /bin/bash】。

    使用命令【mkdir /var/opt/mssql/backup】創(chuàng)建一個目錄,然后再退出容器:

    3.將數(shù)據(jù)庫備份文件(.bak文件)復(fù)制到容器中

    使用命令【docker cp E:/job/techTest/docker/sqlserver/Loan.bak MSSQL_loan:/var/opt/mssql/backup】進行復(fù)制:

    4.還原數(shù)據(jù)庫

    先登錄容器【docker exec -it MSSQL_loan /bin/bash】,列出備份數(shù)據(jù)文件的邏輯名,使用命令【/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'Password01!' -Q 'RESTORE FILELISTONLY FROM DISK="/var/opt/mssql/backup/Loan.bak"' | tr -s ' ' | cut -d ' ' -f 1-2】:

    還原數(shù)據(jù)庫,使用命令【/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'Password01!' -Q 'RESTORE DATABASE Loan FROM DISK="/var/opt/mssql/backup/Loan.bak" WITH MOVE "Loan" TO "/var/opt/mssql/data/Loan.mdf" , MOVE "Loan_log" TO "/var/opt/mssql/data/Loan.ldf"'】:

    注:個人不是很推薦在windows中安裝 docker,日常使用 docker 還是建議安裝在 linux 上的,當然沒有 Linux 服務(wù)器的情況下,windows 安裝 docker 也是不錯的選擇。

網(wǎng)站首頁   |    關(guān)于我們   |    公司新聞   |    產(chǎn)品方案   |    用戶案例   |    售后服務(wù)   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區(qū)    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權(quán)所有