Docker部署前后端分離項目——多項目共享環境部署

目錄

一、簡介

二、文件目錄結構

三、前端部署流程(多nginx)

3.1 前端打包

3.2 編寫部署文件——項目1(consult-system)

3.3 編寫部署文件——項目2(person-system)

3.4 前端部署至linux服務器

3.5 訪問方式

四、前端部署流程二(同nginx)

4.1 前端打包

4.2 編寫部署文件

4.3 部署上線

五、后端部署流程(共用mysql和redis)

5.1 創建共享網絡

5.2 后端打包

5.3 編寫部署文件——項目1(consult-system)

5.4 編寫部署文件——項目2(person-system)

5.5 后端部署至linux服務器

六、開放端口

七、數據庫加載


一、簡介

????????多項目共享環境部署,指的是在同一臺服務器或同一個?Docker?主機上,通過?Docker?Compose?等工具,將多個前后端項目的公共基礎服務(如數據庫、緩存、消息隊列等)統一部署為共享服務,各項目通過自定義網絡等方式共同使用這些服務,從而實現資源復用、簡化運維、提升協作效率的一種部署方式。

????????這里有2個項目(即項目1和項目2),將項目部署在linux上,并且項目之間共用redis和mysql

二、文件目錄結構

文件目錄結構

文件解釋

# 多項目的共同環境
shared-services.yml 
# 后端docker編排
consult-compose.yml和person-compose.yml
# 后端jar包
consultingPlatform......jar和personnel.....jar
# 前端build文件
/consult-system/frontend/dist和/person-system/frontend/dist
# 前端docker編排
docker-compose.yml
# nginx配置
nginx.conf

三、前端部署流程(多nginx)

3.1 前端打包

前端利用node命令來打包項目,得到dist文件夾

# 前端通過構建命令,打包項目
npm run build
npm run build:prod # 生產環境
npm run build:dev  # 開發環境

3.2 編寫部署文件——項目1(consult-system)

dev-ops/consult-system/frontend/docker-compose.yml文件

# docker-compose -f docker-compose.yml up -d
version: "3"services:consult-nginx:image: nginx:alpineports:- 81:81 # 宿主機端口:容器端口volumes:- ./dist:/usr/share/nginx/html- ./nginx.conf:/etc/nginx/nginx.confprivileged: true #這個必須,解次nginx的文件調用的權限問題

dev-ops/consult-system/frontend/nginx.conf文件

# 添加必要的上下文塊
http {# 包含默認的 MIME 類型include       /etc/nginx/mime.types;default_type  application/octet-stream;server {# 端口,需要與docker-compose一致listen 81;server_name localhost;# 靜態文件根目錄root /usr/share/nginx/html;index index.html;# 開啟 gzip 壓縮gzip on;gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;# 處理前端路由(如 Vue/React 的 history 模式)location / {try_files $uri $uri/ /index.html;}# 禁止訪問 .env 等敏感文件location ~ /\.(?!well-known).* {deny all;}
}
}# 添加 events 塊(可選但推薦)
events {worker_connections 1024;
}

3.3 編寫部署文件——項目2(person-system)

dev-ops/person-system/frontend/docker-compose.yml文件

# docker-compose -f docker-compose.yml up -d
version: "3"services:person-nginx:image: nginx:alpineports:- 82:82 # 宿主機端口:容器端口volumes:- ./dist:/usr/share/nginx/html- ./nginx.conf:/etc/nginx/nginx.confprivileged: true #這個必須,解次nginx的文件調用的權限問題

dev-ops/person-system/frontend/nginx.conf文件

# 添加必要的上下文塊
http {# 包含默認的 MIME 類型include       /etc/nginx/mime.types;default_type  application/octet-stream;server {# 端口,需要與docker-compose一致listen 82;server_name localhost;# 靜態文件根目錄root /usr/share/nginx/html;index index.html;# 開啟 gzip 壓縮gzip on;gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;# 處理前端路由(如 Vue/React 的 history 模式)location / {try_files $uri $uri/ /index.html;}# 禁止訪問 .env 等敏感文件location ~ /\.(?!well-known).* {deny all;}
}
}# 添加 events 塊(可選但推薦)
events {worker_connections 1024;
}

3.4 前端部署至linux服務器

step1:通過xftp將dev-ops整個文件夾上傳至linux根目錄

step2:對項目1(consult-system)部署

cd /dev-ops/consult-system/frontend
docker-compose -f docker-compose.yml up -d
# 查看是否啟動
docker psCONTAINER ID   IMAGE                            COMMAND                  CREATED          STATUS                    PORTS                                        NAMES
...
e6753c3329b0   nginx:alpine                     "/docker-entrypoint.…"   28 minutes ago   Up 28 minutes             80/tcp, 0.0.0.0:81->81/tcp                   frontend-consult-nginx-1
...

step3:對項目2(person-system)部署

cd /dev-ops/person-system/frontend
docker-compose -f docker-compose.yml up -d
# 查看是否啟動
docker psCONTAINER ID   IMAGE                            COMMAND                  CREATED          STATUS                    PORTS                                        NAMES
...
e6753c3329b0   nginx:alpine                     "/docker-entrypoint.…"   28 minutes ago   Up 28 minutes             80/tcp, 0.0.0.0:82->82/tcp                   frontend-person-nginx-1
...

3.5 訪問方式

通過ip+端口的形式進行訪問

項目1:http://xxx.xxx.xxx.xxx:81

項目2:http://xxx.xxx.xxx.xxx:82

四、前端部署流程二(同nginx)

4.1 前端打包

項目配置靜態資源路徑——(后續與nginx配合使用

  • vue項目
// 項目一
// vue.config.js
module.exports = {publicPath: process.env.NODE_ENV === 'production' ? '/consult/' // 生產環境路徑: '/' // 開發環境路徑
}// 項目二
// vue.config.js
module.exports = {publicPath: process.env.NODE_ENV === 'production' ? '/person/' // 生產環境路徑: '/' // 開發環境路徑
}
  • react項目
// 項目一
// package.json
{"homepage": "/consult/", // 生產環境路徑
}// 項目二
// package.json
{"homepage": "/person/", // 生產環境路徑
}
  • umi(react)項目
// .umirc.ts
export default defineConfig({define: {"process.env.UMI_ENV": process.env.UMI_ENV,},// 靜態資源路徑,根據process.env.UMI_ENV判斷publicPath: process.env.UMI_ENV === "prod" ? "/person/" : "/",
});
// package.json"scripts": {"build:prod": "cross-env UMI_ENV=prod umi build",},

?前端利用node命令來打包項目,得到dist文件夾

# 前端通過構建命令,打包項目
npm run build
npm run build:prod # 生產環境
npm run build:dev  # 開發環境

4.2 編寫部署文件

docker-compose-common-nginx.yml

# docker-compose -f docker-compose-common-nginx.yml up -d
version: "3"services:consult-nginx:image: nginx:alpineports:- 80:80 # 宿主機端口:容器端口volumes:# 掛載consult-system- ./consult-system/frontend/dist:/usr/share/nginx/html/consult-system# 掛載person-system- ./person-system/frontend/dist:/usr/share/nginx/html/person-system- ./common-nginx.conf:/etc/nginx/nginx.confprivileged: true #這個必須,解次nginx的文件調用的權限問題

common-nginx.conf

events {worker_connections 1024;
}http {include       /etc/nginx/mime.types;default_type  application/octet-stream;# 全局開啟 gzip 壓縮gzip on;gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;server {listen 80;server_name localhost;# 禁止訪問敏感文件(全局生效)location ~ /\.(?!well-known).* {deny all;}# ======================# 配置 consult-system 應用# 訪問路徑:http://localhost/consult/# ======================location /consult/ {alias /usr/share/nginx/html/consult-system/;index index.html;try_files $uri $uri/ /consult/index.html;}# ======================# 配置 person-system 應用# 訪問路徑:http://localhost/person/# ======================location /person/ {# 指向 person-system 的靜態文件目錄alias /usr/share/nginx/html/person-system/;index index.html;# 處理前端路由 (history 模式)try_files $uri $uri/ /person/index.html;}# ======================# 可選:默認重定向# ======================location = / {# 可重定向到其中一個應用return 302 /consult/;# 或顯示歡迎頁面# root /usr/share/nginx/html;# index welcome.html;}location = /person {return 301 /person/;}location = /consult {return 301 /consult/;}}
}

4.3 部署上線

cd /dev-opsdocker-compose -f docker-compose-common-nginx.yml up -d# 查看,是否存在 nginx80端口容器
docker ps 

五、后端部署流程(共用mysql和redis)

5.1 創建共享網絡

dev-ops/shared-services.yml

# docker-compose -f shared-services.yml up -d# -f:指定使用的 Docker Compose 配置文件(默認文件名是 docker-compose.yml)
# up:啟動所有服務(包括構建鏡像)
# -d:在后臺運行容器
version: "3"networks:my-network:driver: bridge# 添加網絡名稱確保唯一性name: shared-networkservices:# 共享的 MySQL(兩個項目共用)mysql:image: mysql:5.7# 添加容器名稱確保可尋址container_name: shared-mysqlports:- 13306:3306environment:TZ: Asia/ShanghaiMYSQL_ROOT_PASSWORD: 123456networks:- my-networkhealthcheck:test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]interval: 5stimeout: 10sretries: 10start_period: 15s# 共享的 Redis(兩個項目共用)redis:image: redis:6.2container_name: shared-redisrestart: alwaysprivileged: trueports:- 16379:6379networks:- my-networkvolumes:- ./redis/redis.conf:/usr/local/etc/redis/redis.confcommand: redis-server /usr/local/etc/redis/redis.confhealthcheck:test: ["CMD", "redis-cli", "ping"]interval: 10stimeout: 5sretries: 3

??通過xftp將dev-ops整個文件夾上傳至linux根目錄,并構建共享網絡

cd /dev-ops/
docker-compose -f shared-services.yml up -d# 查看自定義網絡,列表中有shared-network
docker network ls
# 查看網絡信息,container下有mysql和redis
docker network inspect <網絡名稱/id>

5.2 后端打包

進入后端項目的pom.xml添加構建打包代碼,然后在命令行執行 nvm clean package,將會在target文件夾下生成jar包,注意:記得修改主函數,也就是后端啟動類

<build><!-- 1. 最終生成的JAR文件名 --><finalName>${project.artifactId}-${project.version}</finalName><!-- 2. 資源文件處理配置 --><resources><resource><directory>src/main/resources</directory><filtering>true</filtering> <!-- 啟用資源過濾,替換占位符 --><includes><include>**/*.properties</include><include>**/*.xml</include><include>**/*.yml</include><include>**/*.yaml</include></includes></resource><!-- 包含靜態資源 --><resource><directory>src/main/resources</directory><filtering>false</filtering><includes><include>static/**</include><include>templates/**</include><include>public/**</include></includes></resource></resources><!-- 3. 測試資源處理 --><testResources><testResource><directory>src/test/resources</directory><filtering>true</filtering></testResource></testResources><!-- 4. 插件配置 --><plugins><!-- 編譯器插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.11.0</version> <!-- 更新到最新版本 --><configuration><source>${java.version}</source><target>${java.version}</target><encoding>${project.build.sourceEncoding}</encoding><compilerArgs><arg>-parameters</arg> <!-- 保留方法參數名,方便MyBatis使用 --></compilerArgs></configuration></plugin><!-- 跳過測試 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.1.2</version><configuration><skipTests>true</skipTests> <!-- 構建時跳過測試 --></configuration></plugin><!-- Spring Boot打包插件 --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><mainClass>xxx.xxx.xxx.xxx</mainClass><skip>false</skip> <!-- 確保執行打包 --><executable>true</executable> <!-- 生成可執行JAR --><layers><enabled>true</enabled> <!-- 啟用分層打包,優化Docker鏡像構建 --></layers></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal> <!-- 重新打包包含所有依賴 --></goals></execution></executions></plugin><!-- 資源過濾插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><version>3.3.1</version><configuration><delimiters><delimiter>@</delimiter> <!-- 使用@作為占位符分隔符,避免與Spring沖突 --></delimiters><useDefaultDelimiters>false</useDefaultDelimiters></configuration></plugin></plugins></build>

5.3 編寫部署文件——項目1(consult-system)

dev-ops/consult-system/consult-compose.yml文件

# docker-compose -f consult-compose.yml up -d
# -f:指定使用的 Docker Compose 配置文件(默認文件名是 docker-compose.yml)
# up:啟動所有服務(包括構建鏡像)
# -d:在后臺運行容器
version: "3"networks:shared-network: # 使用共享網絡與共享服務在同一網絡下,是shared-services.yml中定義的網絡external: trueservices:consult-system-behind:image: consult-system-behind:latestbuild: . # 在同一級下尋找Dockerfile并構建,默認是尋找Dockerfileports: # 暴露端口- 8877:8877# 記得jdbc:mysql://{mysql容器名}:3306/person_system?environment:- TZ=PRC- SERVER_PORT=8877- APP_CONFIG_API_VERSION=v1- APP_CONFIG_CROSS_ORIGIN=*- SPRING_DATASOURCE_USERNAME=root- SPRING_DATASOURCE_PASSWORD=123456- SPRING_DATASOURCE_URL=jdbc:mysql://shared-mysql:3306/consult_platform?serverTimezone=UTC&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Shanghai- SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver- SPRING_HIKARI_POOL_NAME=Retail_HikariCP- REDIS_SDK_CONFIG_HOST=shared-redis- REDIS_SDK_CONFIG_PORT=6379# 使用共享網絡networks:- shared-network

dev-ops/consult-system/Dockfile文件

FROM openjdk:8-jre-slim# 作者
MAINTAINER yeqc# 添加應用
ADD consultingPlatform-0.0.1-SNAPSHOT.jar app.jarENTRYPOINT ["java","-jar","/app.jar"]

5.4 編寫部署文件——項目2(person-system)

dev-ops/person-system/person-compose.yml文件

# docker-compose -f person-compose.yml up -d
# -f:指定使用的 Docker Compose 配置文件(默認文件名是 docker-compose.yml)
# up:啟動所有服務(包括構建鏡像)
# -d:在后臺運行容器
version: "3"networks:shared-network: # 使用共享網絡與共享服務在同一網絡下,是shared-services.yml中定義的網絡external: trueservices:person-system-behind:image: person-system-behind:latestbuild: . # 在同一級下尋找Dockerfile并構建,默認是尋找Dockerfileports: # 暴露端口- 8082:8082# 記得jdbc:mysql://{mysql容器名}:3306/person_system?environment:- TZ=PRC- SERVER_PORT=8082- APP_CONFIG_API_VERSION=v1- APP_CONFIG_CROSS_ORIGIN=*- SPRING_DATASOURCE_USERNAME=root- SPRING_DATASOURCE_PASSWORD=123456- SPRING_DATASOURCE_URL=jdbc:mysql://shared-mysql:3306/person_system?serverTimezone=UTC&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Shanghai- SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver- SPRING_HIKARI_POOL_NAME=Retail_HikariCP- REDIS_SDK_CONFIG_HOST=shared-redis- REDIS_SDK_CONFIG_PORT=6379# 把服務加入共享網絡networks:- shared-network

dev-ops/person-system/Dockerfile文件

FROM openjdk:8-jre-slim# 作者
MAINTAINER yeqc# 添加應用
ADD personnel-management-system-behind-0.0.1-SNAPSHOT.jar app.jarENTRYPOINT ["java","-jar","/app.jar"]

5.5 后端部署至linux服務器

?step1:通過xftp將dev-ops整個文件夾上傳至linux根目錄

step2:對項目1(consult-system)部署

cd /dev-ops/consult-system
docker-compose -f consult-compose.yml up -d
# 同理,利用docker ps查看是否存在consult-system-behind:latest

step3:對項目2(person-system)部署

cd /dev-ops/person-system
docker-compose -f consult-compose.yml up -d
# 同理,利用docker ps查看是否存在person-system-behind:latest

六、開放端口

需要在云服務器中開放對應的端口,根據自己設置的端口來開放,我這里的端口如下:

項目1:前端(81)后端(8877)

項目2:前端(82)后端(8082)

七、數據庫加載

通過數據庫可視化工具,輸入自己的云服務器ip、賬號、密碼、端口(13306),進行登錄,執行sql腳本,導入數據

注意:若登錄不上,可能是沒有開放13306端口,需要在云服務器中開放

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/91909.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/91909.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/91909.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

學習筆記(39):結合生活案例,介紹 10 種常見模型

學習筆記(39):結合生活案例&#xff0c;介紹 10 種常見模型線性回歸只是機器學習的 “冰山一角”&#xff01;根據不同的任務場景&#xff08;分類、回歸、聚類等&#xff09;&#xff0c;還有許多強大的模型可以選擇。下面我用最通俗易懂的語言&#xff0c;結合生活案例&#…

BabyAGI 是一個用于自構建自主代理的實驗框架

這個最新的 BabyAGI 是一個用于自構建自主代理的實驗框架 核心是一個新的函數框架 &#xff08;functionz&#xff09;&#xff0c;用于存儲、管理和執行數據庫中的函數。它提供了一個基于圖形的結構&#xff0c;用于跟蹤導入、依賴函數和身份驗證密鑰&#xff0c;并具有自動加…

商業秘密視域下計算機軟件的多重保護困境

作者&#xff1a;邱戈龍、柯堅豪重慶商業秘密律師廣東長昊律師事務所引言&#xff1a;計算機軟件保護的復雜性 在商業秘密保護的宏大版圖中&#xff0c;計算機軟件因其技術密集性和創新性占據著特殊地位。軟件的真正價值不僅在于其代碼本身&#xff0c;更在于其背后的流程、邏…

深入理解 Spring Boot 自動配置原理

Spring Boot 之所以能“開箱即用”&#xff0c;其核心就在于 自動配置機制&#xff08;Auto Configuration&#xff09;。本文將深入剖析 Spring Boot 自動配置的工作原理&#xff0c;從注解入手&#xff0c;再到底層的源碼機制&#xff0c;揭開 Spring Boot 背后的“魔法”。 …

Ubuntu18.04開機啟動執行腳本

#!/bin/bash # 運行 .NET Core 應用程序 dotnet /home/bruce/atg/SmartConsole.dll &# 打開瀏覽器 firefox 給文件權限sudo chmod 777 start.sh運行gnome-session-properties打開系統自帶的一個啟動程序

c語言進階 字符函數和字符串函數

字符函數和字符串函數字符函數和字符串函數1. strlenstrlen 函數詳解模擬實現1.計數器方式2.不能創建臨時變量計數器&#xff08;遞歸&#xff09;3.指針-指針的方式2. strcpystrcpy 函數詳解模擬實現3. strcatstrcat 函數詳解模擬實現4. strcmpstrcmp 函數詳解模擬實現5. strn…

(LeetCode 每日一題) 1233. 刪除子文件夾 (排序)

題目&#xff1a;1233. 刪除子文件夾 思路&#xff1a;排序&#xff0c;時間復雜度0(L*nlogn)。 文件夾a的子文件b&#xff0c;b字符串字典序列一定是大于a的&#xff0c;所以直接將字符串數組folder升序排序。每次只需判斷當前字符串&#xff0c;是否是父文件夾數組v最后一個…

集成算法學習bagging,boosting,stacking

baggibg(rf隨機森林) adaboostibg 用來展示 Project Jupyter | Home 展示源碼 Eclipse IDE | The Eclipse Foundation Eclipse 下載 |Eclipse 基金會 教程8-Adaboost決策邊界效果_嗶哩嗶哩_bilibili (23 封私信) 圖解機器學習神器&#xff1a;Scikit-Learn - 知乎 Baggi…

HOOPS SDK賦能PLM:打造全生命周期3D數據管理與協作能力

在制造業和工業領域&#xff0c;產品全生命周期管理&#xff08;PLM&#xff09; 已成為驅動企業數字化轉型、提升創新力與運營效率的核心引擎。一個高效的PLM平臺不僅需要管理海量的設計數據&#xff0c;還必須在設計、制造、供應鏈、銷售和服務等多個環節之間無縫流轉信息&am…

解決 Selenium 頁面跳轉過快導致的內容獲取問題:從原理到實踐

在使用 Selenium 進行網頁自動化操作時&#xff0c;很多開發者都會遇到一個頭疼的問題&#xff1a;頁面還沒加載完&#xff0c;代碼就已經執行到下一句了。結果要么是元素找不到&#xff0c;要么是獲取的內容不完整&#xff0c;甚至直接拋出異常。今天我們就來聊聊如何優雅地解…

【Python練習】051. 編寫一個函數,實現簡單的定時器功能

051. 編寫一個函數,實現簡單的定時器功能 051. 編寫一個函數,實現簡單的定時器功能 代碼說明: 示例運行: 擴展功能 代碼說明: 實現Python定時器的幾種方法 051. 編寫一個函數,實現簡單的定時器功能 以下是一個簡單的Python函數,用于實現定時器功能。這個定時器可以設置…

springboot基礎-demo

1.創建學生信息表 create table stu(id int unsigned primary key auto_increment comment ID,name varchar(100) comment 姓名,age tinyint unsigned comment 年齡,gender tinyint unsigned comment 性別, 1:男, 2:女,score double(5,2) comment 成績,phone varchar(11) comme…

關于transformer的一些疑點總結

殘差連接的作用 Transformer中的殘差連接&#xff08;Residual Connection&#xff09;是其深層架構能穩定訓練的核心設計之一&#xff0c;主要通過以下機制發揮作用&#xff1a; 1. 緩解梯度消失&#xff0c;支持深層訓練 梯度保護機制&#xff1a;在反向傳播時&#xff0c;…

【終極指南】解決 Windows 11 更新后 Docker 連接 localhost 奇慢(卡頓、超時十幾秒)的通用方案

聰明人能看得出這是 ai 寫的&#xff0c;但也是我親身實踐的&#xff0c;最后讓 ai 總結寫了一篇&#xff0c;放心食用 一、 結論先行&#xff08;直接用&#xff09;問題現象&#xff1a; 升級到某個 Windows 11 版本后&#xff0c;在本地訪問 Docker 容器中部署的任何服務&am…

Stream API

Java 8 引入的 Stream API 是處理集合數據的強大工具&#xff0c;它允許你以聲明式方式處理數據集合&#xff0c;支持各種聚合操作和并行處理。以下是 Stream API 的核心知識點及具體代碼示例&#xff1a; 1. Stream 概述 Stream 是數據渠道&#xff0c;用于操作數據源&#xf…

相機參數的格式與作用

在計算機視覺中&#xff0c;相機標定是非常重要的一步&#xff0c;主要目的是從圖像中恢復出物體的三維信息。為了做到這一點&#xff0c;我們需要了解和使用一系列的數學工具&#xff0c;這些工具描述了相機的成像過程&#xff0c;包括相機的內參、外參、畸變系數、投影矩陣和…

【jvm|基本原理】第四天

摘要&#xff1a;本文簡單分析了Java虛擬機的核心運行機制。首先介紹了基本數據類型在32位和64位虛擬機中的存儲差異&#xff0c;說明slot槽設計以空間換時間的優化思路。其次詳細解析了對象在堆內存中的存儲結構&#xff0c;包括對象頭、對象數據和對齊填充機制。然后探討了方…

Git高級操作與最佳實踐詳解

前言 熟練掌握Git的高級操作可以顯著提高開發效率&#xff0c;優化工作流程&#xff0c;解決復雜問題。本文將詳細介紹Git的高級操作技巧與最佳實踐&#xff0c;幫助開發者更加高效地管理代碼和協作開發。 1. 提交歷史管理 1.1 修改最近的提交 # 修改最近的提交信息 git co…

ElasticSearch:商品SKU+SPU實現join查詢,設計及優化

文章目錄一、SPUSKU1、商品SPU和SKU2、SPU和SKU的關系3、實現SPUSKU父子嵌套查詢1. **嵌套對象&#xff08;Nested Objects&#xff09;**2. **父子關系&#xff08;Parent-Child&#xff09;**3. **應用層關聯&#xff08;Application-Side Join&#xff09;**&#xff08;推薦…

Objective-c 初階 —— Runtime(方法交換 消息傳遞)

一、消息傳遞1、什么是消息[a func1];我們會把這種用方括號來調函數的方式稱為發消息。對于這個例子&#xff0c;就相當于我們給 a 這個對象發了個 func1 的消息&#xff08;個人認為指令更好理解&#xff09;。2、什么是 selectorselector 就是一個函數區分器。它只會給這個方…