17年二月份的时候对前端产生了非常浓厚的兴趣,于是开始学习前端等技术.陆陆续续看了5个多月的视频,写了一些demo.但是,学习过程中发现,单纯的前端,是没有办法独立去访问后台的数据的,ajax正常情况是没有办法跨域的!(当时知道了这个事实后难过了很久orz),于是,在查阅了部分资料后决定:学前端的最终目的就是以node.js为后台框架,搭建一个前后端分离的前端服务器!
但是过程是比较痛苦的,那时候对后台理解确实接近为0,不知道何为缓存,三层架构是什么概念,路由分发什么的也是懂的不多,后台io什么的不懂.仅仅凭着的js的理解就想做好一个后台的服务器,理解的过程确实是十分艰辛,当时的想法是数据的获取从java后台获取,自己做个中转给前端页面,然后一路摸爬滚打的写了出来.
在搭完一个nodedemo后,毅然决然的投入到java的大军中,从基础开始学起.
---5个月后---
java学完,对后台有了一定的理解,现在重新审视当初的nodedemo,以java的角度去理解其中的语言.
首先,贴一下当时六月份搭建的node项目demo结构图:
1.config:存放配置文件,用户路由跳转等
2.controller:存放用户的访问行为,tools处理的是后台访问数据的路径,view存放的后台访问页面的路径,后面会细说
3.node_modules:node依赖库,类似maven依赖,cocoapods
4.public:静态页面存放位置,java中这个文件夹就是webapp了
app.js
这是项目的入口文件,相当于iOS 的main函数,java启动项目有两种,一种是把项目打包到tomcat容器中,用容器去启动项目.一种是用maven的tomcat插件工具,用内置tomcat形式启动.而node作为一个服务器,是不需要tomcat容器的(其实还是得装个node环境啦~~,云服务器也是)
启动方式是进入到项目的根目录,在命令行中配置 node app.js,运行即可启动,退出方式是ctrl+c
学完java后重新过来看,发现node真的是一个很干净很纯洁的一个框架,所以的东西都是需要自己去配,这给我一种sub3的感觉,纯自定义
下面逐行解析一下app.js代码
模块引入
var express = require('express'),
path = require('path'),
session = require('express-session');
var app = express();
这里引入了一些必要的组件,然后将express对象化.相当于启动了一个服务器!
配置文件引入
var config = require('./config/config'),
routeConfig = require('./config/routeConfig'),
routeRequrestApi = require('./config/routeRequrestApi'),
routeViewsApi = require('./config/routeViewsApi');
这里引入了一些配置文件,大概意思就是静态路径位置,api路由跳转分配,页面路由跳转配置,我很喜欢java的配置文件概念,很多东西都是以配置的文件的方式去读取,比如db.properties,contextConfig.xml,SqlMapConfig.xml等,而iOS 这块则是弱化了配置文件的概念,宏定义这种东西还是给我一种在改代码的感觉,全局宏一改编译又需要挺久的,如果用extern会相对好一些,毕竟不是字符串替换什么的
node提供了一种很舒服js引入方式,require("***.js"),这样就可以以对象调用的方式来调用这个js里面的属性或者方法,当时第一次接触的时候觉得非常神奇,???,还能这样玩?这是new了吗?其实我觉得还是伪对象,并不是实例化
页面引擎与静态资源路径
//设置模板
app.set("view engine",'ejs');
//设置render查找的ejs目录
app.set('views', path.join(__dirname, "public"));
//设置静态页面
// app.use(express.static("public"));
app.use(express.static(config.staticPath));
之前不太理解,现在差不多懂了,一个正常的html承载不了一个模板数据的加载,必须使用特殊的页面加载,类似java中的jsp,可以使用el语法等还有jsp语法,这里的ejs其实和jsp的语法基本一样,其他类似的还有jade这种格式的页面
关于设置render查找ejs页面,设置静态资源路径这块,用java的方式去理解,如下图
在给war项目增加web.xml文件时,系统会自动给我们生成一个静态资源访问的路径,那就是webapp,而node需要我们手动配,这里需要填一点的是__dirname指的是当前模块app.js所在的文件夹绝对路径,这里是系统根路径,然后拼接上同目录下的public即可,而如果你用相对目录的话,这个相对目录找的是当前服务启动入口的相对目录,很容易出错,基本上项目用的是__dirname
cookie-Parser
//===================== cookie parser =====================
var cookieParser = require('cookie-parser');
app.use(cookieParser());
cookie-parser这个在我的字面意思看来应该是对cookie的解析的意思,这个我目前没有在java中见到应用,资料说是将http传入的cookie信息存入到req.cookie,而在java中,移动端传入的数据都是body拿到的,而cookie这种东西只在b/s结构中使用,springmvc中是直接在mapping的方法参数中拿到传入的body,同时参数中的req是可以直接拿到cookie的,所以可能是springmvc框架帮我做的(目前的猜测).
讲到这顺便说一句,express的use这个函数基本作用是两个:
1.调用中间件
2.匹配请求路径
后续使用到的时候会继续提及
session设置
//===================== session !!! 必须在cookieParser的后面 =====================
app.set('trust proxy', 1);// trust first proxy
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: {secure: true }
}));
cookie和session在iOS 端基本没有提及,在浏览器端经常使用,session是后台的东西,相当于当前用户的唯一标识,在一次会话过程中(跟req请求有点不一样),将session过期时间设置时间长点,后台就可以用session存储用户的数据什么的.
这里的参数什么的不太懂,网上基本都是这么设置的,后续有机会深入的话我会再加说明
body-parser
//===================== body parser =====================
var bodyParser = require('body-parser');
// application/json
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));//使用body-parse,req.body自动转为对象
body-parser实现的内容是将请求体解析赋值给req.body,后台取请求体的时候直接调用req.body即可,当然他还有其他功能,比如针对不同的数据类型做相应的解析,如果text/plain,text/json,注意:不能解析那种文件上传的格式,叫什么multipart什么的!如果是那种的话,需要用其他的解析器
java这边,springmvc都帮我们做好了o(╯□╰)o(实在强大)
url路由跳转处理
//设置api数据处理路由
app.use('/api',routeConfig(routeRequrestApi));
//设置页面路由
app.use('/',routeConfig(routeViewsApi));
//最后设置一个出错页面
app.use((err,req,res,next)=>{
// if (!err) {
// return next();
// }
// if (err) throw err;
res.status(404).send('err');
});
这是匹配路径的代码,es6的语法是可以忽略function的,具体的信息下面的图片说明:
这里面核心的关键代码在routerConfig.js,用的是路由的一个方法
router[get)("/login","../controller/views/my") (ps:不能用中括号)
这是目前我能想到的最简单的匹配路由的方式了,routerRequestApi.js是数据请求的js,routerView.js是页面跳转的js,两个都暴露出数组,然后用循环一个个跳转维护
最后还有一个监听错误路径路由跳转的,就是访问非配置过的路径时的跳转路由
app监听端口启动
app.listen(3000,(err)=>{
if (err) {
throw err;
}
console.log('启动服务器成功,监听3000');
});