用Express写一个hello world 程序。在合适的地方打开命令行窗口(使用的git bash),mkdir express-tut && cd express-tut && npm init -y, 初始化项目。再 touch server.js, 用于项目入口。由于express 是第三方框架,我们要先安装它,npm install express -S, 最后code . (安装vs code 的时候,加入到path, 所以code . 就可以打开vscode)。server.js 代码如下:
const express = require("express");
const app = express(); app.use((request, response) => {
response.writeHead(, { "Content-Type": "text/plain" });
response.end("Hello, world!");
}); app.listen(, () => {
console.log(`server listen at `)
});
在git bash 中,输入node server 开启服务器,控制台显示‘server listen at 8080’ 表示开启成功。浏览器中输入localhost:8080 可以看到Hello World, 简单吧。项目虽然简单,但也看到了express 项目开发时的核心,app.use() 方法,我们在它的回调函数中来处理请求,app.use()最大的好处就是它可以调用多次,这样,我们就可以把请求处理放到不同的app.use 的回调函数进行,一个函数只做一个功能,依次调用app.use() 方法,完成大的功能。比如,想在响应之前输出请求日志,直接在真正的响应之前添加一个app.use()方法,它接受的函数处理日志,就可以了
const express = require("express");
const app = express(); // 记录请求日志
app.use((request, response, next) => {
console.log("Incomes a " + request.method + " to " + request.url);
next();
}); // 对请求做出响应
app.use((request, response) => {
response.writeHead(, { "Content-Type": "text/plain" });
response.end("Hello, world!");
}); app.listen(, () => {
console.log(`server listen at `)
});
记得重启服务器(node server), 然后刷新浏览器,控制台就可以看到日志了。依次调用两个函数对http 请求进行处理,一个记录日志,一个负责响应,这就是Express 的中间件思想,不是把http请求放到一个大的函数中进行处理,而是把请求进行分解,放到每一个函数中进行处理,
一个函数只做一件事件,Express 则按照函数的书写顺序从上到下依次执行。这些处理函数称为中间件。
再回头看看记录日志的回调函数,你会发现多了一个next参数,当记录完日志后,调用了next() 方法。next() 表示,我这个中间件已经处理完了,可以到下一个中间件了,如果有下一个中间件,下一个中间件会接着处理,这时到了响应请求的中间件。而 响应请求的回调中并没有next 参数,这是因为服务器已经响应完客户端请求了,无需下一步操作了,终止整个响应流程就可以了,所以也就无需调用next().
可以看到中间件的主要功能就是拦截http 服务器提供的请求和响应对象,执行逻辑,或者结束响应,或者把它传递给下一个中间件组件,所以中间件都会接受两个参数:请求对象(req),响应对象(res), 还有一个可选的参数next 函数, 调用next 函数可以传递给下一个中间件组件.
自己创中间件的时候,只要按照这个模式创建就可以了。不过,业界有一种更通用的方法,就是创建一个函数来返回中间件函数,这样有利于创建可配置 的中间件。日志记录中间件修改如下:
const express = require("express");
const app = express(); // 日志记录中间件
function logger (format) {
return function(req,res, next) {
console.log(req[format]);
next();
}
} // 日志调用
app.use(logger('url')); // 对请求做出响应
app.use((request, response) => {
response.writeHead(, { "Content-Type": "text/plain" });
response.end("Hello, world!");
}); app.listen(, () => {
console.log(`server listen at `)
});
实际上,由于中间件是一个个独立的功能,为此有很多第三方中间件可供使用, 比如日志功能 中间件morgan,npm install morgan -S 安装,然后在文件中替换掉我们自己的函数
const express = require("express");
const logger = require("morgan"); // 引入morgan const app = express();
app.use(logger("short")) // 替换掉自己的函数 // 对请求做出响应
app.use((request, response) => {
response.writeHead(, { "Content-Type": "text/plain" });
response.end("Hello, world!");
}); app.listen(, () => {
console.log(`server listen at `)
});
Express 也内置了唯一的内置中间件static,它提供静态文件服务,例如浏览器请求的图片。在express-tut 文件夹下新建public文件夹,存放静态资源,比如放一张图片(如:flower.png) . static 中间件使用也非常简单,它只接受一个参数,就是我们静态文件放置的目录。
const express = require("express");
const logger = require("morgan"); // 引入morgan
const path = require('path'); const app = express();
app.use(logger("short")) // 替换掉自己的函数
app.use(express.static(path.join(__dirname, 'public'))) // 静态资源服务 // 对请求做出响应
app.use((request, response) => {
response.writeHead(, { "Content-Type": "text/plain" });
response.end("Hello, world!");
}); app.listen(, () => {
console.log(`server listen at `)
});
重启服务器,在浏览器中输入localhost:8080/flower.png的时候,网页显示一张图片。但当我们输入localhost:8080 时候,Hello, world! 当有静态文件服务的时候,如果我们请求的静态文件正好和服务器上的资源相匹配,它就会返回静态资源,程序也不会继续执行。 如果没有相匹配的静态资源,程序就会继续执行.
在使用中间件的时候,一定要注意顺序,比如把logger 中间件放到响应中间件的后面,它就不会输出logger了。还有一种高级的用法,那就是中间件的挂载。就是在使用中间件的时候,在它前面添加一个路径,只有在请求的url 中带有此路径,才会调用这个中间件,那么app.use 方法就需要接受两个参数,第一个参数就是路径,第二个参数就是中间件,如 app.use("/admin", admin) ,添加一个admin 中间件, 随便在server.js中添加一下
app.use('/admin',(req, res) => {
switch (req.url){
case '/':
res.end("try user")
break;
case '/user' :
res.end("hello user");
break;
}
});
当输入localhost:8080/admin时,可以看到try user ,表明它执行了admin中间件,且是第一个case, 再输入localhost:8080/admin/user,可以看到 hello user. 它还是执行了admin 中间件,第二个case. 挂载,就是给这个中间件定义一个路径,只有在访问该路径的时候,它才执行, 最常用的地方在于路由
Express路由
路由就是不同的url 响应不同内容,例如用户点击about , 我们就要返回 about 页面,用户点击home,我们就要返回首页。最简单的实现方式是app.method(path, function) . method就是指的get, post 请求,path 指的就是/about, 后面的函数就是对这个请求的处理。如用户点击about, 服务器该怎么返回呢? 它是一个get 请求,请求的是about, 我们要返回about, 就可以这么写,app.get('/about', function(req,res){res.end("about")}). 再写几个路由加深一下理解, 整个server.js 修改如下
let express = require('express')
let app = express(); // 首页路由
app.get("/", function(request, response) {
response.end("Welcome to my homepage!");
});
// about 路由
app.get("/about", function(request, response) {
response.end("Welcome to the about page!");
});
// weather 路由
app.get("/weather", function(request, response) {
response.end("The current weather is NICE.");
});
// 404 页面
app.use(function(request, response) {
response.statusCode = 404;
response.end("404!");
});
app.listen(8080)
我们在浏览器中输入localhost:8080/about, 就看到 Welcome to the about page。
Express模版引擎
Express增加了对许多模板引擎的支持,如pug(jade), ejs等,可以动态输出html. 使用模版引擎有三个步骤,安装,注册,配置, 用ejs 演示一下
安装很简单 npm install ejs -S; 注册是对express 不支的模版如handlebars 而言的,由于Express 原生支持ejs, 所以不需要注册;配置,就是告诉Express要使用哪个模版引擎,模版文件放在什么地方,以便Express在渲染的时候知道从哪里去寻找模版。
在express-tut(根目录) 中新建views文件夹,用于放置模版文件, 在views文件夹中新建一个模版文件,如index.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello, world!</title>
</head>
<body>
<%= message %>
</body>
</html>
在server.js中配置模版引擎
app.set("view engine",'ejs'); // 设置 view engine, 使用ejs模版引擎
app.set("views", path.resolve(__dirname,'views')) // 设置views,模版放置的地方
动态渲染模版,输出html。 要调用res.render()方法,render 方法,接受一个参数就是我们要渲染的模版的名称,还有一个可选的参数,就是向模版中输入的数据 来替换模版中的变量。调用render方法的时候,express 就向views 文件夹中寻找对应的模版,这也是我们 app.set("views",...) 的原因。
app.get('/', function(req,res){
res.render('index',{
message:"this is a ejs view"
})
})
完成的server.js 如下,把其他的日志,static 都删除了,在浏览器中输入localhost:8080, 就看到 this is a ejs view。
const express = require("express");
const path = require('path'); const app = express(); app.set("view engine",'ejs'); // 设置 view engine, 使用ejs模版引擎
app.set("views", path.resolve(__dirname,'views')) // 设置views,模版放置的地方 // 对请求做出响应, 渲染模板
app.get('/', function(req,res){
res.render('index', {
message:"this is a ejs view"
})
}) app.listen(, () => {
console.log(`server listen at `)
});
Express 的基本知识就差不多了,通过一个留言本实例来加深Express 的认识 ,再多加一个中间件 body-parser,用来解析post请求 npm install body-parser --save,
server.js 文件如下:
// 引入各种模块依赖
const express = require('express');
const logger = require('morgan');
const bodyParser = require('body-parser');
const path = require('path'); // 利用express 创建应用
const app = express(); // 设置模版引擎为ejs
app.set('views', path.join(__dirname, 'views'));
app.set('view engine','ejs'); // 创建一个数组对象,保存用户通过表单上传的内容
var entries = []; // app.locals,它是一个对象,提供整个app应用所需要的数据,这时属性entries就可以用在模版中
app.locals.entries = entries; // 使用morgan 中间件记录请求日志
app.use(logger('dev')) // 利用body-parser 中间件获取用户上传的数据,通过这个中间件,用户上传的数据都会附在req.body的属性上。
app.use(bodyParser.urlencoded({extended: false})) //路由的设置
app.get('/', (req,res) => {
res.render('index');
})
app.get('/new-entry', (req,res) => {
res.render('new-entry');
}) app.post('/new-entry', (req,res) => {
if(!req.body.title || !req.body.body) {
res.status(400).send('Entris have a title and body')
return;
}
entries.push({
title:req.body.title,
content: req.body.body,
published: new Date()
})
res.redirect('/')
}) // 当用户访问页面,我们的路由都不匹配时,提供回退404页面
app.use((req,res) => {
res.status(404).render('404')
}) // 监听3000端口,启动服务
app.listen(3000, () => {
console.log('server started on port 3000')
})
这时需要提供几个页面,index.ejs, new-entries.ejs, 404.ejs, 由于几个页面都有共同的footer和header, 所以我们可以把header 和footer 单独提取出来,形成header.ejs 和footer.ejs,其它页面直接引进就可以了。在views 文件夹中新建这几个页面
header.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>留言板</title>
<!--引入bootstrap 提供简单的样式-->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body class="container">
<h1>
Express 留言板
<a href="/new-entry" class="btn btn-primary pull-right">
写一个留言
</a>
</h1>
footer.ejs
</body>
</html>
index.ejs 页面主要显示我们留言的内容,而我们所有的留言都存在的entries数组中,所以要用ejs中的循环对entries 进行遍历,对内容进行输出。由于第一次进入页面,我们并没有任何留言,所以要对entries 进行判断,如果没有内容,要让用户添加留言
<!--引入header-->
<% include header %> <!--对entries进行判断-->
<% if (entries.length) { %>
<!--有内容,进行循环遍历,显示内容-->
<% entries.forEach(function(entry) { %>
<div class="panel panel-default">
<div class="panel-heading">
<div class="text-muted pull-right">
<%= entry.published %>
</div>
<%= entry.title %>
</div>
<div class="panel-body">
<%= entry.content %>
</div>
</div>
<% }) %>
<!--没有内容,提示用户添加留言-->
<% } else { %>
没有留言内容! <a href="/new-entry">添加一个留言</a>
<% } %> <!--引入footer-->
<% include footer %>
所以当第一次进入页面时显示以下内容
当用户点击添加一个留言, 我们要跳转到添加留言的页面,就是/new-entry页面,这时添加new-entry页面,它就是一个form 表单
<% include header %> <h2>书写一个留言</h2>
<form method="post" role="form">
<div class="form-group">
<label for="title">标题</label>
<input type="text" class="form-control" id="title"
name="title" placeholder="标题" required>
</div>
<div class="form-group">
<label for="content">内容</label>
<textarea class="form-control" id="body" name="body"
placeholder="内容" rows="3" required></textarea>
</div>
<div class="form-group">
<input type="submit" value="提交留交" class="btn btn-primary">
</div>
</form> <% include footer %>
当提交订单的时候,我们并没有给form 表单添加action, 表单内容提交到什么地方? 原来表单中没有指定action时,它会提交到当前页面/new-entry, 正好对应server.js中的app.post(‘/new-entry’), 所以当提交订单时,服务端会收到我们传过去的内容。
页面内容展示如下:
最后提供一个404.ejs页面
<% include header %>
<h2>404! Page not found.</h2>
<% include footer %>
好了,在命令行中输入node server.js 开启服务器,然后在浏览器中输入localhost:8080体验一下。
如果我们想使用handlebars 作为模板呢?也没有问题,不过 需要安装第三方模块express-handlebars 进行支持,并且还要注册模板引擎。npm install express express-handlebars -S, 安装完成,在server.js 中引入express-handlebars.
const exphbs = require("express-handlebars")
调用app.engine() 进行注册,内容如下
app.engine("handlebars", exphbs({
defaultLayout: "main",
layoutDir: app.get('views') + '/layouts',
partialsDir:[app.get('views') + '/partials']
}))
app.engine 接受两个参数,一个是名字,这很好理解,注册肯定要给它起个名字,以便后面使用。第二个是handlebars 的配置,exphbs 是一个函数,接受对象作为参数进行配置。default Layout:默认布局文件名称, layoutDir, 布局文件所在的目录,partialsDir局部文件所在的目录,为什么这么定义呢?需要了解一下handlebars 中的基本概念 : 布局,局部, 还有视图。
视图(views): 就是我们定义的任何的模板片段
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">欢迎使用handlebars</h3>
</div>
</div>
布局:也是一种模版,不过作用比较特殊,所以单独列出来。想一下我们的网站,主要分为header ,main, footer 三个部分,通常header ,footer 部分是不变的,只有main 是经常改变的, 程序在运行的过程中,只要动态的替换掉main 就可以了。这时我们就可以定义一个文件,包含不变的header, footer 和 可变的main,这个文件就是布局,所以在注册handlebars的时候,我们设置 defaultLayout 为main,layoutDir文件夹
局部文件(partial):有些时候,有几个页面要共用相同的部分,如侧边栏这,我们通常都会封装为组件,然而在handlebars 中,它们称之为局部文件partial,可以知道局部文件也是代码片段。我们在注册模版引擎的时候,设置 partialsDir
好了,注册成功了,就要告诉express来使用 handlerbars, 调用app.set 方法,第二个参数是我们注册的模板的名字,就是app.engine中第一个参数,他们要保证一致
app.set(“view engine”, 'handlebars' )
最后还要告诉express 我们的模版文件放在什么地方,以便express 去查找使用,还是要调用app.set() 方法
app.set("views", __dirname+ "/views"); // 第一个参数views是复数,一定不忘记后面的还有一个s, 要不然会报 View is not a construction
现在可以使用handlebars 了,不过根据handlebars 在注册时的配置,还需要views 文件夹下面再建两个文件夹 layouts 和partials, layouts 下面建立main.handlebars 作为布局 文件。注意,文件要以handlebars为后缀名,因为我们注册的模板就是handlebars。简单写一个布局文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Express Handlebars 使用</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" >
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-8">
{{{ body }}}
</div>
<div class="col-sm-4">
{{> partial }}
</div>
</div>
</div>
</body>
他就是定义整个网页的骨架,可以看到里面有两个特殊的地方{{{body}}}, 我们的view 就会渲染在{{{body}}}占位符所在的地方。{{> partial }} 局部文件的名称, 把局部文件partial.handlebar 放到这个地方。在views 文件夹中定义一个index.handlebars, 还是上面的视图吧
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">欢迎使用handlebars</h3>
</div>
</div>
在partials 文件下,建一个partial.handlebar 文件
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">侧边栏</h3>
</div>
</div>
定义的视图,布局,局部文件,我们怎么使用呢?这要用到render方法,去渲染模版。render 方法是定义在res 响应对象上的,所以我们浏览器端发起一个请求,让它输出动态模版,所以我们在 server.js 中定义一个路由,整个server.js如下
var express = require('express'),
app = express(); // 引入express-handlebars
var exphbs = require("express-handlebars") // 设置模板存放路径
app.set("views", __dirname+ "/views") // 注册handlebars模板引擎
var hbs = exphbs.create({
defaultLayout: "main",
layoutDir: app.get('views') + '/layouts',
partialsDir:[app.get('views') + '/partials']
});
app.engine('handlebars', hbs.engine); // 告诉express使用handlebars模板,
// 第二个参数是我们注册的模板的名字,就是app.engine中第一个参数,他们要保证一致
app.set('view engine', 'handlebars' ) // render 渲染模板
app.get('/', function (req,res) { res.render('index')
})
app.listen(8080);
render方法,接受一个参数,那就是要渲染的模版(视图)的名字,当exrpess 执行render 的时候,它会从views 文件夹下找到我们指定的文件,然后再找到布局文件,替换掉里面的{{{body}}},如果有partial, 它还会从particals 文件夹下找到局部文件,进行合并,形在一个完整的html文件进行输出。这也就是我们上面一系列设置文件夹的原因。
我们每次渲染一个视图文件时,都会结合layout 布局模版渲染, 有时我们并不需要layout布局模版,这时可以在render 方法中进行设置 layout: false
app.use(function (req,res) {
res.render('404', {
layout: false
});
})
在设置模版引擎的时候,我们只指定了一个默认的布局视图,如果我们带想使用其他视图,怎么办? 调用render 方法的时候,指定layout,当然要确保这个layout文件在layout文件夹中。
app.get('/foo', function(req, res){
res.render('foo', { layout: 'microsite' });
})
那么我们在渲染的时候要给time传递参数, render 方法可以接受第二个可选参数,它是一个对象, 就是我们向模版中传递的数据,对象的属性就是我们在模版中定义的表达式,如time
res.render('index' , {
time: Date.now()
})
这时我们发现,页面中显示的日期,但它是日期毫秒数,我们想把他转化成年月日的形式,这就要执行一定的逻辑操作,但是handlebars不支持在模版中使用逻辑的,这时要用到 helper 助手。它其实是一个函数,对模版中的表达式执行逻辑操作, helper 在模版中使用之前要先注册。这时有两种方法,
一种是 在注册handlebars 模版引擎的时候,直接给它配置helpers
var hbs = exphbs({
defaultLayout: "main",
layoutDir: app.get('views') + '/layouts',
partialsDir:[app.get('views') + '/partials'],
// 增加helpers
helpers: {
timeFormate: function (time) {
var dateTime = new Date(time)
return dateTime.getFullYear() +"年"+ (dateTime.getMonth()+1)+ "月" +
dateTime.getDay() +'日'
}
}
});
一种是在调用render 方法的时候给它配置helpers
app.get('/', function (req,res) { res.render('index' , {
time: Date.now(),
//配置helpers
helpers : {
timeFormate: function (time) {
var dateTime = new Date(time)
return dateTime.getFullYear() +"年"+ (dateTime.getMonth()+1)+ "月" +
dateTime.getDay() +'日'
}
}
})
})
上面的第一种配置方式,可以叫做全局配置,因为它在所有的模版文件中都可以使用,下面的一种则只能在 index模版中使用,可以叫做局部配置。
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">
<!-- 增加 timeFormate helper -->
欢迎使用handlebars模板 <small>{{timeFormate time}}<small>
</h3>
</div>
</div>
express-handlebars还支持子目录, 所以如果你有大量的局部文件,可以将它 们组织在一起。例如,你有一些社交媒体局部文件,可以将它们放在views/ partials/social 目录下面, 然后使用{{> social/facebook}}、{{> social/twitter}} 等来引入它们。
Express学习(1) ------Express 入门的更多相关文章
-
前端学习 node 快速入门 系列 —— 报名系统 - [express]
其他章节请看: 前端学习 node 快速入门 系列 报名系统 - [express] 最简单的报名系统: 只有两个页面 人员信息列表页:展示已报名的人员信息列表.里面有一个报名按钮,点击按钮则会跳转到 ...
-
express学习-express搭建后台
前言:本文是纯用node express做一个后端服务的教程,并不等同于express官网的入门教程,本文也并不涉及任何高级的Node服务端性能优化等知识. 本文是在已经看过express官方入门指南 ...
-
Node 之 Express 学习笔记 第一篇 安装
最近由于工作不忙,正好闲暇时间学学基于 node 的 web开发框架. 现在关于web开发框架除了Express 还有新出的 KOA以及其它一些. 但是想想还是先从 Express 入手吧.因为比较成 ...
-
Sql Server 2008开发版(Developer Edition)过期升级企业版(Enterprise Edition)失败后安装学习版(Express Edition)
最近一个多月,甚是悠哉,无事可做.上线的网站系统也没接到客户的反馈,反而觉得无聊之极了.上周五早上,一上QQ,就收到客户发来消息,管理平台无法登陆了.心里一惊,立马开始查找故障原因.翻看了系统日志,提 ...
-
# nodejs模块学习: express 解析
# nodejs模块学习: express 解析 nodejs 发展很快,从 npm 上面的包托管数量就可以看出来.不过从另一方面来看,也是反映了 nodejs 的基础不稳固,需要开发者创造大量的* ...
-
express学习(三)—— cookie和session
express学习(三)-- cookie和session cookie存在浏览器中,最大只能保存4K数据,不安全 session存在服务器中,不能独立(先读取cookie再读取session),较安 ...
-
Node.js、Express、Socket.io 入门
前言 周末断断续续的写了第一个socket.io Demo.初次接触socket.io是从其官网看到的,看着get started做了一遍,根据官网的Demo能提供简单的服务端和客户端通讯. 这个De ...
-
Nodejs学习总结 -Express 登录注册示例(二)
项目创建后,我们来做个登录注册实例,详细操作步骤如下. 1.新建项目demo ,具体操作步骤参考上一章内容 https://www.cnblogs.com/Anlycp/ 2.添加mysql和sess ...
-
express 学习笔记
首先把这个库加载下来 npm install -g express 这样会安装它所有依赖包,这个非常恐怖.这个框架要依赖这么多外来的东西,如果有一个不与时俱进就会拖累整个框架的质量. C:\windo ...
随机推荐
-
Ant环境变量配置
Ant环境变量配置 1.新建系统变量ANT_HOME 变量名: ANT_HOME 变量值: D:\biancheng\apache-ant-1.7.1 2.修改PATH 变量值最后面 ...
-
HTTP协议/RTSP协议/RTMP协议的区别
RTSP. RTMP.HTTP的共同点.区别 共同点: 1:RTSP RTMP HTTP都是在应用应用层. 2: 理论上RTSP RTMPHTTP都可以做直播和点播,但一般做直播用RTSP RTMP, ...
-
中值排序的java实现
public class MidSort { public static void main(String[] args){ ,,,,,,,,}; midSort(arr,,); for(int i: ...
-
Spring boot中使用springfox来生成Swagger Specification小结
Rest接口对应Swagger Specification路径获取办法: 根据location的值获取api json描述文件 也许有同学会问,为什么搞的这么麻烦,api json描述文件不就是h ...
-
ZOJ 2477 Magic Cube 暴力,模拟 难度:0
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1477 用IDA*可能更好,但是既然时间宽裕数据简单,而且记录状态很麻烦,就直接 ...
-
现在有m组n个有序数组,例如{1,2,3,4},{2,3,4,6},{1,3,5,7},在这些数组中选择第k小的数据,然后返回这个值
问题描述:现在有m组n个有序数组,例如{1,2,3,4},{2,3,4,6},{1,3,5,7},在这些数组中选择第k小的数据,然后返回这个值 思路:参照两个数组归并的过程,每次选取最小的数据进行比较 ...
-
【慕课网实战】Spark Streaming实时流处理项目实战笔记十四之铭文升级版
铭文一级: 第11章 Spark Streaming整合Flume&Kafka打造通用流处理基础 streaming.conf agent1.sources=avro-sourceagent1 ...
-
__iter___和__next__方法
__iter__方法变成一个迭代器类对象, 迭代器类要实现__next__方法
-
Aggregated Counting(找规律 + 预处理)
Aggregated Counting 转 : https://blog.csdn.net/cq_phqg/article/details/48417111 题解: 可以令n=1+2+2+3+3+.. ...
-
PS官方正式中文版(搬砖分享)
https://pan.baidu.com/s/1c3IdQq0 PS官方正式中文版(搬砖分享) 注意事项: 1.安装开始前请先断网,在成功破解激活前请全程断网: 2.安装完成后先试运行软件一次,然后 ...