node.js从入门到菜鸟——资源无法载入?你需要学会地址解析

node.js是什么似乎已经不需要我多为赘述了,非阻塞的服务器语言、JS书写的后台代码,无数的文章已经很好的展示了node的魅力与展望。关于node.js的安装,大家不妨参考博客园聂微东的http://www.cnblogs.com/Darren_code/archive/2011/10/31/nodejs.html (node.js初体验),这篇文章很好的综述了node.js的一个基础(从安装到体验到模块的一个入门,个人感觉是一篇很好的文章),相信通过东哥的这篇文章大家可以对node有一个初步的了解。

node是一门很有意思的框架,它能够让一个长期执迷于前端开发的攻城湿(忘记了还有一种语言叫后端语言。。。)能够觉得很舒适(编码习惯都一样),但是也同样会让一个新手觉得无所适从(为什么么有从入门到精通哩?参考书在哪里???)。这是一个前端高手为之一亮(也许只亮了一眼o(╯□╰)o),新手眼前一晕(if you want to find more information,please read the source(╯□╰)o)的框架。为了让和我一样的新手能够多多少少摸到一点门路,我以身试法,来为新手找一条路~

本文旨在新手入门,所学尚浅,代码水准有限,这也仅仅只是一个基本入门的笔记,高手可以笑一笑然后点关闭了。。。

首先我假设你已经安装好了node(http://nodejs.org/#download,0.6.14已经很成熟了),那么首先我们来进行一个入门的编码分析。

在进行分析之前,我们先来想一下以前的服务器端语言框架的工作原理。首先,用户通过浏览器来访问我们的应用。然后服务器通过对端口的监听,来接收网络端的request请求,并进行相应的处理。最后再将处理的结果返回客户端。

好了,那么我们可以开始了。首先是服务器,要是没有办法启动服务器,那么一切都是闲的。我们也许用过很多服务器端的语言(PHP、JAVA、ASP等等),接收HTTP请求并提供Web页面的过程似乎不用我们来做,apache和IIS似乎都会帮我们来完成。但是在node里,这一步必须你自己做。我们来实现的不仅仅是一个应用,还需要实现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时内心都会有一丝变态的快意。。。

让我们来回忆一下刚才的问题:实现一个http的服务器。其实这个很简单,http模块自带的createServer方法就可以完成。该方法只有一个参数,类型为函数,在接口文档中的定义是“始终接收request事件”。而server.listen方法(server就是刚才通过createServer创建的server)的参数是(port, [hostname], [callback]),第一个是监听的端口号,第二个和第三个是可选项,第二个是主机名称,第三个回调函数。这个函数只在绑定端口后进行调用。

接下来是回调函数,回调函数的参数有两个,第一个是客户端发送的request,第二个是服务器端的response。这段代码进行了一个简单的响应操作。首先是书写了一个响应头,响应头参数包括状态码、原因描述以及头部内容。状态码即http状态码,例如200、404、500之类的。原因描述与头部内容可选,具体的就参见网络报头的书写了,这里就不多说了(其实我也不会。。。)。writehead方法必须写在end方法之前,这个是肯定的。。。

response的write方法就和JS的write所做的工作一样,就是向页面写入数据,虽然原理不尽相同,但目前没有准备去钻研这部分源码的我们可以忽略了。。。最后是end方法,它有两个可选参数,分别是data与encoding。该方法用于所有的响应头与响应正文输出之后,进行响应的终结,并将管道流中的所有响应数据输出。简单地说就是在响应最后加上去的东西,它执行后会将响应执行。如果该方法带有参数,那么就相当于先调用了response.write(data, encoding)方法,之后再调用无参数的end方法。

好了,最简单的一个http服务器已经工作起来了。当用户访问127.0.0.1的12345端口时服务器会监听到这一端口的request请求并书写报头与最简单的helloworld于页面上,用户得到响应之后会在浏览器中显示响应的内容,也就是helloworld。这个最简单的服务器已经搭好了,但我们不能只满足于这一点。

在继续下一步的学习之前,我想给所有没有使用过JS或者不怎么使用的同学大体的讲述一下一个也许你们会略微奇怪的参数传递方法——函数传递。

在JS中,函数与数字、字符串等都是以var定义的,在参数传递的过程中所接受的参数也是var这种弱类型的。而function类型也是作为弱类型传递,当我们将一个函数进行传递时,所得到的不是该函数的返回值,而是这个函数本身。也就是说,这个函数在运行时会变成传递到的函数的本地变量(自己都觉得好乱。。。)。

让我们回忆一下刚才的例子,在creatServer方法中我们使用了一个匿名函数作为参数,现在我们把这个匿名函数提出来:

 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则可以在载入模块后将该函数载入全局变量的作用链中。

说到这大家也应该明白了,我们要进行一次模块引用。将这段代码存入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向服务器传递的参数。

而path模块的作用是解决文件路径问题,我们这次先学习三个方法:

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

第一个方法是获取扩展名的方法,参数是url路径。第二个方法是做路径拼接使用,用来标准化最终路径,参数是需要拼接的路径。第三个方法是检验路径存在与否,第一个参数是标准化的路径,第二个是可选的回调函数,无论路径存在与否都会被调用,函数有一个exist参数,标示路径是否存在。

好了,现在我们就可以通过这两个模块进行一个简单的路径服务器的搭建了。通过这个服务器的搭建,我们可以对本地的静态网站进行部署,对于页面以及网页所需要载入的各种资源进行寻址,最后对请求的资源进行反馈。

 1 //请求模块
2 var http = require('http');
3 var url=require('url');
4 var fs = require("fs"); //在这里先导入文件模块,仅仅做一个简单的操作,具体有关文件模块的学习在之后的文件服务器上会进行进一步的学习。
5 var path = require("path");
6 //创建一个http服务器
7 var server=http.createServer(start).listen(12345);
8 //依据路径获取返回内容类型字符串,用于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服务器主函数,解析请求,返回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"; //指定为默认网页
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 //创建只读流用于返回
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 }

这是当时对着一篇大牛的博文敲的例子,后来发现只能载入单个网页,而其他资源不能很好的载入,就进行了一次较大的改正,主要添加了对不同pathname的寻址以及载入。本例的css、js以及image文件夹都与页面所在的html文件夹在同一目录下。

相信通过这个例子大家已经能简单的让一个静态网站在我们的服务器上支持起来了。我们下一次将会简单的部署一个文件系统,希望大家能继续关注。新手上道,文章代码写的都比较粗糙,希望大家指正。bye





 







转载于:https://www.cnblogs.com/xiao-yao/archive/2012/03/30/2425716.html

评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符

极简JAVA学习营第五期

01-19
想学好JAVA必须要报两万的培训班吗? 【课程背景】 JAVA是市场份额最大的编程语言,每天各大招聘网站上都会有数万个JAVA开发工程师的在招岗位,但是JAVA的技术体系庞大复杂,要想扎实掌握JAVA不是一件容易的事,线上学习相比线下两万起的高昂费用便宜了很多,而且具备学习时间灵活的优势,但是线上学习的劣势也很明显,没有线下那种学习氛围,碰到问题没法解决,在家学习很容易偷懒,极简JAVA学习营充分考虑到这些问题,通过每日实战编程练习,分队pk,助教答疑,作业点评,作业讲解,项目答辩等诸多环节充分激发你的学习热情,解决你学习中碰到的问题,让你花十分之一的钱学到JAVA的精髓,开启你的人生逆袭之路。 【专项的贴心服务】 1. 学练结合:定期布置视频任务和编程实战练习:通过每天的视频任务统一大家的进度,以便同学更好的交流,针对每天的任务会有相应的编程实战练习,通过练习内化知识。 2. 分队PK:将就业营的同学分成几队,通过作业统计表统计每队提交作业情况进行PK,激发你的学习动力。 3. 助教讲师答疑:碰到任何问题,发到群里,助教和讲师十分钟内帮你解决问题,扫清学习中的障碍。 4. 助教点评讲解作业:你每天提交作业都会有助教进行点评,让你知道有什么问题怎么解决,每三天一次视频讲解作业,互动解答问题 5. 项目答辩:每个阶段学完会有项目答辩,通过做项目巩固前一阶段的知识点,锻炼编码能力。 【往期训练营学习展示】 【套餐内容简介】 本套课以市场就业和职位需求为核心,从JAVA入门到多领域实战,设计出学习路线,共分为二十大模块,分别是:JAVA面向对象、Object类与常用API、集合框架、IO流、反射注解、多线程与网络编程、Object类与常用API等等。 同时采用理论讲解加实战演练的方式,既能让学员听懂听明白达到理解透彻,又能够在一个个真实实战案例中,让学员掌握真正有用的开发技能,从而进阶 JAVA 工程师! 套餐中一共包含21门JAVA程,助你从零进阶JAVA工程师! 阶段一:JAVA基础 课程1:《极简JAVA学习营开营篇》 课程2:《极简JAVA:JAVA面向对象》 课程3:《极简JAVA:Object类与常用API》 课程4:《极简JAVA:集合框架》 课程5:《极简JAVA:IO流》 课程6:《极简JAVA:反射注解》 课程7:《极简JAVA:多线程与网络编程》 阶段二:数据库入门 课程8:《极简JAVA:MySql数据库》 课程9:《极简JAVA:JDBC与连接池》 阶段三:JAVA WEB 课程10:《极简JAVA:HTML5与CSS3》 课程11:《极简JAVA:极简JAVA十一:Javascript与Jquery》 课程12:《极简JAVA:BootStrap》 课程13:《极简JAVA:JAVA Web》 阶段四:框架实战 课程14:《极简JAVA:Mavean入门》 课程15:《极简JAVA:MyBatis框架》 课程16:《极简JAVA:Spring框架》 课程17:《极简JAVA:Spring Mvc》 课程18:《极简JAVA:Oracle数据库》 课程19:《极简JAVA:Git入门》 课程20:《极简JAVA:Linux入门》 课程21:《极简JAVA:SpringBoot》 【课程特色】 1、易理解:讲师思路清晰、节奏明确、从易到难讲解透彻明白; 2、知识全:知识全面系统,从JAVA入门到实战,由易到难,让你彻底掌握JAVA开发; 3、重实战:涵盖大量实战项目,锻炼你的动手实操能力,面向工作编程; 【面向人群】 1、在校计算机专业或者对软件编程感兴趣的学生; 2、零基础想学JAVA却不知道从何入手 3、囊中羞涩,面对两万起的JAVA培训班不忍直视 4、在职没有每天大块的时间专门学习JAVA 这么细致的服务,这么好的氛围,这样的学习效果,你还等什么?赶紧报名吧,抓紧抢位,本期只招100人,错过只有等时间待定的下一期了
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值