信息获取来源Eno Yao
express
express其实就是先想用JS语言配合nodejs环境搭建服务器
服务器作用就是处理请求,响应结果,就如php和java要有运行环境
前端 | 后端 |
---|---|
客户端 | 服务端 |
浏览器 | 服务器 |
JS,HTML,CSS | PHP(APACHE),JS(NODEJS),JAVA(JDK) |
http | localhost | 3000 | /katsuki.html | ?id=18 | #hash |
---|---|---|---|---|---|
协议 | 域名 | 端口 | 路由 | 参数 | 哈希值 |
创建js服务
切换不同的路由,就进入不同的逻辑,
也就是浏览器输入不同路径,页面就有不同的返回结果
下面案例说明
项目结构
katsuki.html
service.js
katsuki.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p>katsuki</p>
</body>
</html>
service.js
var express = require("express");
var app = express(); // 实例化一个express的服务器应用
// console.log(app);
// 服务器处理路径为 / 的get请求 请求和响应
// 处理完成后,将执行后面的回调函数
// 处理前端发过来(一般就是ajax)的请求request (数据处理,数据库操作,文件读写)
// 后端根据需要去返回对应的结果response
nodejs php
// req -> $_GET[] $_POST[]
// mysql_query()
// res -> echo
app.get("/", (req, res) => {
//字符串katsuki desu解析到页面
res.send('katsuki desu')
})
app.get("/katsuki.html", (req, res) => {
// 读文件
function readFile(){
return new Promise((reslove,reject) => {
fs.readFile("./katsuki.html", (err, data) => {
//data本来是文件的buffer流二进制数据
//加上 toString()后为正常文件内容
//这里拿到katsuki.html的标签结构
reslove(data.toString())
})
})
}
// 响应结果
function echo(data){
//字符串data解析到页面
res.send(data);
}
(async function(){
let data = await readFile();
await echo(data);
})()
})
app.listen(3000) //用3000端口处理请求
console.log("开启服务器");
控制台输入
node service
开启服务
浏览器中输入
http://localhost:3000 进入 /路由 页面显示katsuki desu
http://localhost:3000/katsuki.html 进入 /katsuki.html路由 页面显示读文件的data内容
express的脚手架
什么是express的脚手架?就是一键搭好express的平台
全局安装
npm install -g express-generator@4
在一个文件夹里面用express
命令创建应用架构
express katsuki-project
cd katsuki-project
进入katsuki-project文件夹安装依赖,推荐cnpm安装所有依赖
npm install
执行到此的项目结构如图
routes 路由
public 存放静态资源(和后端无关系)
app.js 入口文件
express端口设置
该脚手架的默认端口为3000
如需修改,则在app.js
文件中添加
该方式添加,2000,3000端口均可访问
app.listen(2000);
该方式修改,只能使用2000端口访问
process.env.PORT = 2000;
启动应用
npm run start
npm start 只有start可以省略run
访问在浏览器3000端口号
http://localhost:3000 目录中的index.js的/作为路由打开页面
http://localhost:3000/users 目录中的users.js的/作为路由打开页面
创建路由
若对routes的js进行以下修改
index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
//原本的
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
//添加的
router.get('/katsuki', function(req, res, next) {
res.send('i_katsuki');
});
module.exports = router;
users.js
var express = require('express');
var router = express.Router();
/* GET users listing. */
//原本的
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
//添加的
router.get('/katsuki', function(req, res, next) {
res.send('u_katsuki');
});
module.exports = router;
访问路径
目录中的index.js的/katsuki作为路由 打开页面出现i_katsuki
http://localhost:3000/katsuki
目录中的users.js的/katsuki作为路由 打开页面出现u_katsuki
http://localhost:3000/users/katsuki
express的处理请求和响应
建议使用谷歌浏览器的ApiDebug-接口调试插件模拟请求
GET | POST | JSONP | COOKIE |
---|---|---|---|
req.query | req.body | req.query | req.cookies |
在上面的脚手架搭建环境下,在routes中创建
account.js
var express = require('express');
var router = express.Router();
req浏览器信息(请求) res服务器信息(响应)
router.get('/katsuki', function (req, res, next) {
//拿到 get请求发送的请求url
console.log(req.query);
res.send('katsuki');
});
router.post('/kasami', function (req, res, next) {
//拿到 post请求发送的请求body
console.log(req.body);
res.send('kasami');
});
router.get('/Grisaia', function (req, res, next) {
//拿到 get请求发送的请求header
console.log(req.header);
//假设请求的key命名为 ka tsu ki
let {
ka,
tsu,
ki
} = req.headers;
//这样可以拿到对应传递名称的值,任何请求获取都一样
console.log(ka,tsu,ki);
res.send('Grisaia');
});
module.exports = router;
app.js中添加
var accountRouter = require('./routes/account');
app.use('/account', countRouter);
像这样在routes中添加编辑路由文件即为路由处理
上述处理完成开启服务即可访问下面链接
http://localhost:3000/account/katsuki get请求
http://localhost:3000/account/kasami post请求
最深层次来讲,get和post其实没有区别,这两种方式的参数能放url也能放请求体。只是一般认定get参数放url,post参数放请求体,毕竟jQuery的ajax的get/post就是设定成这里描述的一般情况。
express的跨域处理
假设本地有个get.html文件,引入jQuery,想在本地打开发送get请求到http://localhost:3000/account/katsuki
会有跨域问题,本地是file文件协议,访问的是http
get请求
get.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<script src="jquery.js"></script>
<script>
$.ajax({
//不写type默认是get
url: "http://localhost:3000/account/katsuki",
data: {
name: "katsuki"
},
success(data) {
console.log(data)
}
})
</script>
</body>
</html>
在上面的account.js添加res.append
var express = require('express');
var router = express.Router();
router.get('/katsuki', function (req, res, next) {
//在响应头添加这句,允许跨域
res.append('Access-Control-Allow-Origin', '*');
console.log(req.query);
res.send('katsuki');
});
module.exports = router;
打开html文件,成功发送data
post请求
post.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<script src="jquery.js"></script>
<script>
$.ajax({
type: 'post'
url: "http://localhost:3000/account/katsuki",
data: {
name: "katsuki",
skill:['js','css']
},
success(data) {
console.log(data)
}
})
</script>
</body>
</html>
router.all()
var express = require('express');
var router = express.Router();
all允许所有请求类型,get post put 等等
router.all('/katsuki', function (req, res, next) {
res.append('Access-Control-Allow-Origin', '*');
console.log(req.query);
console.log(req.body);
res.send('katsuki');
});
module.exports = router;
jsonp
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<script src="jquery.js"></script>
<script>
// 保留全局函数
function callback(data){
console.log(data)
}
var script = document.createElement("script");
//请求获取到callback('katsuki'),生成script时执行
script.src = "http://localhost:3000/account/katsuki";
document.body.appendChild(script);
</script>
<!-- <script>
callback('katsuki')
</script> !-->
</body>
</html>
var express = require('express');
var router = express.Router();
all允许所有请求类型,get post put 等等
router.all('/katsuki', function (req, res, next) {
res.append('Access-Control-Allow-Origin', '*');
console.log(req.query);
console.log(req.body);
res.send(`
callback('katsuki')
`);
});
module.exports = router;
express的全局拦截
app.js中的app.use(),就是用于校验拦截,只有通过才能进入请求的路径
app.use(logger('dev'));
app.use(express.json());
//中文字符串转码
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
//请求带后缀时,在此处拦截,比如请求服务器拿.jpg .mp3文件等
//文件会进入public文件夹找到文件,返回给请求
app.use(express.static(path.join(__dirname, 'public')));
//全局拦截,每个请求进来都会被拦截到这加上下面的响应头,达到不跨域效果
app.use(function(req, res, next) {
// 就是cors解决跨域方案
res.append('Access-Control-Allow-Origin', '*');
next();
});
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/account', countRouter);
访问public文件
假设之前的项目结构的public
下有个katsuki.html
,public/images
中有个katsuki.jpg
打开网页
http://localhost:3000/katsuki.html
网页输入,得到图片,这种路由称为特殊路由
http://localhost:3000/images/katsuki.jpg