Java 開發者如何入門 Node.js

oschina發表於2014-08-25

  首先, 我必須得承認,作為一個有著十多年開發經驗的java開發者,我已經形成了解決絕大部分問題的固有套路,儘管它們很多時候顯得笨重和繁瑣。 比如說如果要讀取一個檔案,那應該就是初始化一個BufferedReader 例項並傳入一個FileReader,這幾乎是順理成章的,我在很多自認為算得上“企業級”的專案中編寫這樣的程式碼並且很享受這個過程,可以說我就是一個對其他語言不屑一顧的java腦殘粉。     

  如果你正在閱讀這篇博文,你可能已經陷入了我多年前早就陷入的一個誤區,作為一名合格的開發人員應該不斷地學習新的技術並且根據實際工作需求選用適當的技術。儘管我一直在變老並且有朝一日可能會厭煩了java。但是我現在真的發現了一個激動人心的新東西,node.js對於我就像一個兒童得到一個新奇的玩具,在這篇博文中,我將先向您展示如何使用Java EE建立一個簡單的Rest服務來讀取 MongoDB資料庫。然後我會用node.js來實現相同的功能,你會更容易瞭解到這種新的開發語言的激動人心之處。

 從基礎開始——什麼是Node.js?

  首先,我要說明一點,Node.js不是那種“新潮時尚”,只有“潮人”才使用的語言。雖然它是本著這種認知開始,但是我很高興的報告給大家,Node.js是一種成熟的語言——並且在當下這個網際網路時代,它已經找到了其自己的方式進入大型企業,支撐起一些最高流量的網站。Node.js是你技能儲備當中的一個非常實用的工具,在構建穩定、安全和高效能的程式碼上,其便捷度會令你大吃一驚。

  言而總之,Node是一種針對伺服器端活動的語言。它使用了Javascript語言,並且有非常多的庫可用,比如npm模型。你可以把那些npm模型比作Java中的.jar包。當你需要一部分功能,並且不喜歡自己全部編寫這部分程式碼,極有可能在npm模型中已經提供了你正在尋找的特性。

  Node應用程式通常執行時需要實現效率最大化利用非阻塞 I/O 和非同步事件。對於Java開發者來講需要知道的一點是Node應用執行單執行緒中。然而,後端節點程式碼使用多個執行緒進行操作,如網路和檔案訪問。鑑於此,Node對於那些需要實時經驗的應用是完美的選擇。

 繼續——IDE支援

  你可能會像我一樣,在IDE中“生存”和“呼吸”,這可能源於Java實在是太羅嗦了,需要我們在軟體開發過程中編寫恆定的程式碼來完成功能。一旦我們找到了程式碼完成的好處,我們慢慢學會了使用 IDE 進行檔案管理、 除錯和其他非常有用的功能。可以這樣說,我喜歡使用一款IDE並且在使用Nodeb工作時繼續使用它。下面是當前最為第一批支援Node的IDE:

  • Eclipse——這應該很容易上手當你在Java中已經使用它。僅需要安裝Node.js外掛即可。

  • JetBrains IntelliJ IDEA——一款非常流行的商業化的IDE。目前為止,這是我最喜歡的IDE。

  • Microsoft Visual Studio——是的,你沒看錯。Node已經成長到微軟在Visual Studio新增了對其的原生支援。這個實現非常穩定,並且VS是我第二喜歡的IDE。說來也怪,我使用VS僅僅用作一些基礎的Node專案。

  • CodeEnvy——一款基於web的IDE

  • Cloud9——一款基於web的IDE

  • SublimeText 2——沒有多餘裝飾的文字編輯器,由於其輕量級,在開發者中的知名度越來越高。

  這是我工作在Node基礎專案上的最喜歡的幾款IDE。僅僅做個舉例。

 從一個範例開始

  在這篇博文的剩下部分裡,我們將要用Java EE和Node.js結合起來建立一個簡單的REST服務。這個REST服務將會簡單的從MongoDB資料庫裡面讀取資訊並且返回這些結果給請求者。而關於Java應用伺服器和MongoDB資料庫的安裝和配置則不在本文的討論範圍之中。

 建立我們的Java應用

  第一步:配置pom.xml檔案

  我們把這個範例叫做restexample ,我將會使用JBoss EAP應用伺服器。第一件我們要做的事情就是為使用Maven構建系統的依賴管理來配置我們的pom.xml檔案。下面就是包含了我們這個restexample 應用裡面所需要的依賴的pom.xml檔案:

<project xmlns="http://maven.apache.org/POM/4.0.0"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <groupId>restexample</groupId>
       <artifactId>restexample</artifactId>
       <packaging>war</packaging>
       <version>1.0</version>
       <name>restexample</name>
       <repositories>
           <repository>
               <id>eap</id>
               <url>http://maven.repository.redhat.com/techpreview/all</url>
               <releases>
                   <enabled>true</enabled>
               </releases>
               <snapshots>
                   <enabled>true</enabled>
               </snapshots>
           </repository>
       </repositories>
       <pluginRepositories>
           <pluginRepository>
               <id>eap</id>
               <url>http://maven.repository.redhat.com/techpreview/all</url>
               <releases>
                   <enabled>true</enabled>
               </releases>
               <snapshots>
                   <enabled>true</enabled>
               </snapshots>
           </pluginRepository>
       </pluginRepositories>
       <properties>
           <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
           <maven.compiler.source>1.6</maven.compiler.source>
           <maven.compiler.target>1.6</maven.compiler.target>
       </properties>
       <dependencies>
           <dependency>
               <groupId>org.jboss.spec</groupId>
               <artifactId>jboss-javaee-6.0</artifactId>
               <version>3.0.2.Final-redhat-4</version>
               <type>pom</type>
               <scope>provided</scope>
           </dependency>
           <dependency>
               <groupId>org.mongodb</groupId>
               <artifactId>mongo-java-driver</artifactId>
               <version>2.9.1</version>
           </dependency>
           </dependencies>
       </project>

  酷,相當的詳細,但是我希望你們能夠理解裡面的程式碼,在這篇博文中我假設讀者都已經瞭解Java,因此我不準備解釋裡面的細節了。

  第二步:建立beans.xml檔案並且設定我們的servlet對映

  作為範例的一部分,我們將會對我們的資料庫訪問類使用CDI(上下文依賴注入)。根據官方的CDI配置說明,一個應用要使用CDI的話就要在該應用的 WEB-INF 目錄裡面包含一個beans.xml檔案。因此我們就來建立這個檔案並且按照我們所需的資訊來配置它。進入到你的 /src/main/webapp/WEB-INF 目錄然後建立一個 beans.xml檔案,加入下面的程式碼:

<?xml version="1.0"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
  http://jboss.org/schema/cdi/beans_1_0.xsd"/>

  我們也需要在 web.xml 檔案裡面為我們的RESI API設定servlet對映。在 /src/main/webapp/WEB-INF 目錄的檔案裡面加入下面的servlet對映元素:

<servlet-mapping>
   <servlet-name>javax.ws.rs.core.Application</servlet-name>
   <url-pattern>/ws/*</url-pattern>
</servlet-mapping>

  第三步:建立DBConnection類

  到這一步,我們已經建立好專案並且我們的pom.xml檔案已經包含了MongoDB資料庫的驅動依賴,記得要確保所需要的驅動已經被打包好在我們的應用裡面。下一件事我們就要建立一個類用來管理資料庫的連線。建立一個新的檔案命名為 DBConneection.java,把這個檔案放置到 /src/main/java/com/strongloop/data 目錄裡面,然後再這個檔案裡面加入下面的程式碼:

  注意:要確保你安裝MongoDB資料庫配置好適當的連線授權細節資訊!

package com.strongloop.data;
 
import java.net.UnknownHostException;
 
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;
 
import com.mongodb.DB;
import com.mongodb.Mongo;
 
@Named
@ApplicationScoped
public class DBConnection {
 
   private DB mongoDB;
 
   public DBConnection() {
       super();
   }
 
   @PostConstruct
   public void afterCreate() {
       String mongoHost = "127.0.0.1"
       String mongoPort = "27001"
       String mongoUser = "strongloop;
       String mongoPassword = "rocks";
       String mongoDBName = "restexample";
       int port = Integer.decode(mongoPort);
 
       Mongo mongo = null;
       try {
           mongo = new Mongo(mongoHost, port);
       } catch (UnknownHostException e) {
           System.out.println("Couldn't connect to MongoDB: " + e.getMessage()
                   + " :: " + e.getClass());
       }
 
       mongoDB = mongo.getDB(mongoDBName);
 
       if (mongoDB.authenticate(mongoUser, mongoPassword.toCharArray()) == false) {
           System.out.println("Failed to authenticate DB ");
       }
 
   }
 
   public DB getDB() {
       return mongoDB;
   }
 
}

  第四步:把資料匯入到MongoDB中(mmmm啤酒)

  在我們的專案中,我們想要載入所有名稱為Pabst的啤酒列表。如果你不熟悉啤酒行業,你可以試下Pabst Brewing公司生產的美式淡啤。這些啤酒上面帶有藍綬帶和柯爾特手槍圖案,他們包含所有的麥芽糖飲料種類。

  首先你需要下載一個json檔案,裡面包含需要返回的所有資料。你可以用下面的URL來實現這點:

  https://dl.dropboxusercontent.com/u/72466829/beers.json

  下載結束後,使用mongoimport命令把它匯入到資料庫中,命令如下:

$ mongoimport --jsonArray -d yourDBName -c beers --type json --file /tmp/beers.json -h yourMongoHost --port yourMongoPort -u yourMongoUsername -p yourMongoPassword

  你可以看到如下結果:

connected to: 127.0.0.1:27017
Tue Jun 10 20:09:55.436 check 9 24
Tue Jun 10 20:09:55.437 imported 24 objects

  第5步: 建立Beer模型物件

  我們已經建立了一個資料庫連線類並且已經把啤酒資訊載入到MongoDB資料庫裡了,是時候建立一個模型物件來控制我們的啤酒資訊了。建立一個新檔案,名為Beer.java並把它放到/src/main/java/com/strongloop/data目錄下。建立好該檔案後,在其中新增如下程式碼:

package com.strongloop.data;
 
public class Beer {
   private String id;
   private String name;
   private String description;
 
   public String getId() {
       return id;
   }
   public void setId(String id) {
       this.id = id;
   }
   public String getName() {
       return name;
   }
   public void setName(String name) {
       this.name = name;
   }
   public String getDescription() {
       return description;
   }
   public void setDescription(String description) {
       this.description = description;
   }
}

  注意: 提供好的JSON檔案中包含了更多我們將會使用到的資訊,所以可以找出來看看,並向其中新增一些額外的功能來拓寬你的學習經驗。

  第6步: 建立REST服務

  猜猜看該幹什麼了?不錯,我們終於準備好要建立基於REST的web服務了,它使我們可以獲取到上一個步驟當中載入進來的啤酒資訊。為此,我們需要建立一個新的名為BeerWS.java的檔案,並把它放到/src/main/java/com/strongloop/webservice目錄下。建立好之後,新增下列程式碼:

package com.strongloop.webservice;
 
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import com.strongloop.data.DBConnection;
import com.strongloop.data.Beer;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
 
@RequestScoped
@Path("/beers")
public class BeerWS {
 
   @Inject
   private DBConnection dbConnection;
 
   private DBCollection getBeerCollection() {
       DB db = dbConnection.getDB();
       DBCollection beerCollection = db.getCollection("beers");
       return beerCollection;
   }
 
   private Beer populateBeerInformation(DBObject dataValue) {
       Beer theBeer = new Beer();
       theBeer.setName(dataValue.get("name"));
       theBeer.setDescription(dataValue.get("name"));
       theBeer.setId(dataValue.get("_id").toString());
 
       return theBeer;
   }
 
   // 獲取所有啤酒
   @GET()
   @Produces("application/json")
   public List<Beer> getAllBeers() {
       ArrayList<Beer> allBeersList = new ArrayList<Beer>();
 
       DBCollection beers = this.getBeerCollection();
       DBCursor cursor = beers.find();
       try {
           while (cursor.hasNext()) {
               allBeersList.add(this.populateBeerInformation(cursor.next()));
           }
       } finally {
           cursor.close();
       }
 
       return allBeersList;
   }
}

  第7步: 瀏覽著啤酒資訊傻樂

  喔,搞定。我們已經寫好了一個REST服務,可以從資料庫中獲取所有的啤酒資訊。現在把你的程式碼部署到你的應用伺服器吧, 在瀏覽器中開啟下列地址看看它是否工作正常:

  http://yourserverlocation/ws/beers

  如果所有東西都正常,你將會看到所有的啤酒資訊列表,如下圖所示:

restexample

  建立 Node 應用

  如果你按照上面的步驟使用java進行程式設計,你會意識到使用javaEE建立應用盡管進展很快,但是建立一個類似REST服務的簡單應用還是很麻煩。不要誤解,我仍然很喜歡用javaEE,但是發現對於很多場景,比如建立返回json資料的REST服務,Node更適用。接下來,我們將要使用StrongLoop的LoopBack API建立一個簡單的web服務。另外,我會向你展示如何在蘋果OSX系統上安裝Node。

  步驟1:安裝 Node

  最簡單的安裝Node的方式是通過一個相容大部分作業系統的二進位制包。開啟瀏覽器訪問下面的網頁,根據你的作業系統下載適用的版本:http://nodejs.org/download/

  下載完成後,你會看到下面的內容:

  如果你用的是Mac OSX,點選通用的.pkg檔案。這會把安裝程式儲存到你本機中。下載了該檔案之後,雙擊它就可以啟動安裝程式,你會看到下列安裝對話方塊:

wizard

  一路預設的安裝下去,成功安裝之後,點選close按鈕來退出安裝程式。

  相當簡單,是吧?

  步驟2:使用NPM安裝LoopBack

  現在本地系統中已經安裝了Node,接下來要安裝StroopLoop公司提供的LoopBack包。LoopBack是一個開放的API原始碼包,當你學習使用Node開發、部署軟體時,LoopBack可以使程式設計更簡單。

  為了安裝LoopBack,我們要使用npm命令列,它是Node語言核心的一部分。NPM是一個官方的包管理工具,用於安裝應用程式依賴的類庫或模版。如果你是一名java程式設計師,你可以把NPM比作Maven。使用Maven構建專案,開發人員可以在pom.xml中配置專案依賴的jar包或模版。當專案開始編譯時,Maven會下載所有依賴的檔案,並將jar包引入到專案中。NPM工作原理和Maven相同,對於一些特殊的專案,它使用package.json檔案來配置專案依賴的檔案。你也可以使用命令列方式將依賴的檔案下載到本地系統中。如果這些內容你不理解,不要擔心,在接下來的步驟裡我們會詳細描述package.json檔案。

  為了安裝LoopBack, 我們使用一個簡單的命令列來下載和安裝所有依賴的檔案。開啟你的window命令列視窗,輸入下面命令:

$ npm install -g strongloop

  提示:安裝時,你可能需要使用其它使用者帳號來執行這個命令。

  這個命令列是什麼含義呢?-g參數列示告訴npm我們想要安裝strong-cli包。-g引數使這個包對任何系統和應用程式都相容。一旦你執行了上面的命令,NPM會下載所有依賴的檔案。下載的時間視網速而定,可能需要幾分鐘。

  步驟3:建立應用程式

  使用LoopBack API建立一個應用程式很簡單。 開啟你的window命令列視窗,使用下面的命令來建立一個新的應用程式restexample.

$ slc loopback

  接下來它會提示輸入專案根路徑的名稱。 在這個示例中,使用restexample。 接下來它會提示輸入應用程式名稱。 使用預設值restexample。

  slc命令現在已經建立一個名稱為restexample的LoopBack應用程式,並且已經配置了這個應用程式。 如果再次執行上面的命令,仍然使用restexample命名,LoopBack會建立一個新的目錄。 可以使用cd命令來修改應用程式的根路徑。

$ cd restexample

  現在我們已經建立完一個應用程式,接下來我們將MongoDB配置為程式的資料來源。 

  步驟4:定義資料來源

  為了連通MongoDB,我們需要給應用程式增加一個資料來源,執行以下命令即可:

  $ slc loopback:datasource

  在彈出的提示符下,可以輸入任意自定義的資料來源名稱,這裡選擇myMongo

  [?] Enter the data-source name: myMongo

  這樣我們就將後端的資料來源定義附加到由StrongLoop支援的真實聯結器上面.這裡我們從列表選擇MongoDB聯結器.

  [?] Select the connector for myMongo:
  PostgreSQL (supported by StrongLoop)
  Oracle (supported by StrongLoop)
  Microsoft SQL (supported by StrongLoop)
  MongoDB (supported by StrongLoop)
  SOAP webservices (supported by StrongLoop)
  REST services (supported by StrongLoop)
  Neo4j (provided by community)
  (Move up and down to reveal more choices)

  步驟5:指向真實的資料來源

  為了連通MongoDB,我們需要指向真實際的MongoDB例項.LoopBack在datasource.json檔案中定義了所有的資料來源配置資訊.這個檔案位於應用程式的root/server目錄.開啟這個檔案,按照如下的方式,為MongoDB增加一個資料來源:

{
 
 "db": {
   "name": "db",
   "connector": "memory"
 },
 "myMongo": {
   "name": "myMongo",
   "connector": "mongodb"
   "url": "mongodb://localhost:27017/restexample"
 }
}

  注意:要保證為MongoDB資料庫提供正確的 連線 URL.針對這個例子,我建立了一個名為 restexample 的資料庫,它用來作為資料來源.

  步驟6:匯入資料到MongoDB(mmmmm 啤酒)

  就像本文Java部分說到的那樣,我們需要載入資料集到MongoDB資料庫中.如果你已經按照本文說到的方法完成了這個步驟,然後打算使用同一個資料庫,你可以忽略步驟6,直接跳到步驟7.

  首先,你需要下載一個包含所有要返回資訊的JSON檔案,可以從如下的URL獲取:

  https://dl.dropboxusercontent.com/u/72466829/beers.json

  資料集檔案下載完畢後,直接使用如下的mongoimport命令將它載入到資料庫:

  $ mongoimport --jsonArray -d yourDBName -c beers --type json --file /tmp/beers.json -h yourMongoHost --port

  你應該可以看到如下的結果:

  connected to: 127.6.189.2:27017
  Tue Jun 10 20:09:55.436 check 9 24
  Tue Jun 10 20:09:55.437 imported 24 objects

  步驟7:創造我們自己的啤酒模型

  在Java世界裡,由此可以想到物件模型.它代表這一個物件,只是在這裡,這個物件是啤酒.LoopBack通過命令列,提供了一種建立模型物件的簡便方式.開啟終端視窗,進入到工程資料夾,輸入如下命令:

  $ slc loopback:model

  這將會開啟一個互動式的會話來定義模型.首先需要輸入的是模型名稱,這裡輸入"beer".接下來會提示,這個模型應該附加到的資料來源,這裡選擇之前建立的myMongo資料來源.

  [?] Enter the model name: beer
  [?] Select the data-source to attach beer to:
  db (memory)
  myMongo (mongodb)

  接下來提示,是否通過REST將此API暴露出來.當然,這裡希望這樣.

  [?] Expose beer via the REST API? Yes

  最後,為模型選擇網路複數名,這裡模型名為beer,所以複數為beers(預設).敲擊Enter鍵接受預設值.

  [?] Custom plural form (used to build REST URL):

  接下來會提示定義模型屬性.對這個示例程式,我們關注名稱和對啤酒的描述.

  Enter an empty property name when done.
  [?] Property name: name

  只要敲擊了Enter,就會提示輸入各個指定屬性的資料型別.第一個項是name,這裡選擇字串型別.選擇字串型別,然後敲擊Enter.

  [?] Property type: (Use arrow keys)
  string
  number
  boolean
  object
  array
  date
  buffer
  geopoint
  (other)

  接下來,按照同樣的方式建立description屬性,接著會要求輸入資料型別.它同樣是一個字串型別,選擇字串選項,然後敲擊Enter.

  Let's add another beer property.
  Enter an empty property name when done.
  [?] Property name: description
  invoke loopback:property
  [?] Property type: string
  [?] Required? Yes

  祝賀!你已經使用LoopBack結合Node完成了模型物件的建立.如果想檢視在這個過程中真正建立了什麼,可以開啟位於應用程式root/common/models目錄的beer.json檔案,滾動到這個檔案的最後,將會看到如下模型:

{
 "name": "beer",
 "base": "PersistedModel",
 "properties": {
   "name": {
     "type": "string",
     "required": true
   },
   "description": {
     "type": "string",
     "required": true
   }
 },
 "validations": [],
 "relations": {},
 "acls": [],
 "methods": []
}

  這裡可以看到,我們建立了一個模型,同時,name和description屬性已經賦予了這個模型.

  在/server/model-config.js檔案中,可以注意到,檔案中包含一些額外的欄位,包括public和datasource.其中public域指定我們希望通過一個REST網路服務將此模型暴露給外部.datasource域則指定這個模型的CRUD操作將會用到的資料來源.

 "beer": {
    "dataSource": "myMongo",
    "public": true
  }

  步驟8:沉浸在看到beers的喜悅中

  祝賀!你已經建立了第一個Node.js應用程式,其中包含可以獲取beer資訊的REST網路服務.最後,我們需要做的就是部署這個應用程式.

  慶幸的是,部署是已經很容易的事情.可以通過在應用程式根目錄執行如下命令來完成:

  $ slc run

  只要應用程式一執行,就可以通過瀏覽器轉到如下的URL來確認部署是否成功:

  http://0.0.0.0:3000/api/beers

  相當酷,是不是?

  LoopBack同時也包含了一個允許檢視應用程式所有可用服務的頁面,包括Beer模型和我們建立的REST服務,將瀏覽器指向如下的URL即可檢視:

  http://0.0.0.0:3000/explorer

  頁面載入成功後,你會看到下面的介面,我們已經建立了beers節點作為部落格的一部分,我把/beers端點進行高亮顯示了:

explorer1

  你可以點選/beers來展開可供呼叫的API,你可以操作並測試一下,如下圖所示:

explorer2

 結論

  在這篇博文中,我展示瞭如何使用java EE 去建立一個rest服務,這個服務能夠返回Pabst啤酒公司的啤酒產品清單資料。 之後我又使用node.js以及基於node.js的loopback框架使用很少的程式碼實現了相同功能的rest服務。 最重要的是,LoopBack API  還對beer實體的增刪查改提供了預設的實現,使得我們不用再寫一行程式碼就得到了一個具有完整增刪查改功能的rest服務。

  下面的清單對博文中涉及的javaEE和node.js各自特性進行一個對比:

Feature

Java EE

Node.js

完善的IDE支援

Yes, 多種IDE供選擇,包括 Eclipse, Sublime and Idea

Yes,  多種IDE供選擇, Visual Studio, Eclipse, Sublime

依賴管理

Maven

NPM

有企業級專案採用

Yes

Yes

龐大的元件生態系統

Yes

Yes

需要 JVM

Yes

No

通用開發框架

Spring, JEE

Express

資料庫支援

Yes

Yes

ORM 框架

Yes

Yes

測試框架

Yes

Yes

 接下來的內容?

  •  即將釋出的Node v0.12 將帶來至少8個激動人心的新特性,它們會是什麼呢?訪問 “What’s New in Node.js v0.12” 頁面瞭解更多.

  • 對Node相關的培訓和認證感興趣? StrongLoop 公司提供各種服務滿足您的需求。

  原文地址:http://strongloop.com/strongblog/node-js-java-getting-started/

相關文章