springboot H2 linux下搭建使用

這次研究是H2資料庫了,關鍵還是再Linux下進行搭建部署的,被這個資料庫快弄死了弄了4天時間,現在大致可以用了,還有些細節需要修正。

我這邊使用的是springboot集成模式。直接使用程式碼啟停方式的就和我的描述就不一樣了。

H2資料庫有3鐘模式mem,file,remote 3種模式。

記憶體就不說了,這個就是臨時的,我覺得用記憶體還不如jvm記憶體呢。沒啥意思。當然也是由於我沒有細究的緣故。

file模式是本地模式。本地創建相應的資料庫文件,然後進行調用。這裡會存在個問題就是本地用了file之後,我其他電腦想訪問這個資料庫就是沒法打開。報錯是資料庫被佔用。這個是真心難受。

那麼使用remote模式這邊會存在直接springboot啟動起不來。

那麼這會就需要借用H2資料庫官網上的啟動方式了。網址://www.h2database.com/

這裡將最新版的程式下載下來。version 2.1.214這個版本,在本地解壓後bin目錄下有個h2w.bat 文件,windows下直接啟動就好了。Linux下就需要使用指令去啟動了。

相關指令如下:

java -cp h2-2.1.214.jar org.h2.tools.Server -web -webAllowOthers -tcp -tcpAllowOthers -ifNotExists

這裡我詳細說幾個參數webAllowOthers,web管理介面是否在其他IP中可以訪問,tcpAllowOthers ,其他電腦是否可以通過remote模式訪問該系統的H2資料庫,ifNotExists資料庫不存在時是否允許創建,一般linux啟動的時候這個是不開啟的,不然你的linux系統中會充斥著一堆雜七雜八的資料庫。通過linux系統自啟。

如果你想修改默認的tcp埠,那也是可以的需要將這個入參帶上    -tcpPort 19200 

如果大家好奇有哪些入參可以帶入,我在這邊就稍微截點源碼出來:

 1 public void init(String... args) {
 2         // set the serverPropertiesDir, because it's used in loadProperties()
 3         for (int i = 0; args != null && i < args.length; i++) {
 4             if ("-properties".equals(args[i])) {
 5                 serverPropertiesDir = args[++i];
 6             }
 7         }
 8         Properties prop = loadProperties();
 9         port = SortedProperties.getIntProperty(prop,
10                 "webPort", Constants.DEFAULT_HTTP_PORT);
11         ssl = SortedProperties.getBooleanProperty(prop,
12                 "webSSL", false);
13         allowOthers = SortedProperties.getBooleanProperty(prop,
14                 "webAllowOthers", false);
15         setExternalNames(SortedProperties.getStringProperty(prop, "webExternalNames", null));
16         setAdminPassword(SortedProperties.getStringProperty(prop, "webAdminPassword", null));
17         commandHistoryString = prop.getProperty(COMMAND_HISTORY);
18         for (int i = 0; args != null && i < args.length; i++) {
19             String a = args[i];
20             if (Tool.isOption(a, "-webPort")) {
21                 port = Integer.decode(args[++i]);
22             } else if (Tool.isOption(a, "-webSSL")) {
23                 ssl = true;
24             } else if (Tool.isOption(a, "-webAllowOthers")) {
25                 allowOthers = true;
26             }  else if (Tool.isOption(a, "-webExternalNames")) {
27                 setExternalNames(args[++i]);
28             } else if (Tool.isOption(a, "-webDaemon")) {
29                 isDaemon = true;
30             } else if (Tool.isOption(a, "-baseDir")) {
31                 String baseDir = args[++i];
32                 SysProperties.setBaseDir(baseDir);
33             } else if (Tool.isOption(a, "-ifExists")) {
34                 ifExists = true;
35             } else if (Tool.isOption(a, "-ifNotExists")) {
36                 ifExists = false;
37             } else if (Tool.isOption(a, "-webAdminPassword")) {
38                 setAdminPassword(args[++i]);
39             } else if (Tool.isOption(a, "-properties")) {
40                 // already set
41                 i++;
42             } else if (Tool.isOption(a, "-trace")) {
43                 trace = true;
44             }
45         }
46 //            if (driverList != null) {
47 //                try {
48 //                    String[] drivers =
49 //                        StringUtils.arraySplit(driverList, ',', false);
50 //                    URL[] urls = new URL[drivers.length];
51 //                    for(int i=0; i<drivers.length; i++) {
52 //                        urls[i] = new URL(drivers[i]);
53 //                    }
54 //                    urlClassLoader = URLClassLoader.newInstance(urls);
55 //                } catch (MalformedURLException e) {
56 //                    TraceSystem.traceThrowable(e);
57 //                }
58 //            }
59         for (String[] lang : LANGUAGES) {
60             languages.add(lang[0]);
61         }
62         if (allowOthers) {
63             key = null;
64         }
65         updateURL();
66     }
 1 public void init(String... args) {
 2         port = Constants.DEFAULT_TCP_PORT;
 3         for (int i = 0; args != null && i < args.length; i++) {
 4             String a = args[i];
 5             if (Tool.isOption(a, "-trace")) {
 6                 trace = true;
 7             } else if (Tool.isOption(a, "-tcpSSL")) {
 8                 ssl = true;
 9             } else if (Tool.isOption(a, "-tcpPort")) {
10                 port = Integer.decode(args[++i]);
11                 portIsSet = true;
12             } else if (Tool.isOption(a, "-tcpPassword")) {
13                 managementPassword = args[++i];
14             } else if (Tool.isOption(a, "-baseDir")) {
15                 baseDir = args[++i];
16             } else if (Tool.isOption(a, "-key")) {
17                 key = args[++i];
18                 keyDatabase = args[++i];
19             } else if (Tool.isOption(a, "-tcpAllowOthers")) {
20                 allowOthers = true;
21             } else if (Tool.isOption(a, "-tcpDaemon")) {
22                 isDaemon = true;
23             } else if (Tool.isOption(a, "-ifExists")) {
24                 ifExists = true;
25             } else if (Tool.isOption(a, "-ifNotExists")) {
26                 ifExists = false;
27             }
28         }
29     }

TCP server running at tcp://192.168.1.126:9092 (others can connect)
Web Console server running at //192.168.1.126:8082 (others can connect)

在這裡你會發現,tcp的默認埠是9092,web訪問的埠是8082

從這兩張圖中也可以看出,帶不帶埠效果都是一致的。

 

 

當然這些參數你也可以在H2的源碼中找到相應的地方在,在這個類中:org.h2.engine.Constants。

 

在linux系統中直接將其以程式的形式進行啟動後,其他應用就可以通過remote的形式進行調用了。友情提示,啟動H2的時候需要使用nohup進行啟動。

這裡我將我的H2配置資訊發出來

 1 #設置H2驅動
 2 spring.datasource.driver-class-name=org.h2.Driver
 3 #設置H2遠程TCP地址
 4 spring.datasource.url = jdbc:h2:tcp://192.168.?.???/~/test1
 5 #設置web介面是否啟用
 6 spring.h2.console.enabled=true
 7 #設置其他ip地址是否可以訪問webConsole
 8 spring.h2.console.settings.web-allow-others=true
 9 #設置H2默認地址
10 spring.h2.console.path=/h2
11 #實際地址就是 url:埠/程式默認地址/h2 這些配置資訊可以去 org.springframework.boot.autoconfigure.h2下的H2ConsoleProperties中進行查看,真的不是我不想多點參數控制,而是springboot就只開放了這些。這是真心難受啊。

其他小知識,在h2的webConsole控制台如下圖

這裡有個配置功能,然後你一開始點擊是能點擊進去的,進入配置控制介面。但是一保存時候發現一直要輸入密碼,關鍵是我前前後後找了1天都沒找到密碼是哪裡設置的。真心吐血,後面發現,保存之後他就會在windows系統中的用戶目錄下創建一個.h2.server.properties一個文件,自從有了這個文件就需要輸入密碼了。刪掉就沒有了。

後面我通過程式碼跟蹤的形式去查了源碼發現他的登錄介面核心程式碼

 1 private String adminLogin() {
 2         String password = attributes.getProperty("password");
 3         if (password == null || password.isEmpty() || !server.checkAdminPassword(password)) {//將if屏蔽了就可以不用管密碼了
 4             return "adminLogin.jsp";
 5         }
 6         String back = (String) session.remove("adminBack");
 7         session.put("admin", true);
 8         return back != null ? back : "admin.do";
 9     }
10 
11 boolean checkAdminPassword(String password) {
12         if (adminPassword == null) {
13             return false;
14         }
15         byte[] salt = Arrays.copyOf(adminPassword, 32);
16         byte[] hash = new byte[32];
17         System.arraycopy(adminPassword, 32, hash, 0, 32);
18         return Utils.compareSecure(hash, SHA256.getHashWithSalt(password.getBytes(StandardCharsets.UTF_8), salt));
19     }

看到這裡的小夥伴應該知道他的坑爹之處了吧,密碼不能為空,管理員默認密碼也不能為空。關鍵是我執行到adminPassword的時候他是空的。真的是坑爹啊。當然將其屏蔽調就可以了,我調整之後,我的系統進入webConsole的配置介面已經不需要這個該死的密碼認證了。真是白花了我一天的時間,在這裡我為那1天時間默哀10秒鐘。