Express: ?Node.js용 웹 애플리케이션 프레임워크?Express는 간결하고 유연한 node.js 웹 애플리케이션 개발 프레임워크로, 다양한 웹 및 모바일 장치 애플리케이션을 만드는 데 도움이 되는 일련의 강력한 기능을 제공합니다.
목차
이 기사에서는 Mongoose, Ejs, Bootstrap 및 기타 관련 콘텐츠가 포함된 Express4.x(구체적으로 4.10.4)의 개발 프레임워크에 중점을 둡니다.
프로젝트 만들기
디렉토리 구조
Express4.x 구성 파일
Ejs 템플릿 사용법
부트스트랩 인터페이스 프레임워크
라우팅 기능
세션 사용량
페이지 팁
페이지 접근 제어
개발 환경:
우분투
MonogoDB: v2.6.4
nodejs:v0.11.2
npm 2.1.10(nodejs가 1.2.19 버전으로 설치된 경우 이 글은 2.x 버전으로 업그레이드되었습니다.)
1. 프로젝트 생성
프로젝트 디렉토리를 입력하세요
mkdir 직장
CD작업장
express를 전역적으로 설치하면 express가 명령으로 시스템에 설치됩니다.
npm install -g express
익스프레스 버전 보기
익스프레스 -V
참고: express 명령은 express4.x 버전에 더 이상 포함되지 않습니다.
express-generator 설치 필요
npm install express-generator -g
자세한 설치 과정은 "Nodejs 개발 환경 Ubuntu 준비"를 참조하세요.
express 명령을 사용하여 프로젝트 생성 및 ejs 지원
hadoop@sven:~/workspace/nodeJs$ express -e nodejs-demo
생성: nodejs-demo(프로젝트 이름)
생성: nodejs-demo/package.json (프로젝트 패키지 정보)
생성: nodejs-demo/app.js(메인 프로그램)
생성: nodejs-demo/public(공용 디렉터리)
생성: nodejs-demo/public/images
생성: nodejs-demo/public/javascripts
생성: nodejs-demo/public/stylesheets
생성: nodejs-demo/public/stylesheets/style.css
create: nodejs-demo/routes(라우팅 디렉터리, 나중에 이 디렉터리에서 프로그램을 개발한 다음 app.js에서 사용)
생성: nodejs-demo/routes/index.js
생성: nodejs-demo/routes/users.js
생성: nodejs-demo/views(디렉토리 보기, 템플릿 파일 보기 등)
생성: nodejs-demo/views/index.ejs
생성: nodejs-demo/views/error.ejs
생성 : nodejs-demo/bin
생성: nodejs-demo/bin/www(app.js를 시작하는 데 사용되는 시작 파일)
종속성 설치:
$ cd nodejs-demo && npm 설치
앱을 실행하세요:
$ DEBUG=nodejs-demo ./bin/www
프로젝트가 성공적으로 생성되었습니다.
위 팁에 따라 종속성을 설치합니다.
안내에 따라 웹을 시작하세요.
그러나 여기서는 이 방법을 사용하여 프로그램을 시작하지 않을 것입니다. 그 이유는 개발 과정에서 nodemon을 도구로 사용해야 하기 때문입니다.
Nodemon은 개발 프로세스 중에 프로젝트 변경 사항을 동적으로 식별한 다음 이를 동적으로 로드하는 데 사용됩니다(이는 Eclipse의 Java 웹 개발과 유사합니다). 이 도구는 웹 개발에 필수적입니다
nodemon 설치:
npm install nodemon -g
그럼 위의 ./bin/www 스크립트를 사용하면 어떨까요?
이유는 nodemon./bin/www가 프로젝트 변경 사항을 식별할 방법이 없기 때문입니다. (직접 실험해봤습니다. 혹시 아시는 전문가 계시면 조언 부탁드립니다)
app.js 수정:
마지막 줄을 주석 처리합니다. //module.exports = app
다음으로 대체: app.listen(3000);
app.js 기본 프로그램을 시작하려면 다음 명령을 사용하세요.
hadoop@sven:~/workspace/nodeJs/nodejs-demo$ nodemon app.js
그런 다음 프로그램을 수정하여 동적으로 로드되는지 확인하세요. 다음과 같은 메시지가 표시됩니다:
12월 1일 16:22:07 – [nodemon] 변경으로 인해 다시 시작…
12월 1일 16:22:07 – [nodemon] `node app.js` 시작
은 효력을 발휘한다는 의미입니다.
테스트:
로컬 포트 3000이 열리고 브라우저를 통해 액세스됩니다: localhost:3000
2. 디렉토리 구조
./
drwxrwxr-x 5 hadoop hadoop 4096 12월 1일 15:57 ../
-rw-rw-r– 1 hadoop hadoop 1495 12월 1일 16:22 app.js
-rw-r–r– 1 hadoop hadoop 12288 12월 1일 16:22 .app.js.swp
drwxr-xr-x 2 hadoop hadoop 4096 12월 1일 15:57 bin/
drwxrwxr-x 9 hadoop hadoop 4096 12월 1일 15:58 node_modules/
-rw-rw-r– 1 hadoop hadoop 326 12월 1일 15:57 package.json
drwxr-xr-x 5 hadoop hadoop 4096 12월 1일 15:57 공개/
drwxr-xr-x 2 hadoop hadoop 4096 12월 1일 15:57 경로/
drwxr-xr-x 2 hadoop hadoop 4096 12월 1일 15:57 views/
디렉토리 소개:
node_modules는 모든 프로젝트 종속 라이브러리를 저장합니다. (각 프로젝트는 Maven, Gradle 등과는 다른 자체 종속성을 관리합니다.)
package.json, 프로젝트 종속성 구성 및 개발자 정보
app.js, 프로그램 메인 입구
공개, 정적 파일(css, js, img)
경로, 라우팅 파일(C, MVC의 컨트롤러)
뷰, 페이지 파일(Ejs 템플릿)
nodejs-demo/bin/www (app.js를 시작하는 데 사용되는 시작 파일)
app.js를 열어 콘텐츠 보기:
/** * 模块依赖 */ var express = require('express') , routes = require('./routes') , user = require('./routes/user') , http = require('http') , path = require('path'); var app = express(); //环境变量 app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/views'); app.set('view engine', 'ejs'); app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(path.join(__dirname, 'public'))); // 开发模式 if ('development' == app.get('env')) { app.use(express.errorHandler()); } // 路径解析 app.get('/', routes.index); app.get('/users', user.list); // 启动及端口 http.createServer(app).listen(app.get('port'), function(){ console.log('Express server listening on port ' + app.get('port')); });
4. Ejs 템플릿 사용
ejs 템플릿 파일은 확장자가 html인 파일을 사용하도록 합니다.
수정: app.js
var ejs = require('ejs'); //ejs를 소개합니다. 종속성 다시 설치>
app.engine('.html', ejs.__express);
app.set('뷰 엔진', 'html'); // app.set('뷰 엔진', 'ejs');
이름 바꾸기: views/*.ejs를 views/*.html로 변경
localhost:3000에 접근하는 것이 맞습니다
index.ejs 등 주로 파일 이름을 바꿉니다
5. 부트스트랩 인터페이스 프레임워크 추가
실제로 js 및 css 파일을 프로젝트의 해당 디렉터리에 복사하면 됩니다. 4개 파일 포함:
public/stylesheets 디렉토리에 복사
bootstrap.min.css
bootstrap-responsible.min.css
public/javascripts 디렉토리에 복사
bootstrap.min.js
jquery-1.9.1.min.js
다음으로 index.html 페이지를 header.html, index.html, footer.html의 세 부분으로 나눕니다
header.html은 HTML 페이지의 헤더 영역입니다
index.html은 콘텐츠 표시 영역입니다
footer.html은 페이지 하단 영역입니다
header.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title><%=: title %></title> <!-- Bootstrap --> <link href="http://www.geedoo.info/stylesheets/bootstrap.min.css" rel="stylesheet" media="screen"> <!-- <link href="http://www.geedoo.info/css/bootstrap-responsive.min.css" rel="stylesheet" media="screen"> --> </head> <body screen_capture_injected="true"> index.html <% include header.html %> <h1><%= title %></h1> <p>Welcome to <%= title %></p> <% include footer.html %> footer.html <script src="http://www.geedoo.info/javascripts/jquery-1.9.1.min.js"></script> <script src="http://www.geedoo.info/javascripts/bootstrap.min.js"></script> </body> </html>
localhost:3000에 접근하는 것이 맞습니다.
EJS 템플릿 기능을 성공적으로 사용하여 페이지에서 공개 머리글과 바닥글을 분리했습니다.
그리고 부트스트랩 인터페이스 프레임워크가 도입되었습니다.
6. 라우팅 기능
사용자 로그인 비즈니스 요구 사항을 설계해 보겠습니다.
접속경로 : /, 페이지 : index.html, 로그인 필요없이 바로 접속 가능합니다.
접속경로 : /home, 페이지 : home.html, 접속 전 반드시 사용자 로그인이 필요합니다.
접속 경로: /login, 페이지: login.html, 로그인 페이지, 사용자 이름과 비밀번호를 정확하게 입력하면 자동으로 home.html로 이동
접속경로 : /logout, 페이지 : 없음 로그아웃 후 자동으로 index.html 페이지로 돌아갑니다
app.js 파일을 열고 라우팅 구성을 추가하세요
app.get('/',routes.index); app.route('/login') .get(routes.login) post(routes.doLogin); app.get('/logout',routes.logout); app.get('/home',routes.home);
참고: get은 get 요청이고 post는 post 요청이며 all은 이 경로에 대한 모든 요청입니다.
routes/index.js 파일을 열고 해당 메소드를 추가합니다.
exports.index=function(req, res) { res.render('index', { title: 'index' }); }; exports.login=function(req,res){ res.render('login',{title: '用户登录'}); }; exports.doLogin=function(req,res){ var user = { username:"admin", password:"admin" } if(req.body.username==user.username && req.body.password==user.password){ res.redirect('/home'); } res.redirect('/login'); }; exports.logout = function(req,res){ res.redirect('/'); }; exports.home = function(req,res){ var user = { username:'admin', password:'admin' } res.render('home',{title:'Home',user:user}); };
views/login.html과 views/home.html이라는 두 개의 파일을 만듭니다
login.html
<% include header.html %> <div class="container-fluid"> <form class="form-horizontal" method="post"> <fieldset> <legend>用户登陆</legend> <div class="control-group"> <label class="control-label" for="username">用户名</label> <div class="controls"> <input type="text" class="input-xlarge" id="username" name="username"> </div> </div> <div class="control-group"> <label class="control-label" for="password">密码</label> <div class="controls"> <input type="password" class="input-xlarge" id="password" name="password"> </div> </div> <div class="form-actions"> <button type="submit" class="btn btn-primary">登陆</button> </div> </fieldset> </form> </div> <% include footer.html %> home.html: <% include header.html %> <h1>Welcome <%= user.username %>, 欢迎登陆!!</h1> <a claa="btn" href="http://www.geedoo.info/logout">退出</a> <% include footer.html %>
index.html 수정 및 로그인 링크 추가
index.html
<% include header.html %> <h1>Welcome to <%= title %></h1> <p><a href="http://www.geedoo.info/login">登陆</a></p> <% include footer.html %>
路由及页面我们都写好了,快去网站上试试吧。
7. Session使用
从刚来的例子上面看,执行exports.doLogin时,如果用户名和密码正确,我们使用redirect方法跳转到的home
res.redirect('/home');
执行exports.home时,我们又用render渲染页面,并把user对象传给home.html页面
res.render('home', { title: 'Home',user: user});
为什么不能在doLogin时,就把user对象赋值给session,每个页面就不再传值了。
session这个问题,其实是涉及到服务器的底层处理方式。
像Java的web服务器,是多线程调用模型。每用户请求会打开一个线程,每个线程在内容中维护着用户的状态。
像PHP的web服务器,是交行CGI的程序处理,CGI是无状态的,所以一般用cookie在客户的浏览器是维护用户的状态。但cookie在客户端维护的信息是不够的,所以CGI应用要模仿用户session,就需要在服务器端生成一个session文件存储起来,让原本无状态的CGI应用,通过中间文件的方式,达到session的效果。
Nodejs的web服务器,也是CGI的程序无状态的,与PHP不同的地方在于,单线程应用,所有请求都是异步响应,通过callback方式返回数据。如果我们想保存session数据,也是需要找到一个存储,通过文件存储,redis,Mongdb都可以。
接下来,我将演示如何通过mongodb来保存session,并实现登陆后用户对象传递。
app.js文件
在相应位置添加下面代码:
var session = require('express-session'); var connect = require('connect'); var SessionStore = require("session-mongoose")(connect); var store = new SessionStore({ url:"mongodb://localhost/session", interval: 120000 }); app.use(session({ secret: 'test.com', store: store, cookie:{maxAge:10000} //expire session in 10 seconds })); //用于把登录用户设置到res.locals里面,在home.html里显示 app.use(function(req,res,next){ res.locals.user = req.session.user; console.log('Session is = ',req.session.user); next(); });
需要添加中间件connect、session-mongoose。
其中session-mongoose是用于连接mongodb数据库。然后自动写入session信息到数据库中(也可以用mongoose中间件,但是要自己实现session的写入)
app.use(session(….)) 这里是全局设置了session的信息及session信息存储的方式。
注:app.js文件有顺序要求,一定要注意!!!
安装session-mongoose依赖库
npm install connect
npm install session-mongoose
npm install session-mongoose
安装有错误但是没关系。
访问:http://localhost:3000/login,正常
修改routes/index.js文件
exports.doLogin方法
exports.doLogin = function(req, res){ var user={ username:'admin', password:'admin' } if(req.body.username===user.username && req.body.password===user.password){ req.session.user=user; return res.redirect('/home'); } else { return res.redirect('/login'); } };
exports.logout方法
exports.logout = function(req, res){ req.session.user=null; res.redirect('/'); };
exports.home方法
exports.home = function(req, res){ res.render('home', { title: 'Home'}); };
这个时候session已经起作用了,exports.home的user显示传值已经被去掉了。 是通过app.js中app.use的res.locals变量,通过框架进行的赋值。
app.use(function(req, res, next){ res.locals.user = req.session.user; next(); });
注:这个session是express4.10.4的写法,与express4之前的版本是不一样的。
访问页面可以查看mongodb有没有数据:
nodejs-mongodb
nodejs-mongodb
由于上面配置的 cookie:{maxAge:10000} //expire session in 10 seconds
过期时间,因此你会看到mongodb里面的数据过一段时间就被清除了。
参考:
Mongoose:http://mongoosejs.com/
关于express4.2.0与express3.x操作的区别:http://blog.csdn.net/u013758116/article/details/38758351
8. 页面提示
登陆的大体我们都已经讲完了,最后看一下登陆失败的情况。
我们希望如果用户登陆时,用户名或者密码出错了,会给用户提示,应该如何去实现。
打开app.js的,增加res.locals.message
登陆的大体我们都已经讲完了,最后看一下登陆失败的情况。
我们希望如果用户登陆时,用户名或者密码出错了,会给用户提示,应该如何去实现。
打开app.js的,增加res.locals.message
app.use(function(req, res, next){ res.locals.user = req.session.user; var err = req.session.error; delete req.session.error; res.locals.message = ''; if (err) res.locals.message = '<div class="alert alert-danger">' + err + '</div>'; next(); });
修改login.html页面,<%- message %>
<% include header.html %> <div class="container-fluid"> <form class="form-horizontal" method="post"> <fieldset> <legend>用户登陆</legend> <%- message %> <div class="control-group"> <label class="control-label" for="username">用户名</label> <div class="controls"> <input type="text" class="input-xlarge" id="username" name="username" value="admin"> </div> </div> <div class="control-group"> <label class="control-label" for="password">密码</label> <div class="controls"> <input type="password" class="input-xlarge" id="password" name="password" value="admin"> </div> </div> <div class="form-actions"> <button type="submit" class="btn btn-primary">登陆</button> </div> </fieldset> </form> </div> <% include footer.html %>
修改routes/index.js,增加req.session.error
exports.doLogin = function(req, res){ var user={ username:'admin', password:'admin' } if(req.body.username===user.username && req.body.password===user.password){ req.session.user=user; return res.redirect('/home'); } else { req.session.error='用户名或密码不正确'; return res.redirect('/login'); } };
让我们来看看效果: http://localhost:3000/login 输入错误的和密码, 用户名:dad,密码:da
boostrap-nodejs
9. 页面访问控制
网站登陆部分按照我们的求已经完成了,但网站并不安全。
localhost:3000/home,页面本来是登陆以后才访问的,现在我们不要登陆,直接在浏览器输入也可访问。
页面报错了,提示<%= user.username %> 变量出错。
GET /home?user==a 500 15ms
TypeError: D:\workspace\project\nodejs-demo\views\home.html:2
1| <% include header.html %>
>> 2|
这个页面被打开发,因为没有user.username参数。我们避免这样的错误发生。
还记录路由部分里说的get,post,all的作用吗?我现在要回到路由配置中,再做点事情。
修改app.js文件
app.get('/',routes.index);
app.route('/login')
.all(notAuthentication)
.get(routes.login)
.post(routes.doLogin);
app.route('/logout')
app.get('/',routes.index);
app.route('/login')
.all(notAuthentication)
.get(routes.login)
.post(routes.doLogin);
app.route('/logout')
.get(authentication)
.get(routes.logout);
app.route('/home')
.get(authentication)
.get(routes.home);
访问控制:
/ ,谁访问都行,没有任何控制
/login,用all拦截所有访问/login的请求,先调用authentication,用户登陆检查
/logout,用get拦截访问/login的请求,先调用notAuthentication,用户不登陆检查
/home,用get拦截访问/home的请求,先调用Authentication,用户登陆检查
修改app.js文件,增加authentication,notAuthentication两个方法
function authentication(req, res, next) { if (!req.session.user) { req.session.error='请先登陆'; return res.redirect('/login'); } next(); } function notAuthentication(req, res, next) { if (req.session.user) { req.session.error='已登陆'; return res.redirect('/home'); } next(); }
配置好后,我们未登陆,直接访问localhost:3000/home时或者localhost:3000/logout,就会跳到/login页面
登录后, 访问localhost:3000/login 则直接跳到/home页面
到此,express4 相关内容到此为止。
以上内容是小编给大家分享的Nodejs Express4.x开发框架随手笔记,希望大家喜欢。