乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      node.js從入門到菜鳥——資源無法載入?你需要學會地址解析

       風聲之家 2015-05-08

      node.js是什么似乎已經不需要我多為贅述了,非阻塞的服務器語言、JS書寫的后臺代碼,無數(shù)的文章已經很好的展示了node的魅力與展望。關于node.js的安裝,大家不妨參考博客園聶微東的http://www.cnblogs.com/Darren_code/archive/2011/10/31/nodejs.html (node.js初體驗),這篇文章很好的綜述了node.js的一個基礎(從安裝到體驗到模塊的一個入門,個人感覺是一篇很好的文章),相信通過東哥的這篇文章大家可以對node有一個初步的了解。

      node是一門很有意思的框架,它能夠讓一個長期執(zhí)迷于前端開發(fā)的攻城濕(忘記了還有一種語言叫后端語言。。。)能夠覺得很舒適(編碼習慣都一樣),但是也同樣會讓一個新手覺得無所適從(為什么么有從入門到精通哩?參考書在哪里???)。這是一個前端高手為之一亮(也許只亮了一眼o(╯□╰)o),新手眼前一暈(if you want to find more information,please read the source(╯□╰)o)的框架。為了讓和我一樣的新手能夠多多少少摸到一點門路,我以身試法,來為新手找一條路~

      本文旨在新手入門,所學尚淺,代碼水準有限,這也僅僅只是一個基本入門的筆記,高手可以笑一笑然后點關閉了。。。

      首先我假設你已經安裝好了node(http:///#download,0.6.14已經很成熟了),那么首先我們來進行一個入門的編碼分析。

      在進行分析之前,我們先來想一下以前的服務器端語言框架的工作原理。首先,用戶通過瀏覽器來訪問我們的應用。然后服務器通過對端口的監(jiān)聽,來接收網(wǎng)絡端的request請求,并進行相應的處理。最后再將處理的結果返回客戶端。

      好了,那么我們可以開始了。首先是服務器,要是沒有辦法啟動服務器,那么一切都是閑的。我們也許用過很多服務器端的語言(PHP、JAVA、ASP等等),接收HTTP請求并提供Web頁面的過程似乎不用我們來做,apache和IIS似乎都會幫我們來完成。但是在node里,這一步必須你自己做。我們來實現(xiàn)的不僅僅是一個應用,還需要實現(xiàn)HTTP處理的服務器。

      好像很復雜的樣子,但對于node這并不是什么復雜的東西。我們即將進行一個HTTP服務器的初步學習,但是在學習之前我們需要溫習(預習?)一下node的模塊機制。

      node采取的是模塊機制(和JS差不多),通過對模塊的導入我們可以聲明變量并將導入的模塊的實例化對象賦給變量并加以使用。具體各個模塊的使用方法以及用途請參考API,這里就不說了。。。

      好了,我們回來看看HTTP服務器的構成。首先,我們先對HTTP模塊進行一次請求:

      var http = require("http");

      在node中require方法用于對各個模塊的引入,在這里我們需要對http模塊加以使用時就可以導入。導入后將之賦予http變量,然后對http變量進行操作。讓我們以hello world作為例子:

      1 http.createServer(function(request, response) {
      2 response.writeHead(200, {"Content-Type": "text/plain"});
      3 response.write("Hello World");
      4 response.end();
      5 }).listen(12345,”127.0.0.1”);

      每每看到hello world時內心都會有一絲變態(tài)的快意。。。

      讓我們來回憶一下剛才的問題:實現(xiàn)一個http的服務器。其實這個很簡單,http模塊自帶的createServer方法就可以完成。該方法只有一個參數(shù),類型為函數(shù),在接口文檔中的定義是“始終接收request事件”。而server.listen方法(server就是剛才通過createServer創(chuàng)建的server)的參數(shù)是(port, [hostname], [callback]),第一個是監(jiān)聽的端口號,第二個和第三個是可選項,第二個是主機名稱,第三個回調函數(shù)。這個函數(shù)只在綁定端口后進行調用。

      接下來是回調函數(shù),回調函數(shù)的參數(shù)有兩個,第一個是客戶端發(fā)送的request,第二個是服務器端的response。這段代碼進行了一個簡單的響應操作。首先是書寫了一個響應頭,響應頭參數(shù)包括狀態(tài)碼、原因描述以及頭部內容。狀態(tài)碼即http狀態(tài)碼,例如200、404、500之類的。原因描述與頭部內容可選,具體的就參見網(wǎng)絡報頭的書寫了,這里就不多說了(其實我也不會。。。)。writehead方法必須寫在end方法之前,這個是肯定的。。。

      response的write方法就和JS的write所做的工作一樣,就是向頁面寫入數(shù)據(jù),雖然原理不盡相同,但目前沒有準備去鉆研這部分源碼的我們可以忽略了。。。最后是end方法,它有兩個可選參數(shù),分別是data與encoding。該方法用于所有的響應頭與響應正文輸出之后,進行響應的終結,并將管道流中的所有響應數(shù)據(jù)輸出。簡單地說就是在響應最后加上去的東西,它執(zhí)行后會將響應執(zhí)行。如果該方法帶有參數(shù),那么就相當于先調用了response.write(data, encoding)方法,之后再調用無參數(shù)的end方法。

      好了,最簡單的一個http服務器已經工作起來了。當用戶訪問127.0.0.1的12345端口時服務器會監(jiān)聽到這一端口的request請求并書寫報頭與最簡單的helloworld于頁面上,用戶得到響應之后會在瀏覽器中顯示響應的內容,也就是helloworld。這個最簡單的服務器已經搭好了,但我們不能只滿足于這一點。

      在繼續(xù)下一步的學習之前,我想給所有沒有使用過JS或者不怎么使用的同學大體的講述一下一個也許你們會略微奇怪的參數(shù)傳遞方法——函數(shù)傳遞。

      在JS中,函數(shù)與數(shù)字、字符串等都是以var定義的,在參數(shù)傳遞的過程中所接受的參數(shù)也是var這種弱類型的。而function類型也是作為弱類型傳遞,當我們將一個函數(shù)進行傳遞時,所得到的不是該函數(shù)的返回值,而是這個函數(shù)本身。也就是說,這個函數(shù)在運行時會變成傳遞到的函數(shù)的本地變量(自己都覺得好亂。。。)。

      讓我們回憶一下剛才的例子,在creatServer方法中我們使用了一個匿名函數(shù)作為參數(shù),現(xiàn)在我們把這個匿名函數(shù)提出來:

      復制代碼
       1 var http = require("http");
      2 var serverhandel = function(request, response) {
      3 response.writeHead(200, {"Content-Type": "text/plain"});
      4 response.write("Hello World");
      5 response.end();
      6 }
      7 function serverRequest (){
      8 http.createServer(serverhandel).listen(12345);
      9 }
      10 exports. serverRequest = serverRequest;
      復制代碼

      exports即module.exports對象,在node中可以作為全局變量的賦予。也就是說它一般用來定義全局變量的,多用于模塊間的變量傳遞。在此我需要簡單說一下JS的模塊機制,JS中的模塊多用閉包進行包裹(我也不知道這么說對不對),而在閉包中定義的局部變量則無法在全局展開使用,也就是說別的地方調用這個模塊時不能將其中的局部變量單獨的進行使用。而exports則可以在載入模塊后將該函數(shù)載入全局變量的作用鏈中。

      說到這大家也應該明白了,我們要進行一次模塊引用。將這段代碼存入serverRequest.js中,然后建立一個index.js文件,然后引用serverRequest模塊:

      1 var server = require(“./serverRequest”);
      2 server. serverRequest();

      這樣我們就進行了一個最基本的小模塊的搭建,也初步的了解了一下node的模塊體系。那么下一步我們就要進行下連個個非常重要的模塊的學習,也就是url模塊與path模塊。

      url模塊的作用是從請求中獲取請求的url并進行處理,它有著幾個常用的方法:

      1 url.parse(string).pathname;
      2 url.parse(string).query;

      第一個方法的作用是獲取url請求部分的域名之后的路徑名稱,第二個方法獲取的則是通過get向服務器傳遞的參數(shù)。

      而path模塊的作用是解決文件路徑問題,我們這次先學習三個方法:

      1 path.extname(p);
      2 path.join([path1], [path2], [...]);
      3 path.exists(p, [callback]);

      第一個方法是獲取擴展名的方法,參數(shù)是url路徑。第二個方法是做路徑拼接使用,用來標準化最終路徑,參數(shù)是需要拼接的路徑。第三個方法是檢驗路徑存在與否,第一個參數(shù)是標準化的路徑,第二個是可選的回調函數(shù),無論路徑存在與否都會被調用,函數(shù)有一個exist參數(shù),標示路徑是否存在。

      好了,現(xiàn)在我們就可以通過這兩個模塊進行一個簡單的路徑服務器的搭建了。通過這個服務器的搭建,我們可以對本地的靜態(tài)網(wǎng)站進行部署,對于頁面以及網(wǎng)頁所需要載入的各種資源進行尋址,最后對請求的資源進行反饋。

      復制代碼
       1 //請求模塊
      2 var http = require('http');
      3 var url=require('url');
      4 var fs = require("fs"); //在這里先導入文件模塊,僅僅做一個簡單的操作,具體有關文件模塊的學習在之后的文件服務器上會進行進一步的學習。
      5 var path = require("path");
      6 //創(chuàng)建一個http服務器
      7 var server=http.createServer(start).listen(12345);
      8 //依據(jù)路徑獲取返回內容類型字符串,用于http返回頭
      9 var getContentType=function(filePath){
      10 var contentType="";
      11 //使用路徑解析模塊獲取文件擴展名
      12 var extension=path.extname(filePath);
      13 switch(extension){
      14 case ".html":
      15 contentType= "text/html";
      16 break;
      17 case ".js":
      18 contentType="text/javascript";
      19 break;
      20 case ".css":
      21 contentType="text/css";
      22 break;
      23 case ".gif":
      24 contentType="image/gif";
      25 break;
      26 case ".jpg":
      27 contentType="image/jpeg";
      28 break;
      29 case ".png":
      30 contentType="image/png";
      31 break;
      32 case ".ico":
      33 contentType="image/icon";
      34 break;
      35 default:
      36 contentType="application/octet-stream";
      37 }
      38 return contentType; //返回內容類型字符串
      39 }
      40 //Web服務器主函數(shù),解析請求,返回Web內容
      41 var funWebSvr = function (req, res){
      42 //獲取請求的url
      43 var url=req.url;
      44 //使用url解析模塊獲取url中的路徑名
      45 var pathName = url.parse(reqUrl).pathname;
      46 if (path.extname(pathName)=="") {
      47 //如果路徑沒有擴展名
      48 if (pathName.length<2) {//如果是默認域名
      49 pathName+="/";
      50 }
      51 else{
      52 pathName+=".html";
      53 }
      54 }
      55 else{
      56 if (path.extname(pathName)!=".html"){
      57 pathName=".."+ pathName;
      58 }
      59 }
      60 if (pathName.charAt(pathName.length-1)=="/"){
      61 //如果訪問目錄
      62 pathName+="login.html"; //指定為默認網(wǎng)頁
      63 }
      64 var filePath = pathName;
      65 //使用路徑解析模塊,組裝實際文件路徑
      66 if (pathName.charAt(pathName.length).search(/./) == -1) {
      67 filePath = libPath.join("./html",pathName);
      68 };
      69 //判斷文件是否存在
      70 libPath.exists(filePath,function(exists){
      71 if(exists){//文件存在
      72 //在返回頭中寫入內容類型
      73 res.writeHead(200, {"Content-Type": funGetContentType(filePath) });
      74 //創(chuàng)建只讀流用于返回
      75 var stream = libFs.createReadStream(filePath, {flags : "r", encoding : null});
      76 //指定如果流讀取錯誤,返回404錯誤
      77 stream.on("error", function() {
      78 res.writeHead(404);
      79 res.end("<h1>404 Read Error</h1>");
      80 });
      81 //連接文件流和http返回流的管道,用于返回實際Web內容
      82 stream.pipe(res);
      83 }
      84 else {//文件不存在
      85 //返回404錯誤
      86 res.writeHead(404, {"Content-Type": "text/html"});
      87 res.end("<h1>404 Not Found</h1>");
      88 }
      89 });
      90 }
      復制代碼

      這是當時對著一篇大牛的博文敲的例子,后來發(fā)現(xiàn)只能載入單個網(wǎng)頁,而其他資源不能很好的載入,就進行了一次較大的改正,主要添加了對不同pathname的尋址以及載入。本例的css、js以及image文件夾都與頁面所在的html文件夾在同一目錄下。

      相信通過這個例子大家已經能簡單的讓一個靜態(tài)網(wǎng)站在我們的服務器上支持起來了。我們下一次將會簡單的部署一個文件系統(tǒng),希望大家能繼續(xù)關注。新手上道,文章代碼寫的都比較粗糙,希望大家指正。


      數(shù)據(jù)庫de教程


      在前一篇博文中,我們簡單的分心了node,用node建立了一個文件解析服務器,并且在服務器中進行了WEB尋址的操作。通過這些操作,我們已經可以把一個簡單的靜態(tài)網(wǎng)站搭設在服務器之上了(http://www.cnblogs.com/xiao-yao/archive/2012/03/30/2425716.html)。

      當然,僅僅完成這樣的一個步驟還是遠遠不夠的,我們需要的不是通過node搭設一個靜態(tài)網(wǎng)站,而是通過node搭設一個完整的應用。那么我們可以想想下一步操作應該做什么了。沒錯,我們來嘗試一下數(shù)據(jù)庫的簡單操作。

      在嘗試之前,我們需要來學習一個新的模塊:querystring模塊。

      querystring模塊的主要用途是對字符串的處理,我們暫時先學習它的兩個方法:

      querystring.stringify(obj, sep='&', eq='=');
      querystring.parse(str, sep='&', eq='=');

      前一個方法是將對象向字符串的處理,后一個方法是將字符串的處理(是不是想到了JSON?)。前一個方法的參數(shù)是待處理對象、鍵值對之間的分隔符號以及鍵值之間的分割符號;后一個方法的參數(shù)與前一個相同,只不過處理的過程是相反的而已。

      好了,我們了解了這個方法之后,便可以進行下一步的工作了。首先是對參數(shù)的捕獲,前端將數(shù)據(jù)傳遞給后臺時,后臺進行接收并處理,數(shù)據(jù)的傳遞似乎就這么簡單。

      往往讓人莫名痛苦的就是這些簡單的東西,比如數(shù)據(jù)如何傳遞、node如何處理、如何接收傳遞過來的參數(shù)。好的,我們一個一個來解決。

      首先是數(shù)據(jù)從前端的傳遞方式,這個本不該是這里的內容,不過說說也無所謂。前端傳遞參數(shù)有很多方法,比如表單傳遞、AJAX傳遞,但歸根結底就是兩種傳遞方法,post傳遞或者get傳遞。

      兩者的區(qū)別就是get傳遞是通過url后面附加參數(shù)的傳遞方法,而post傳遞是通過表單的數(shù)據(jù)體附加提交。其他的區(qū)別與node無關,這里就不贅述了。

      首先是get方法,通過url傳遞的參數(shù)的獲取非常簡單,記得前面曾學習過一個url.parse(string).query方法嗎?這個方法獲取的就是get方法下所傳遞的參數(shù)。

      然后就是對參數(shù)的處理了,還記得前面的querystring.parse方法吧,這里我們就可以簡單的使用了:

      var name=querystring.parse(url.parse(req.url).query)['name'];

      這樣就獲取了前端get方法傳遞的name屬性的值了,方法很容易。

      那么post呢?它可不在url中啊。處理post參數(shù),我們需要另一個模塊:formidable。

      讓我們來看一下formidable的demo吧:

      復制代碼
      var formidable = require('formidable'),
          http = require('http'),
          util = require('util');
      http.createServer(function(req, res) {
        if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
          // parse a file upload
          var form = new formidable.IncomingForm();
          form.parse(req, function(err, fields, files) {
            res.writeHead(200, {'content-type': 'text/plain'});
            res.write('received upload:\n\n');
            res.end(util.inspect({fields: fields, files: files}));
          });
          return;
        }
        // show a file upload form
        res.writeHead(200, {'content-type': 'text/html'});
        res.end(
          '<form action="/upload" enctype="multipart/form-data" '+
          'method="post">'+
          '<input type="text" name="title"><br>'+
          '<input type="file" name="upload" multiple="multiple"><br>'+
          '<input type="submit" value="Upload">'+
          '</form>'
        );
      }).listen(8888);
      復制代碼

      讓我們簡單的分析一下這個文件上傳:var form = new formidable.IncomingForm();一句通過簡單的引用formidable的IncomingForm方法來捕獲fields與files的信息,之后使用util模塊(以前的sys模塊)的inspect方法來返回post對象的結構信息。通過這樣的方式獲取到post的對象后,便可以對對象進行操作了。

      好了,現(xiàn)在我們分析了兩種不同的參數(shù)傳遞以及接收的方式,現(xiàn)在該講講如何去對數(shù)據(jù)庫進行操作了。關于數(shù)據(jù)庫我采用的是mongo數(shù)據(jù)庫,這種語法類似JS的NO-SQL數(shù)據(jù)庫無非是前端攻城濕所欣賞的一種數(shù)據(jù)庫了。至于mongo的基本操作我建議參考園內大牛一線碼農的8天mongo系列,確實是入門的一部好系列。

      在這里我們先進行做簡單的find查找,其他的我們以后再去討論。

      首先我們先安裝并引入mongo模塊,具體的行為我們這里不再進行贅述了。對于collection的API是這樣寫的:

      復制代碼
      db.open(function(err, db) {
        if(!err) {
          db.collection('test', function(err, collection) {});
          db.collection('test', {safe:true}, function(err, collection) {});
          db.createCollection('test', function(err, collection) {});
          db.createCollection('test', {safe:true}, function(err, collection) {});
        }
      });
      復制代碼

      而find的api則是這樣寫的:

      find(query[, options][, callback]);

      我們采用最簡單的方法來進行一次嘗試:

      復制代碼
      var db = new mongo.Db("test", new mongo.Server('localhost', 27017, {}), {});
          db.open(function() {
              // 打開名為user的表
              db.collection("user", function(err, collection) {
                  // select * from products 相當于db.products.find()
       collection.find({name:querystring.parse(url.parse(req.url).query)['name'],pwd:querystring.parse(url.parse(req.url).query)['pwd']},function(err, cursor) {
                      cursor.toArray(function(err, items) {
                          if (items != null&&items.length != 0) {
                              res.writeHead(200);
                              var obj = {value:1}
                              res.end(JSON.stringify(obj)); 
                          }
                          else{
                              res.writeHead(200);
                              var obj = {value:0}
                              res.end(JSON.stringify(obj));
                          } 
                      });
                  });
              });
          });
      復制代碼

      OK,我們通過對get方法傳遞的參數(shù)進行提取,并將之與user表中的name與pwd字段進行比較,若有該項則返回1,否則返回0。

      我們已經寫好了find方法,但是我不想只有一種數(shù)據(jù)庫操作,所以我需要一個類似路由的方法去尋址。方法如下:

      復制代碼
      var mongord = require("./mongord"),    //mongo數(shù)據(jù)庫讀取模塊
          mongoinsert = require("./mongoinsert"),
          querystring = require("querystring");
      function find_router(req, res){
          if (querystring.parse(url.parse(req.url).query)['num'] == 1) {
              mongord.read_collection(req,res);
          }
          else if(querystring.parse(url.parse(req.url).query)['num'] == 2){
              mongoinsert.insert_collection(req,res);
          }
          else{
      }
      }

      exports.find_router = find_router;

       
      復制代碼

      這樣,我們就獲得了一個近乎路由表的東西,由每次傳遞參數(shù)的value項去判斷執(zhí)行方法。

      最后附上今天的全部代碼:

      在上次的文件中加入:

      if (libUrl.parse(req.url).query!=undefined) {
      router.find_router(req,res);
      }

      然后路由表文件名為router:

      復制代碼
      var mongord = require("./mongord"),    //mongo數(shù)據(jù)庫讀取模塊
          querystring = require("querystring");
      function find_router(req, res){
          if (querystring.parse(url.parse(req.url).query)['num'] == 1) {
              mongord.read_collection(req,res);
          }
          else{
          }
      }

      exports.find_router = find_router;

       
      復制代碼

      最后是數(shù)據(jù)庫模塊,取名為mongord:

      復制代碼
      var http = require("http"),
          mongo = require("mongodb"),
          events = require("events"),
          url=require('url'),
          querystring = require("querystring");
      function read_collection(req, res) {
          // 創(chuàng)建到test數(shù)據(jù)庫的鏈接。相當于use test
          var db = new mongo.Db("test", new mongo.Server('localhost', 27017, {}), {});
          db.open(function() {
              // 打開名為user的表
              db.collection("user", function(err, collection) {
                  // select * from products 相當于db.products.find()
                  collection.find({name:querystring.parse(url.parse(req.url).query)['name'],pwd:querystring.parse(url.parse(req.url).query)['pwd']},function(err, cursor) {
                      cursor.toArray(function(err, items) {
                          console.log(items);
                          if (items != null&&items.length != 0) {
                              res.writeHead(200);
                              var obj = {value:1}
                              res.end(JSON.stringify(obj)); 
                          }
                          else{
                              res.writeHead(200);
                              var obj = {value:0}
                              res.end(JSON.stringify(obj));
                          } 
                      });
                  });
              });
          });
      }
      exports.read_collection = read_collection;
      復制代碼

      好的,今天所講的全部內容就到這里了,希望對于node的新手能有一個較好的幫助,謝謝大家。

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多