六、RESTful(表述性状态转移)
REST是英文Representational State Transfer的缩写,中文称之为“表述性状态转移”,基于HTTP协议是另一种服务架构,传递是JSON、POX(Plain Old XML)而不是SOAP格式的数据充分利用HTTP谓词(Verb)侧重数据的传输,业务逻辑交给客户端自行处理.REST是一种分布式服务架构的风格约束,像Java、.Net(WCF、WebAPI)都有对该约束的实现,使URL变得更加有意义,更加简洁明了,如:
http://www.zhangguo.com/products/1 get请求 表示获得所有产品的第1个
http://www.zhangguo.com/products/product post请求 表示添加一个产品
http://www.zhangguo.com/products/1/price get请求 表示获得第1个产品的价格
http://www.zhangguo.com/products/1 delete请求 删除编号为1的产品
REST设计需要遵循的原则
网络上的所有事物都被抽象为资源(resource);
每个资源对应一个唯一的资源标识符(resource identifier);
通过通用的连接器接口(generic connector interface)对资源进行操作;
对资源的各种操作不会改变资源标识符;
所有的操作都是无状态的(stateless)
谓词
GET
表示查询操作,相当于Retrieve、Select操作
POST
表示插入操作,相当于Create,Insert操作
PUT
表示修改操作,相当于Update操作
DELETE
表示删除操作,相当于Delete操作
其它还有:
NodeJS+Express可以很容易的实现REST
application/x-www-form-urlencoded
multipart/form-data
application/json
res.setHeader('Content-Type', 'application/json;charset=utf-8');
示例代码cars.js:
var express = require('express');var router = express.Router();var _= require('lodash');var cars=[];
cars.push({id:201701,name:"BMW",price:190,speed:"210km/h",color:"白色"});
cars.push({id:201702,name:"BYD",price:25,speed:"160km/h",color:"红色"});
cars.push({id:201703,name:"Benz",price:300,speed:"215km/h",color:"蓝色"});
cars.push({id:201704,name:"Honda",price:190,speed:"170km/h",color:"黑色"});
cars.push({id:201705,name:"QQ",price:130,speed:"210km/h",color:"白色"});
/* Get */
/*获得所有汽车*/
/*url /cars/*/
router.get('/', function(req, res, next) {
res.json(cars);
});
/*Get*/
/*获得汽车通过id*/
/*url:/cars/:id */
router.get('/:id', function(req, res, next) {
//从路径中映射参数,转换成数字
var id=parseInt(req.params.id);
var car=_.find(cars,{id:id});
res.json(car);
});
/*Post*/
/*添加汽车*/
/*url:/cars/car */
router.post('/car', function(req, res, next) {
var car=req.body;
//从请求正文中获得json对象
car.id=_.last(cars).id+1;
//将编号修改为最后一辆车的编号+1
cars.push(car); //将汽车对象添加到集合中
res.json(car); //将添加成功的车以json的形式返回
});
/*Put*/
/*修改汽车*/
/*url:/cars/car */
router.put('/car', function(req, res, next) {
var car=req.body; //从请求正文中获得json对象
console.log(req.body);
var index=_.findIndex(cars,{id:parseInt(car.id)}); //根据id获得车在集合中的下标
cars[index]=car; //替换原对象
//res.json(car); //将修改后的车以json的形式返回
res.send({status:"success", message:"更新成功!"});
});
/*Delete*/
/*删除汽车*/
/*url:/cars/:id */
router.delete('/id/:id', function(req, res, next) {
//获得url中的编号参数
var id=parseInt(req.params.id);
var index=_.findIndex(cars,{id:id}); //根据id获得车在集合中的下标
cars.splice(index,1); //在cars数组中删除下标从index开始的1条数据
res.send({status:"success", message:"删除成功!"});
});
module.exports = router;
示例代码app.js:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var users = require('./routes/users');
var pdts = require('./routes/product');
var task = require('./routes/task');
var cars = require('./routes/cars');
var app = express();//指定视图引擎为ejs
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
app.use('/pdt', pdts);
app.use("/task",task);
app.use("/cars",cars);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});// error handlerapp.use(function(err, req, res, next) { // set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
/* Get */
/*获得所有汽车*/
/*url /cars/*/
/*Get*/
/*获得汽车通过id*/
/*url:/cars/:id */
/*Post*/
/*添加汽车*/
/*url:/cars/car */
参数中的json格式一定要使用标准格式,注意引号,注意Content-Type,默认的Content-Type类型是:application/x-www-form-urlencoded
/*Put*/
/*修改汽车*/
/*url:/cars/car */
/*Delete*/
/*删除汽车*/
/*url:/cars/:id */
node.js跨域
修改app.js文件拦截所有的请求,修改头部
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "content-type");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By", ' 3.2.1');
res.header("Content-Type", "application/json;charset=utf-8");
if(req.method == "OPTIONS") {
res.send("200");
} else {
next();
}
});
结果:
追梦猪git地址:https://github.com/jiawenguang/NodeJsWebServer
本文章参考张果大大的教程实现
张果大大git地址:
https://coding.net/u/zhangguo5/p/NodeJSExpress/git
https://coding.net/u/zhangguo5/p/NodeJS001/git
特别鸣谢!