1. 程式人生 > 其它 >Spring Boot3.0升級,踩坑之旅,附解決方案

Spring Boot3.0升級,踩坑之旅,附解決方案

1. 配置檔案(nginx.conf)

 1 #是註釋行,
 2 #每個有效配置項用 等號 處理,等號前不超過40個字元,等號後不超過400個字元;
 3 
 4  
 5 #[開頭的表示組資訊,也等價於註釋行
 6 #[Socket]
 7 #ListenPort = 5678    
 8 #DBInfo = 127.0.0.1;1234;myr;123456;mxdb_g
 9 
10 #日誌相關
11 [Log]
12 #日誌檔案輸出目錄和檔名
13 #Log=logs/error.log
14 Log=error.log
15 
16 #只打印日誌等級<= 數字 的日誌到日誌檔案中 ,日誌等級0-8
,0級別最高,8級別最低。 17 LogLevel = 8 18 19 #程序相關 20 [Proc] 21 #建立 這些個 worker程序 22 WorkerProcesses = 4 23 24 #是否按守護程序方式執行,1:按守護程序方式執行,0:不按守護程序方式執行 25 Daemon = 1 26 27 #處理接收到的訊息的執行緒池中執行緒數量,不建議超過300 28 ProcMsgRecvWorkThreadCount = 120 29 30 #和網路相關 31 [Net] 32 #監聽的埠數量,一般都是1個,當然如果支援多於一個也是可以的 33 ListenPortCount = 1
34 #ListenPort+數字【數字從0開始】,這種ListenPort開頭的項有幾個,取決於ListenPortCount的數量, 35 ListenPort0 = 80 36 #ListenPort1 = 443 37 38 #epoll連線的最大數【是每個worker程序允許連線的客戶端數】,實際其中有一些連線要被監聽socket使用,實際允許的客戶端連線數會比這個數小一些 39 worker_connections = 2048 40 41 #Sock_RecyConnectionWaitTime:為確保系統穩定socket關閉後資源不會立即收回,而要等一定的秒數,在這個秒數之後,才進行資源/連線的回收
42 Sock_RecyConnectionWaitTime = 150 43 44 #Sock_WaitTimeEnable:是否開啟踢人時鐘,1:開啟 0:不開啟 45 Sock_WaitTimeEnable = 1 46 #多少秒檢測一次是否 心跳超時,只有當Sock_WaitTimeEnable = 1時,本項才有用 47 Sock_MaxWaitTime = 20 48 #當時間到達Sock_MaxWaitTime指定的時間時,直接把客戶端踢出去,只有當Sock_WaitTimeEnable = 1時,本項才有用 49 Sock_TimeOutKick = 0 50 51 #和網路安全相關 52 [NetSecurity] 53 #flood檢測 54 #Flood攻擊檢測是否開啟,1:開啟 0:不開啟 55 Sock_FloodAttackKickEnable = 1 56 #Sock_FloodTimeInterval表示每次收到資料包的時間間隔是100(單位:毫秒) 57 Sock_FloodTimeInterval = 100 58 #Sock_FloodKickCounter表示計算到連續10次,每次100毫秒時間間隔內發包,就算惡意入侵,把他kick出去 59 Sock_FloodKickCounter = 10

2. 標頭檔案(ngx_c_conf.h)

 1 #ifndef NGX_C_CONF_H
 2 #define NGX_C_CONF_H
 3 #include <vector>
 4 #include <stdio.h>
 5 #include <string.h>
 6 //結構定義
 7 typedef struct _CConfItem
 8 {
 9     char ItemName[50];
10     char ItemContent[500];
11 }CConfItem,*LPCConfItem;
12 
13 
14 //類名可以遵照一定的命名規則規範,比如老師這裡,第一個字母是C,後續的單詞首字母大寫
15 class CConfig
16 {
17 //---------------------------------------------------
18 //這段程式碼老師在《c++從入門到精通》 多執行緒這章老師提過 單例設計模式,就是如下這些程式碼,大家即便沒學過,也可以現在學
19 private:
20     CConfig();
21 public:
22     ~CConfig();
23 private:
24     static CConfig *m_instance;
25 
26 public:
27     static CConfig* GetInstance()               //採用的是單例模式中的餓漢式
28     {
29         if(m_instance == nullptr)
30         {
31             //
32             if(m_instance == nullptr)
33             {
34                 m_instance = new CConfig();
35                 static CGarhuishou cl;
36             }
37             //放鎖
38         }
39         return m_instance;
40     }
41     class CGarhuishou  //類中套類,用於釋放物件
42     {
43     public:
44         ~CGarhuishou()
45         {
46             if (CConfig::m_instance)
47             {
48                 delete CConfig::m_instance;
49                 CConfig::m_instance = nullptr;
50             }
51         }
52     };
53 //---------------------------------------------------
54 public:
55     bool Load(const char *pconfName); //裝載配置檔案
56     const char *GetString(const char *p_itemname);
57     int  GetIntDefault(const char *p_itemname,const int def);
58 
59 public:
60     std::vector<LPCConfItem> m_ConfigItemList; //儲存配置資訊的列表
61 };
62 
63 #endif // NGX_C_CONF_H

3. 原始檔(ngx_c_conf.cpp)

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <vector>
  5 
  6 //自定義標頭檔案放下邊,因為g++中用了-I引數,所以這裡用<>也可以
  7 #include "ngx_c_conf.h"   //和配置檔案處理相關的類,名字帶c_表示和類有關
  8 
  9 //擷取字串尾部空格
 10 void Rtrim(char *string)
 11 {
 12     size_t len = 0;
 13     if(string == NULL)
 14         return;
 15 
 16     len = strlen(string);
 17     while(len > 0 && string[len-1] == ' ')   //位置換一下
 18         string[--len] = 0;
 19     return;
 20 }
 21 
 22 //擷取字串首部空格
 23 void Ltrim(char *string)
 24 {
 25     size_t len = 0;
 26     len = strlen(string);
 27     char *p_tmp = string;
 28     if( (*p_tmp) != ' ') //不是以空格開頭
 29         return;
 30     //找第一個不為空格的
 31     while((*p_tmp) != '\0')
 32     {
 33         if( (*p_tmp) == ' ')
 34             p_tmp++;
 35         else
 36             break;
 37     }
 38     if((*p_tmp) == '\0') //全是空格
 39     {
 40         *string = '\0';
 41         return;
 42     }
 43     char *p_tmp2 = string;
 44     while((*p_tmp) != '\0')
 45     {
 46         (*p_tmp2) = (*p_tmp);
 47         p_tmp++;
 48         p_tmp2++;
 49     }
 50     (*p_tmp2) = '\0';
 51     return;
 52 }
 53 
 54 
 55 
 56 //靜態成員賦值
 57 CConfig *CConfig::m_instance = NULL;
 58 
 59 //建構函式
 60 CConfig::CConfig()
 61 {
 62 }
 63 
 64 //解構函式
 65 CConfig::~CConfig()
 66 {
 67     std::vector<LPCConfItem>::iterator pos;
 68     for(pos = m_ConfigItemList.begin(); pos != m_ConfigItemList.end(); ++pos)
 69     {
 70         delete (*pos);
 71     }//end for
 72     m_ConfigItemList.clear();
 73     return;
 74 }
 75 
 76 //裝載配置檔案
 77 bool CConfig::Load(const char *pconfName)
 78 {
 79     FILE *fp;
 80     fp = fopen(pconfName,"r");
 81     if(fp == NULL)
 82         return false;
 83 
 84     //每一行配置檔案讀出來都放這裡
 85     char  linebuf[501];   //每行配置都不要太長,保持<500字元內,防止出現問題
 86 
 87     //走到這裡,檔案開啟成功
 88     while(!feof(fp))  //檢查檔案是否結束 ,沒有結束則條件成立
 89     {
 90         //大家要注意老師的寫法,注意寫法的嚴密性,商業程式碼,就是要首先確保程式碼的嚴密性
 91         if(fgets(linebuf,500,fp) == NULL) //從檔案中讀資料,每次讀一行,一行最多不要超過500個字元
 92             continue;
 93 
 94         if(linebuf[0] == 0)
 95             continue;
 96 
 97         //處理註釋行
 98         if(*linebuf==';' || *linebuf==' ' || *linebuf=='#' || *linebuf=='\t'|| *linebuf=='\n')
 99             continue;
100 
101     lblprocstring:
102         //屁股後邊若有換行,回車,空格等都擷取掉
103         if(strlen(linebuf) > 0)   //strlen不算\0
104         {   //看看末尾的字元是什麼    10代表換行符,13代表回車鍵,32代表空格
105             if(linebuf[strlen(linebuf)-1] == 10 || linebuf[strlen(linebuf)-1] == 13 || linebuf[strlen(linebuf)-1] == 32)
106             {
107                 linebuf[strlen(linebuf)-1] = 0;
108                 goto lblprocstring;
109             }
110         }
111 
112         if(linebuf[0] == 0)
113             continue;
114         if(*linebuf=='[') //[開頭的也不處理
115             continue;
116 
117         //這種 “ListenPort = 5678”走下來;
118         char *ptmp = strchr(linebuf,'=');  //strchr搜尋第一次出現字元=的位置
119         if(ptmp != NULL)
120         {
121             LPCConfItem p_confitem = new CConfItem;                    //注意前邊型別帶LP,後邊new這裡的型別不帶
122             memset(p_confitem,0,sizeof(CConfItem));
123             strncpy(p_confitem->ItemName,linebuf,(int)(ptmp-linebuf)); //等號左側的拷貝到p_confitem->ItemName
124             strcpy(p_confitem->ItemContent,ptmp+1);                    //等號右側的拷貝到p_confitem->ItemContent
125 
126             Rtrim(p_confitem->ItemName);
127             Ltrim(p_confitem->ItemName);
128             Rtrim(p_confitem->ItemContent);
129             Ltrim(p_confitem->ItemContent);
130 
131             //printf("itemname=%s | itemcontent=%s\n",p_confitem->ItemName,p_confitem->ItemContent);
132             m_ConfigItemList.push_back(p_confitem);  //記憶體要釋放,因為這裡是new出來的
133         } //end if
134     } //end while(!feof(fp))
135 
136     fclose(fp); //這步不可忘記
137     return true;
138 }
139 
140 //根據ItemName獲取配置資訊字串,不修改不用互斥
141 const char *CConfig::GetString(const char *p_itemname)
142 {
143     std::vector<LPCConfItem>::iterator pos;
144     for(pos = m_ConfigItemList.begin(); pos != m_ConfigItemList.end(); ++pos)
145     {
146         if(strcasecmp( (*pos)->ItemName,p_itemname) == 0)
147             return (*pos)->ItemContent;
148     }//end for
149     return NULL;
150 }
151 
152 //根據ItemName獲取數字型別配置資訊,不修改不用互斥
153 int CConfig::GetIntDefault(const char *p_itemname,const int def)
154 {
155     std::vector<LPCConfItem>::iterator pos;
156     for(pos = m_ConfigItemList.begin(); pos !=m_ConfigItemList.end(); ++pos)
157     {
158         if(strcasecmp( (*pos)->ItemName,p_itemname) == 0)
159             return atoi((*pos)->ItemContent);
160     }//end for
161     return def;
162 }

4. main函式(用來測試)

 1 #include <stdio.h>
 2 #include <ngx_c_conf.h>
 3 
 4 int main()
 5 {
 6 
 7     CConfig *p_config = CConfig::GetInstance(); //單例類
 8   
 9     if(p_config->Load("C:\\Users\\123\\Documents\\build-test-Desktop_Qt_5_9_9_MinGW_32bit-Debug\\debug\\nginx.conf") == false) //把配置檔案內容載入到記憶體
10     {
11         printf("Load configFile failed\n");
12     }
13     else
14     {   //只是簡單的測試了一下,如果獲取數字型的配置資訊可以用這個GetIntDefault(const char *p_itemname,const int def)函式,直接得到數字
15 printf("Load configFile success\n"); 16 printf("log = %s\n",p_config->GetString("Log")); 17 printf("LogLevel = %s\n",p_config->GetString("LogLevel")); 18 printf("WorkerProcesses = %s\n",p_config->GetString("WorkerProcesses")); 19 printf("Daemon = %s\n",p_config->GetString("Daemon")); 20  } 21 return 0; 22 }