已經習慣在開發和演示環境使用h2來代替大號數據庫很長時間了。 Embedded 的啟動方式,快速,小巧,該有的都有了,sql和oracle, db2,mysql兼容性都不錯。唯一的問題是,Embedded 方式運行時無法使用工具來查看數據情況,雖然可以通過UT來做測試,但是有些時候還是挺不方便的。

今天瀏覽h2的網站,發現文檔已經做了更新,現在H2的使用模式支持三種
 * Embedded mode (local connections using JDBC)
 * Remote mode (remote connections using JDBC or ODBC over TCP/IP)
 * Mixed mode (local and remote connections at the same time)
 
使用模式增加了一種MixedMode模式,即可以使用Embedded的方式來使用h2的同時, 還可以再啟動一個服務來接受遠程連接。

看了一下,實現還是很簡單的

 

public class H2Server {
 
private int port = 9081;
 
private Server server = null;
 
protected final Log logger = LogFactory.getLog(H2Server.class);

 
 
public int getPort() {
  
return port;
 }


 
public void setPort(int port) {
  
this.port = port;
 }


 
public void start() {
  
try {
   server 
= Server.createTcpServer( new String[] "-tcpPort",  "" + port }).start();
   logger.info(
"start the H2 MixedMode server on port:" + port);
  }
 catch (SQLException e) {
   e.printStackTrace();
   logger.error(e);
   logger.error(
"fail to start the h2 Assist server..");
  }

 }

 
 
public void stop() {
  
if (server != null{
   server.shutdown();
  }

 }



在應用啟動時找個地方起來, 現在就可以用squirrel之類的客戶端工具通過“jdbc:h2:tcp://localhost:9081/~/test”的格式進行連接了。

這段代碼其實和remote mode沒有任何區別,不過在mixed mode中,remote訪問只是輔助手段,所以啟動點可以在任何位置,這樣配置要靈活一些。在我的應用里,我就先對主連接做判斷,是嵌入的h2方式時才啟動這個服務。也可以弄個配置參數決定是否要啟動。

if (dbc.isH2()) {
   logger.info(
" use h2 datbase ");
   
if (!dbc.checkTableIfExist()) {
    logger.info(
" create h2 db table now ");
    dbc.createTable();
    logger.info(
" insert  h2 db init data ");
    dbc.insertInitData();
   }

   h2MixedModeServer 
= new H2Server();
   
new Thread() {
    
public void run() {
     h2MixedModeServer.start();
    }

   }
.start();
  }


h2的文檔中代碼樣例的內容較少,要自己查看test目錄下的測試代碼,順便試了一下,其實1年前的版本就已經支持此功能了,只是文檔未做同步更新而已,這也算是開源項目的一個共同問題吧。

如果覺得第三方工具不夠專業和兼容,也可以使用h2自身帶的管理Console,找到h2發布包的bin目錄下的h2.bat, 運行會打開一個瀏覽器窗口,在里面設置連接即可, 完全基于web方式操作,功能挺全的。

作者還真是超級小強,順手用不到100k的代碼實現了一個 web container。本著八卦到底的原則,順便d了一下他是怎么實現系統托盤和啟動瀏覽器的。

 

if (osName.startsWith("Windows")) {
                Runtime.getRuntime().exec(
"rundll32 url.dll,FileProtocolHandler " + url);
            }
 else if (osName.startsWith("Mac OS X")) {
                
// Runtime.getRuntime().exec("open -a safari " + url);
                
// Runtime.getRuntime().exec("open " + url + "/index.html");
                Runtime.getRuntime().exec("open " + url);
            }
 else {
                System.out.println(
"Please open a browser and go to "+ url);
            }


系統托盤使用了java6的特性,不過做了一個判斷。 小強同志此處有點失誤,干嘛不再做個判斷,如果是6版本則使用Desktop來啟動瀏覽器,這樣可以增加對linux的支持。