node开发web项目

第一步:安装express框架

        命令行转到node.exe的目录下,使用命令:npm install express。

        然后新建一个文件夹test用来放我们的项目,里面新建一个文件index.js,作为入口文件,内容为:

var express = require('express');
var app = express();
app.get('/', function (request, response) {  //express框架处理get请求
   response.send('Hello World!');
});
app.listen(80);
//命令行切换到index.js的目录,用node index.js启动后,在浏览器访问http://localhost,即可看到结果

        至于为什么项目要放在这,主要是因为require加载模块能够找得到,当然,假如你把express框架拷贝一份或者用绝对路径,那么就可以把我们的项目放在任何地方了。require加载模块的搜索方式具体请参照《node.js开发指南》6.1.3章。

        等等,上面的例子处理get请求好像没没涉及到数据的获取吧。。。搜噶,往下。。。

  • 处理get请求

var express = require('express');
var app = express();

app.get("*", function(req, res) {
    //获取数据的格式一为:req.query.参数名;
    var id = req.query.id;              //1
    var myName = req.query.my.name;     //zhangsan
    //获取数据的格式二为:req.param("n");或者req.param.n;
    var id_copy = req.param('id');     //1
    var myName_copy = req.param('my');  //{ name: 'zhangsan', address: 'beijing' }
    
    //另外,还可以用req.param('n')拿到路径中的对象。假如第一个参数不传"*",而传"/test/:hehe"
    //var t = req.param('hehe');  //浏览器访问:http://localhost/test/lisi 则t=lisi
    res.send("测试");
});

app.listen(80);
//假设在浏览器访问的url为:http://localhost?id=1&my[name]=zhangsan&my[address]=beijing

       request.param():可以处理get和post请求参数,但查找优先级由高到低为:req.params→req.body→req.query。

  • 处理post请求

    与处理get请求一样

  • 响应

//格式为:res.send([body|status], [body]);
//当参数为一个String时,Content-Type默认设置为"text/html"。
res.send('Hello World'); //Hello World
当参数为Array或Object时,Express会返回一个JSON。
res.send({ user: 'tobi' }); //{"user":"tobi"}
res.send([1,2,3]); //[1,2,3]
//.当参数为一个Number时,并且没有上面提到的任何一条在响应体里,Express会帮你设置一个响应体,比如:200会返回字符"OK"。
res.send(200); // OK
res.send(404); // Not Found
res.send(500); // Internal Server Error

    这点超赞~返回数组和对象时,express框架自动帮转化为json数据。

第二步:安装mongoDB数据库

  • 首先去官网下载(http://www.mongodb.org/downloads)压缩包(.zip的哦)。

  • 然后解压出来,里层有个bin文件夹。

  • 接着找个地方放好(无需安装版的,建议放非C盘),打开命令行,进入到里面那个bin目录(我是解压后改名为mongodb,所以我的目录是:D:\mongodb\bin)

  • 执行:mongod.exe --logpath=D:\mongodb\log.txt --dbpath=D:\mongodb\db

    --logpath 参数是设定日志文件的路径。
    --dbpath 参数是设定数据库文件的存放路径。
    mongod.exe命令的所有参数选项可通过mongod.exe --help查看。

  • 到此其实mongodb已经安装完成,不过每次都要打开黑窗口执行这句命令并且黑窗口不能关,比较烦~~~so,我们可以把mongodb作为服务安装(好比mySQL一样,要用mysql一样是要开启mysql服务)。在D:\mongodb\bin下,执行:mongod.exe --install --logpath=D:\mongodb\log.txt --dbpath=D:\mongodb\db。

    024408_nncV_1580821.png

    最后看到了对应的服务,以后只要启动此服务即可。

    net start mongodb 启动mongodb服务
    net stop mongodb 启动mongodb服务

    PS:测试方法如下

var express = require('express');
var app = express();
var mongoose = require("mongoose");
var db = mongoose.connect("mongodb://127.0.0.1:27017/test");
db.connection.on("error", function (error) {
    console.log("数据库连接失败:" + error);
});
db.connection.on("open", function () {
    console.log("------数据库连接成功!------");
});
app.listen(80);

第三步:动手

  • 首先新建一个文件夹放项目,我的目录结构如下图:

    091346_fvLZ_1580821.png

    models:用来放mongoose的模式、模型,如user模型等

    node_modules:这个在你安装模块时会自动生成,也可手动创建,用来放模块,如express模块等

    public:用来放静态资源,如页面用到的css和公用js等

    routes:用来放路由文件,当然你把路由全写在app.js里也没人说你错。。。

    schema:本来是用来放mongoose的模式文件的,我把模式和模型合并放在models了,所以不用此文件夹了

    views:用来放视图文件,也就是前台显示的页面

    根目录的app.js:程序入口文件

    根目录的db_connect.js:连接数据库的公用文件

    根目录的npm-debug.log:自动生成的npm调试日志文件

  • 然后冲入口文件app.js下手(/app.js)

var express = require('express');
var bodyParser = require('body-parser');  //已经从express中分离出来,依赖模块:body-parser
var session = require('express-session');
var moment = require('moment');
var app = express();

// 只用于开发环境
if ('development' == app.get('env')) {
  app.set('db uri', 'localhost/dev');
}
// 只用于生产环境
if ('production' == app.get('env')) {
  app.set('db uri', 'n.n.n.n/prod');
}
//设置端口
app.set('port', process.env.PORT || 80);
//选择视图模版,并把后缀由.ejs转换为.html
app.set( 'views', 'ejs' );
app.set( 'view engine', 'html' );
app.engine( '.html', require( 'ejs' ).__express );
//指定视图存放位置
app.set('views', require('path').join(__dirname, 'views'));
//指定静态资源存放位置
app.use(express.static(require('path').join(__dirname, 'public')));
app.use(bodyParser());
//中间件body-parser和multer用于处理和解析post请求的数据
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
//文件上传中间件
// app.use(multer());

//启用session
app.use(session({
	key:'session_overtime_30min',
    secret:'session_secret',
    resave:true,
    saveUninitialized:false,
    cookie:{
        maxAge:1000*60*5  //session过期时间设置(单位毫秒)
    }
}));
app.use(function(req, res, next){
	//这里写处理逻辑
    next();
});
//routes 路由选择
var routes = require('./routes');
routes(app);


//启动服务
app.listen(app.get('port'),function(){
  console.log("【时间】:"+moment().format('YYYY-MM-DD HH:mm:ss'));
  console.log("【状态】:服务器已启动,端口:"+app.get('port'));
});

稍微解释下:

require引入所需的模块,会优先从刚才的node-modules文件夹里找,假如没有才逐级网上找,直到全局。

app.set(...),对express框架的一些设置。

app.use(...),express框架的中间件,用next()传递。(PS:有点像java里面的过滤器)

routes(app),把路由分发处理。当然,路由少的话可以直接把路由处理写在app.js里。

app.listen(...),启动程序监听端口。

  • 然后进入路由分发:(routes/index.js)

/**
 * 路由分发
 */

require('../db_connect');
var user = require('./user');
var admin = require('./admin');
var Inform = require('../models/inform');
var Room = require('../models/room');
var Meeting = require('../models/meeting');
var moment = require('moment');

module.exports = function(app){
    //前台首页
    app.get('/',function(req,res){
      //通知概要
      Inform.find({"level":"A"}, null, {"limit":3,"sort":{"time":-1}}, function(err, user){
      //举例子怎么拿到请求中的数据
      //var n = req.query.n || "";  //假如请求的内容是/?n=1,则n=1
        if (err) {
          console.log(err);
        }else{
          Inform.find({"level":"B"}, null, {"limit":5,"sort":{"time":-1}}, function(err, docs){
            res.render('index', {"title":"首页","active": "index","user":req.session.user,"inform_summary":{"A":user,"B":docs}}); 
          });
        }
      });
    });

    user.routes(app);
    admin.routes(app);
}

代码解释:

require('../db_connect')这是直接把db_connect.js文件插入到此,文件内容为:(、db_connect.js)

var mongoose = require('mongoose');
mongoose.connect("mongodb://127.0.0.1:27017/my");

app.get(请求路径,处理请求和响应的函数):处理对应的get请求。

Inform.find(...):Inform是一个模式,可以直接执行mongo的sql语句,下一步看模式文件。

req:是http中的request,经express框架处理后包含了请求体的全部信息。

res:是http中的response,经express框架处理后的响应体。

res.send(返回的数据):可以返回数据给刚才的请求。

res.render(模版文件名,数据):可以渲染模版然后模版渲染好后自动返回给前台。稍后看模版文件。

user.route(app):以及下面的都是路由分发,这里不处理那么多,交给其他路由文件处理,这是分类思想。

  • 刚才有模式文件和模版文件没晓得是什么,那我们先看模式文件:(models/inform.js)

var mongoose = require('mongoose');

var InformSchema = new mongoose.Schema({
  title: { type: String},
  content: { type: String},
  level: { type: String},
  from:{ type: String},
  time: { type: String, default: new Date() }
});
//模式的静态方法,只有进行模型实例化后才可用的方法
InformSchema.pre('save',function(next){
	//pre方法是在sava之前执行,不会与数据库进行交互。
	next();
});
InformSchema.statics = {
	findAll: function(cb) {
		return this.find({}).sort({'time':-1});
		exec(cb);
	},
	findByKeyword: function(e, cb) {
		return this.find({$or:[{title:/^B.*/},{content:/^B.*/}]}).sort({'time':-1});
		exec(cb);
	}
};
module.exports = mongoose.model('Inform',InformSchema);

代码解释:

var mongoose = require('mongoose'):引入mongoose模块。

new mongoose.Schema({}):建一个Schema(模型),然后把这个模型赋给InformSchema变量。

InformSchema.pre():定义一些在模型实例化为模式之前的处理。

InformSchema.statics:定义一些在执行模式中的方法时的中间处理,只有在模式实例化为模型才可用。

module.exports = mongoose.model('Inform',InformSchema):实例化模式变为模型,对外公开为Inform。

PS:有的人喜欢把模式单独写为一个文件,然后在这里引入再实例化为模型,我觉得没必要,所以合并在一起写了。

呵呵,到这你应该看得懂刚才路由分发中的Inform.find(条件,[过滤条件],回调)这里的函数了吧。

  • 好,那接下来就看模版,我用的是ejs模版(/veiws/index.html)

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title><%= title%></title>
        <% include includes/header %>
        <style type="text/css">

        </style>
    </head>
    <body>
      <% include includes/page_header %>
      <div id="main">
      <% include includes/nav %>
      <% include includes/inform_href %>
      <% include includes/dialog %>
    </div><!-- main end -->
      <div id="footer"></div>
      <% include includes/model_login_register %>
    </body>
</html>

代码解释:

html部分都看得懂就不说了,其中出现的<%%>语法就是ejs模版的语法了,include命令明显是包含的意思,意思是包含includes/page_header(假如包含的文件后缀不是ejs则需要把后缀也加上)这个文件到这里来,看下我的目录结构:

100317_eD30_1580821.png

而header.ejs文件内容为:

<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="/css/css.css">
<script type="text/javascript" src="/js/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="/js/bootstrap.min.js"></script>

这个文件没用到ejs的语法,只是纯粹的把需要的css和js文件包含进来而已。

那么,再看page_header.ejs(代码比较乱,请直接砍<%%>部分)

<div id="header">
    <h1>会议系统</h1>
    <span class='person'>
		<span id="hasLogin" class='person_panel <%if(user){%>hasLogin<%}%>'>
      欢迎你,<a class="user" href="#" title="个人中心"><%if(user){%><%= user.username%><%}%></a>
      &nbsp;<span class="label label-primary logout_btn"style="cursor:pointer;">注销</span>
    </span>
    <span id="notLogin" class='person_panel <%if(!user){%>notLogin<%}%>'>
    	欢迎你,<span class="user">游客</span> &nbsp;
  	  <span class="label label-primary login_btn" data-toggle="modal" 
  	data-target="#loginModal" data-backdrop="static" style="cursor:pointer;">登陆</span>&nbsp;
  	  <span class="label label-primary register_btn" data-toggle="modal" 
  	data-target="#registerModal" data-backdrop="static" style="cursor:pointer;">注册</span>
    </span>
	</span>
</div>
<script type="text/javascript">
	  $('.logout_btn').on('click',function () {
	  	console.log("点击了注销按钮");
         $.ajax({
            type: "POST",
            url: "/logout",
            data: {},
            success: function(msg){
              if (msg.state == "success") {
                $("#hasLogin").removeClass("hasLogin");
                $("#notLogin").addClass("notLogin");
                alert("注销成功!");
              }
            }
         });
      })
      $('.login_btn').on('click',function () {
         $("#username").focus();
         console.log("点击了登陆按钮");
      })

  </script>

比如:<%if(user){%><%= user.username%><%}%>,这里<%%>里面可以写js代码,由ejs模版引擎解析,<%= XXX%>用来输出数据,而数据就是刚才从路由分发那里的res.render(模版文件名,数据)中传过来的。(个人觉得ejs模版和jsp语法差不多,所以选择ejs,当然你也可选择jade等其他模版引擎)。

  • 至此,整个流程基本跑通,需要实现其他高级的功能都在这个基础上实现。


其他知识点总结:

  1. 获取参数值的几种方式和区别

    req.param(),具备了req.body,req.query,req.params的功能,可惜express4.0开始弃用了,就不多说了。

    req.params用法如下

app.get('/user/:name', function(req, res){
  //:name的地方甚至可以用正则,获取就用req.params[0],假如是"/user",则param的值为{}
  var param = req.params.name;
  res.send('hello world' + param);
});

        req.body用法如下(主要是结合body-parser中间件处理post请求)

var express = require('express');
var bodyParser = require('body-parser');  //express4.0以后已经从express中分离出来
var app = express();
app.use(bodyParser());
app.use(bodyParser.json());
app.get('/user', function(req, res){
  //假如提交的ajax post请求数据为:{name:"zhangsan"},假如是表单提交,这name的值为name="name"的值
  var name = req.body.name;    //name的值为"zhangsan"
  res.send('hello world' + name);
});

        req.query用法如下(主要是处理get请求)

app.get('/user', function(req, res){
  //假如请求url为:/user?name="zhangsan",无论是ajax方式还是url访问方式都一样的,只要是get方式的请求。
  var name = req.query.name;   //zhangsan
  res.send('hello world' + name);
});


转载于:https://my.oschina.net/u/1580821/blog/371453

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值