uni-app 的 API 与微信小程序 API 基本一致。掌握微信小程序 API 对后面的开发很有帮助。微信小程序 API 文档:https://developers.weixin.qq.com/miniprogram/dev/api/
模板方法模式是定义一个操作中的算法的骨架,从而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。通常对于一些重要的复杂方法和多个子类共有的方法且逻辑相同的情况下会使用模板方法模式。比如用户第三方用户认证的时候就比较适合使用模板方法。我们来看一个例子:假设我们现在需要用到微信、微博的第三方用户授权来获取用户的信息。//使用模板方法模式描述获取第三方用户信息的过程 public abstract class Authentication{ public void checkUserAuthentication(){ checkIdentity(); fetchInfo(); } protected abstract void checkIdentity(); protected abstract void fetchInfo(); } //微信用户 public class WechatAuthenication extends Authentication{ @Override protected void checkIdentity() { System.out.println("获得微信用户授权"); } @Override protected void fetchInfo() { System.out.println("获取微信用信息"); } } //微信用户 public class WeiboAuthenication extends Authentication{ @Override protected void checkIdentity() { System.out.println("获得微博用户授权"); } @Override protected void fetchInfo() { System.out.println("获取微博用信息"); } } //调用模板方法 public class Demo{ public static void main(String...s){ Authentication auth = new WechatAuthenication(); auth.checkUserAuthentication(); auth = new WeiboAuthenication(); auth.checkUserAuthentication(); } }输出结果:获得微信用户授权 获取微信用信信息 获得微博用户授权 获取微博用信信息现在我们使用 Lambda 表达式换个角度来思考模板方法模式。如果我们用函数式接口来组织模板方法中的调用过程,相比使用继承来构建要显得灵活的多。//定义一个处理接口,用来处理一项事务,如授权或者获取信息。 public interface Processer{ public void process(); } //封装调用过程 public class Authentication{ private final Processer identity; private final Processer userinfo; public Authentication(Criteria identity,Criteria userinfo){ this.identity = identity; this.userinfo = userinfo; } public void checkUserAuthentication(){ identity.process(); userinfo.process(); } } //使用模板方法 public class Demo{ Authentication auth = new Authentication(()->System.out.println("获得微信用户授权"), ()->System.out.println("获取微信用户信息")); auth.checkUserAuthentication(); auth = new Authentication(()->System.out.println("获得微博用户授权"), ()->System.out.println("获取微博用户信息")); auth.checkUserAuthentication(); }输出结果:获得微信用户授权 获取微信用信信息 获得微博用户授权 获取微博用信信息此时,我们的模板方法得到了大幅的简化,同时通过函数接口让模板方法获得了极大的灵活性。
注册微信小程序账号,获取到 AppID,我们后面配置的时候会用到。在 HBuilderX 工具栏,点击发行,选择小程序-微信。输入小程序名称和 AppID,单击发行就可以了。这样我们就会获得一个微信小程序的打包文件,接下来我们来发布微信小程序项目,打开微信小程序开发者工具,导入刚刚生成的微信小程序项目的打包文件,在微信小程序开发者工具中先测试一下,项目运行是否正常,项目测试没有问题后,点击右上角>>按钮,上传代码就可以发布微信小程序了,最后等待微信团队审核通过,别人就可以在线上访问到你的项目了。
Hystrix 针对与分布式系统,其提供了服务容错、服务降级、服务反馈、服务快速失败,快速恢复、延迟降低、服务实时监控等功能,经过近 6 年的发展,Hystrix 已经形成了较为稳定的生态社区以及服务支撑,目的就是为了保证我们的分布式系统能够安全平稳的运行。总结:Hystrix 其实就是为了解决在分布式系统中出现的延迟问题、服务间问题而来的一款微服务组件,其依赖于 Spring Cloud 框架,通过提供一系列保障措施,来保证我们的分布式系统可以安全平稳的运行。
Flask 是一个 Python 实现的 Web 开发微框架,但是这个“微”并不代表着 Flask 功能比较简陋、有所欠缺。微框架中的 “微” 意味着:Flask 旨在保持核心简单而易于扩展;Flask 不会替用户做出太多决策,比如使用何种数据库;Flask 的选项(比如使用何种模板引擎) 通常有多个,用户很容易替换。默认情况下,Flask 不包含数据库抽象层、模板引擎、身份认证或其它任何已有多种库可以胜任的功能,如下图所示。然而,Flask 支持用扩展来给应用添加这些功能,应用程序可以很方便的集成这些扩展。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。
在这一节知识点中,我将带领大家一起学习 <head>标签的相关知识点。<head>标签,是一个对于网页极其重要的标签。在整个前端开发领域算得上不可不知的程度。<head> 标签可谓是“藏龙卧虎”。别看它外观简短,却处处定义着一个网页的“大事”。<head> 也是 HTML 结构中不可获取的一部分。而关键字决定了你是否会被搜索引擎检索到。百度谷歌等搜索引擎想必大家的生活都已经离不开了吧。而网页视角则描述了用户从何种角度看一个网页。当然,作为一个完整的网页,最好还是有一些说明信息。那么,本节我们从四个知识点上来深入学习。首先是学习什么是网页头部信息,进而学习给网页添加关键字,然后学习一下什么叫网页视角,最后我们来学习给网页添加说明信息。
把上面测试实例中的 get() 方法换成 load() 方法。且运行实例:Student stu=null;try{ // 打开事务 transaction = session.beginTransaction(); //查询学号为1的学生 stu=(Student)session.load(Student.class, new Integer(1)); System.out.println("--------------输出学生信息------------------"); System.out.println(stu.getStuName()); transaction.commit();} catch (Exception e) { transaction.rollback();} finally { session.close();}System.out.println("***********关闭Session之后******************");System.out.println(stu.getStuName());控制台上查看实例使用结果:--------------输出学生信息------------------Hibernate: selectstudent0_.stuId as stuId1_0_0_,student0_.stuName as stuName2_0_0_,student0_.stuPassword as stuPassw3_0_0_,student0_.stuPic as stuPic4_0_0_,student0_.stuSex as stuSex5_0_0_ fromStudent student0_ wherestudent0_.stuId=?Hibernate是老大***********关闭Session之后******************Hibernate是老大得到什么结论了吗?现在开始寻找区别。不仔细观察,会误判没有什么区别。而其中有一个很明显的区别就是:调用 load ( ) 方法时,Hiberante 并没有真正的行动,只有当执行到下面代码时:System.out.println(stu.getStuName());Hibernate 才从容不迫地构建 Sql 语句,往数据库跑了一趟,获得数据,再输出数据。OK!再稍微改动一下测试代码://会话对象Student stu=null;try { // 打开事务 transaction = session.beginTransaction(); //查询学号为1的学生 stu=(Student)session.load(Student.class, new Integer(1)); transaction.commit();} catch (Exception e) { transaction.rollback();} finally { session.close();}System.out.println("***********关闭Session之后******************");System.out.println("--------------输出学生信息------------------");System.out.println(stu.getStuName());输出学生信息并不是在调用 load( ) 方法之后,而是关闭 Session 对象之后,结果又会怎样?猜得出来吗?把你心中的猜想和下面的输出结果比较一下。没想到吧,抛异常啦,抛异常没什么大惊小怪的,异常是为了告诉你错误原因。查看异常信息,从中找出原因:org.hibernate.LazyInitializationException: could not initialize proxy - no Sessionat org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)省略其它若干……不要望而生畏,都是纸老虎。找出关键词:could not initialize proxy - no Session初看字面意思:不能初始化代理,没有 Session 对象。什么意思?到了好好解释这个原因的时候:调用 load( ) 方法时,Hibernate 根本没有如你所期望一样,往数据库跑。但是又不想让你知道它没去,或是怕你担心它是否能完成这份工作。于是 Hibernate 为你提供了一个 代理对象。这里会涉及到代理设计模式!为不影响主题学习,代理设计模式相关内容自己了解一下。什么是代理对象?通俗讲就是说外观和开发者所期望的对象一样,但没有实质性数据。再通俗点,就是一个替身。有其外形,而无内涵。再通俗讲:哦,你已经明白了。Hibernate 这是演的哪一出?这不是摆明欺负人吗?别误会,这是 Hibernate 的善意之举!善意从何谈起呀!别急!只有当开发者真正需要数据时:System.out.println(stu.getStuName());Hibernate 才会构建 Sql 语句,往数据库跑一趟,获得真正的数据。但是,执行 Sql 语句是一定要在 Session 的生命周期之内,如果:session.close();通往数据库的桥梁被拆了。Hibernate 也无能为力,只能以异常的方式告诉你:no Session!臣妾做不到呀。测试 get()、load() 方法的输出结果已经表明了两者的差异性:get() 方法言行一致,说出手呀便出手。开发者一调用,便快马加鞭,从数据库中获得数据,保存到学生对象中,只要学生对象在,数据也就在;load() 方法,看起来倒像是说一套,做一套的主。并不会立马行事,而是创建一个学生代理对象,提供和开发者期待的学生数据对象相同的方法接口,不影响开发者调用。只有当开发者真正需要数据时,才会说,好的,我去看一下数据库。故而,使用 load() 时就需要特别注意,在 Hibernate 取数据库之前,千万别关闭通向数据库的桥梁:Session 对象。Session 家里有 2 个可用于查询的兄弟:get() 是老实人,言行一致。load() 有点小调皮,有时搞点恶作剧,但心思并不坏。如果真正理解它的意图,在特定的环境下,可能会感动到你。其实两兄弟都很有趣。
使用 CDN 的方式引入Vue更加方便、快捷。以下推荐几个比较稳定的 CDN。https://cdn.staticfile.org/vue/2.2.2/vue.min.jshttps://unpkg.com/vue/dist/vue.jshttps://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.jshttps://cdn.jsdelivr.net/npm/vue/dist/vue.js528
hasNext()方法的返回值是一个布尔类型,如果输入中包含数据的输入,则返回true。否则返回false。通常用来做输入内容的验证。它的同伴方法是以hasNext单词开头的方法,诸如hasNextLine()、hasNextInt()等方法。例如,上面的代码中,我们可以对应加入hasNext同伴方法结合条件判断语句,来提升代码的稳定性:int age;if (scanner.hasNextInt()) { age = scanner.nextInt();} else { System.out.println("不是int类型");}float height;if (scanner.hasNextFloat()) { height = scanner.nextFloat();} else { System.out.println("不是float类型");}
微前端 尚处在发展时期,其核心概念和 微服务 相似。现阶段较为常用的微前端框架为 single-spa 和 qiankun,后者是基于前者实现的。该技术能做到 技术栈无关,即一个应用,能由多个不同技术的子应用构成,同时做到子应用的相互隔离,这里的隔离就可以选择采用 Web Components 实现。
现实世界中的实体有属性和行为,下面的表格列举了特朗普和成龙的属性和行为:对象属性行为特朗普姓名、年龄自我介绍成龙姓名、年龄自我介绍行为又被称为方法,它是对属性的操作,包括读取操作和修改操作。例如,在特朗普的自我介绍行为中,会读取他的属性:姓名和年龄。
首先去 Nginx 的官方下载地址下载最新 Nginx 的安装包 ,目前而言,选择稳定版是一种比较好的策略。在主线版本中新增的功能普通程序员用不到,此外新开发的版本还存在一些 bug ,并不稳定。因此,我们选择 1.16.1 版本的 Nginx 进行实验。
使用NPM的方法进行安装需要先在本地安装Node环境。3.1、Windows 上安装 Node.js32 位安装包下载地址64 位安装包下载地址下载对应的安装包后,双击安装包,傻瓜式下一步安装就好了。3.2、Mac 上安装 Node.js1、在官方下载网站下载 pkg 安装包,直接点击安装即可。2、使用 brew 命令来安装:brew install nodebrew install node# 查看本地node环境$ node -vv10.16.0在用 Vue 构建大型应用时推荐使用 NPM 安装。当然,仅仅使用npm install是不能完整搭建Vue开发环境的。还需要webpack或 Browserify 等模块打包器配合使用。# 创建项目目录$ mkdir demo# 进入项目文件夹$ cd demo$ npm init -y# 最新稳定版$ npm install vue# 安装指定版本Vue$ npm install vue@2.6.3安装完成后可以查看到demo目录下多了 node_module/vue 文件夹。说明Vue成功安装。
1. 独立的页面维护了全局 错误码错误码由5位整数构成2. 每个接口一个独立的 参数说明页面正常情况下出参只返回业务实体异常情况才有 errCode errMsg每个接口下也可能有自己的业务错误码
上述模板中的表单数据提交至 Student\addPost 方法中,方法定义如下: public function addPost() { try { $studentModel = new StudentModel(); $studentModel->name = $this->request->param('name', ""); $studentModel->age = $this->request->param('age', 0, 'intval'); $studentModel->id_number = $this->request->param('id_number', ''); $studentModel->save(); } catch (\Exception $exception) { return $this->error($exception->getMessage()); } return $this->success('请求成功'); }如下图所示:Tips:学生信息添加成功就会录入到数据库中。
希尔排序又叫缩小增量排序,它是基于插入排序的改进算法,相比插入排序更加高效,但是属于不稳定算法,而插入排序则是一种稳定算法。希尔排序的基本思想是将待排序元素进行增量分组,然后在分组组内进行插入排序,随着增量的减少,每个分组组内的元素越来越多,直至增量减至1时,所有元素都分到同一个组内,执行插入排序后完成整个排序操作。希尔排序通过这种策略使得整个数组在初始阶段达到从宏观上看基本有序,小的基本在前,大的基本在后。然后缩小增量,到增量为1时,其实多数情况下只需微调即可,不会涉及过多的数据移动。
咱们打开新浪微博,然后随便找个带皇冠的,按下F12键(Mac用户按command+option+i)然后选中控制台的箭头,再点击皇冠:再点开这个图片可以发现:可以看到那些大 V 图标皇冠图标以及各种微博认证等图标,都是放在了一张雪碧图里(即使再牛的大 V,身份标志也是放在雪碧图中的)。
而移动端的宽高比刚好相反,手机通常都是竖着的,只有在看电影电视剧或者玩游戏的时候才会横过来,甚至有许多用户直接锁定了竖屏,即使横过来手机也不会发生任何变化。这就导致了移动端与 PC 端的布局有很大的不同,移动端是宽太窄了,通常只能容纳一个列(横行竖列),但是高却很长,尤其是现在的全面屏,让人感觉屏幕超级长,这时候就可以在行(横行竖列)上动手脚了,比较常见的一种布局是上面一行和下面一行固定在屏幕的 header 和 footer,它们并不会随着屏幕的滚动而移动,类似于这样:微信几乎是大家最熟悉的软件了,没有了它就相当于没有了社交,在这样一款用户及其庞大的软件上就运用了移动端最经典的布局。滑动好友列表最上面的灰色那栏并不会移动:同理,下面的那栏控制着微信的会话、通讯录、朋友圈以及设置等重要功能,它也不会被移动:将此种布局稍微抽象一下就能得出这样的一张图:最上面的那行通常被称为 header,最下面的通常被称为 footer,很好理解,头和脚嘛!
在讲解方法区内存放的数据之前,我们先通过示意图来直观的看下,方法区存放的数据与堆内存之间的关系。如下图所示:从图中可以看到,方法区存放了 ClassLoader 对象的引用,也存放了一个到类对象的引用,这两个引用的对象实例会存放到堆内存中。从上图我们就可以简单的了解到方法区存放的数据是什么,接下来,我们对存放的数据类型进行解释。类型全限定名:全限定名为 package 路径与类名称组合起来的路径;类型的直接超类的全限定名:父类或超类的全限定名;类型是类类型还是接口类型:判定当前类是 Class 还是接口 Interface;类型的访问修饰符:判断修饰符,如 pulic,private 等;类型的常量池:这部分会在下文进行讲解;字段信息:类中字段的信息;方法信息:类中方法的信息;静态变量:类中的静态变量信息;一个到类 ClassLoader 的引用:对 ClassLoader 的引用,这个引用指向对内存;一个到 Class 类的引用:对对象实例的引用,这个引用指向对内存。
本节我们用 Toast 实现一个“农药”提示,有两个 Button,点击会触发一个短暂的消息提示。代码比较简单,首先在布局中加入两个 Button:<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:padding="10dp" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/dont_wave" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="猥琐发育,别浪" /> <Button android:id="@+id/hold_on_we_can_win" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="稳住,我们能赢" /></LinearLayout>接着在 Java 代码中注册监听器,在点击不同 Button 的时候弹出不同的 Toast 提示信息:package com.emercy.myapplication;import android.app.Activity;import android.os.Bundle;import android.view.Gravity;import android.view.LayoutInflater;import android.view.View;import android.widget.LinearLayout;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity implements View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.dont_wave).setOnClickListener(this); findViewById(R.id.hold_on_we_can_win).setOnClickListener(this); } @Override public void onClick(View v) { showToast(((TextView) v).getText().toString()); } private void showToast(String text) { LinearLayout layout = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.toast, null); TextView textView = layout.findViewById(R.id.text); textView.setText(text); Toast toast = new Toast(this); toast.setView(layout); toast.setDuration(Toast.LENGTH_SHORT); toast.setGravity(Gravity.TOP, 0, 500); toast.show(); }}可以看到在创建 Toast 之后,通过setView方法设置了一个 LinearLayout 类型的 View 对象。通过这种方式就可以自定义一个展示样式,最后编写 Toast 的布局样式代码:<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:gravity="bottom" android:layout_height="match_parent" android:orientation="horizontal"> <ImageView android:layout_width="50dp" android:layout_height="50dp" android:src="@mipmap/mc" /> <TextView android:id="@+id/text" android:layout_marginLeft="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="30sp" /></LinearLayout>XML 文件中我们横向放置了一个图片和一个文本,对应的是游戏人物和提示语,然后在点击的时候弹出此样式的 Toast。最终编译运行效果如下:
Nginx 的进程模型采用了 Master/Workers 进程池的机制,即通常情况下,Nginx 会启动一个 Master 进程(当然,也可以无 master 进程)和多个 Worker 进程对外提供服务。Master 进程是监控进程,本身并不处理具体的 TCP 和 HTTP 请求,只负责接受 UNIX 信号,管理 Worker 进程,类似于工地的包工头。Worker 进程是比较累的,负责处理客户端的连接请求,它充分利用了 Linux 系统中的 epoll、kqueue 等机制,高效处理 TCP 和 HTTP 请求,利用这些特点,Nginx 充分挖掘了服务器的潜能,让服务器更快响应用户请求。一般情况下,10000 个非活跃的 HTTP Keep-Alive 连接在 Nginx 中仅仅消耗 2.5M 内存,这是 Nginx 支持高并发连接的基础,体现了 Nginx 高性能的特点。另外,由于官方提供的模块都非常稳定,每个 Worker 进程都相对独立,Woker 进程出错时,Master 进程会立马感知到并快速拉起新的 Worker 子进程不间断提供服务,保证服务的稳定性。nginx的进程模型
下面定义一下路由里面指向的 getStudent() 方法,方法如下: // 获取单个学生信息 public function getStudent() { $student_id = (int)$this->request->param('student_id'); if (!$student_id) { return json('参数不合法', 404); } //查询单条数据 $student = StudentModel::where('id', $student_id)->where('status', 1)->find(); if (empty($student)) { return json('学生信息不存在', 404); } //把时间戳转化为可读的日期格式 $student->created_at = date("Y-m-d H:i", $student->created_at); return json($student); }Tips: 其中 where('id',$student_id) 表示使用 id=$student_id 查询,find() 方法表示查询单条。
本小节我们学习了 measureText 方法 , 它们是 canvas 2D API 提供的获取绘制文本的相关属性的方法,该方法返回一个 TextMetrics 对象,该对象包含关于文本尺寸的信息,里面就有文本宽度。
字段表后边紧跟的是方法表计数器,方法表计数器后边紧跟的是方法表。定义:方法表计数器(methods_count)与方法表不可分割,这里我们对两部分结构一起讲解。方法表计数器(methods_count):记录方法表中字段的数量,为无符号数类型。方法表(methods):存储了当前类或者当前接口中的 public 方法,protected 方法,default 方法,private 方法等。方法表为表结构类型。Tips:Class文件是通过Java文件编译而来的,如果文件中有方法,就会将方法的信息存储到方法表,并通过方法表计数器进行方法的计数。方法表计数器无符号数结构示意图:与其他计数器一样,方法表计数器(methods_count)是一个无符号数结构类型的数据,u2 大小。方法表-表结构类型示意图:方法表是一个表结构的类型数据,与前文所讲解的字段表结构一样。一个method_info中会存储很多方法的特征值,我们通过如下示例方法进行举例:public String get(String name) { return "";}对于get 方法,method_info 中会存储如下信息:方法的修饰符 public:还记的我们上节所讲述的 access_flag 吗?access_flag 对应表中有一个 ACC_PUBLIC 就代表了 public 修饰符,他对应的值为 0x0001,此处的标记也需要使用到这个表。都是通用的哦;方法名称:get 方法;方法的参数:String name;方法的返回值类型: String 类型的返回值。通过如上方法特征值的共同修饰,完成了一个 method_info 的存储,也就完成了一个方法的存储。
Ruby 提供了一种组织代码并重用的功能,它可以让我们无需创建冗长的 Ruby 代码,在需要它们的时候才会使用它们。对于方法,您只需要学会方法的声明、调用以及传参即可。在本章中会为您详细介绍方法的使用。
上一节我们介绍了「密码认证」的实现方法,本节我们讨论如何通过 OAuth2.0 方式直接从第三方机构获取用户身份信息的方法。OAuth(开放授权)是一个开放标准,允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容,OAuth2.0 是 OAuth 协议的延续版本,但不向后兼容 OAuth1.0 即完全废止了 OAuth1.0。除了自建认证中心外,常用的互联网 OAuth2.0 认证中心还包括:QQ、微信、微博、Github 等,例如 imooc.com 的登录选项里,我们能看到「微博登录」、「微信登录」和「QQ 登录」,这些其实就是对 OAuth2.0 认证的应用。慕课网登录页面 /center>本节将以 Github 作为第三方认证中心为例,讨论如何使用 Spring security 实现 OAuth2 登录的功能。本节开发环境JDK 1.8Maven 3.5.3 依赖项:spring-security-config:5.3.2.RELEASEspring-security-oauth2-client:5.3.2.RELEASEspring-security-oauth2-jose:5.3.2.RELEASEspring-boot-starter-thymeleaf:2.3.0.RELEASEspring-boot-starter-web:2.3.0.RELEASEthymeleaf-extras-springsecurity5:3.0.4.RELEASE
上面我们已经大概了解了什么是 HTTP 协议,简单来说就是客户端与服务端用来通信的协议,HTTP 协议中规定和很多 HTTP 方法来让我们根据不同的需求向服务端发起请求。下面我们通过一个具体的例子,说明如何在 Flask 中使用不同的 HTTP 方法:from flask import Flask, requestapp = Flask(__name__)首先,导入类 flask.Flask 和 flask.request,request 封装了请求消息,可以获取请求的各种参数。@app.route('/login', methods = ['GET'])def login(): return '''<form action="/check_login" method="POST"> <p><input type="text" name="name"/></p> <p><input type="password" name="password"/></p> <p><input type="submit" value="submit"/></p></form>'''定义处理路径 /login 的函数 login,装饰器 @app.route(’/login’, methods = [‘GET’]) 表示使用 GET 方法处理路径 /login 的请求。函数 login 返回一段用于登录的 HTML 表单,表单包括 2 个字段: name 和 password。在第 4 行,指定使用 POST 方法提交表单给服务端的 /check_login 页面。@app.route('/check_login', methods = ['POST'])def check_login(): name = request.form['name'] password = request.form['password'] if name == 'guest' and password == '123': return 'Login succeed' else: return 'Login failed'定义处理路径 /check_login 的函数 check_login,装饰器 @app.route(’/check_login’, methods = [‘POST’]) 表示使用 POST 方法处理路径 /check_login 的请求。函数 check_login 根据请求的参数 name 和 password 是否正确,返回给用户相应的信息。在第 3 行,提取参数 name 的值,在第 4 行,提取参数 password 的值。如果 name 是 guest,password 是 123,则返回登录成功消息,否则返回登录失败消息。if __name__ == '__main__': app.run()调用 app.run() 运行程序。用户在浏览器中输入 http://localhost:5000/login,浏览器显示:用户输入正确的 name 和 password 后,浏览器跳转到页面 http://localhost:5000/check_login,显示:
在现实世界中,具体的实体被称为对象,观察这些对象的属性和行为,发现可以使用相同的特征去描述一类对象。例如:对象属性和行为美国总统特朗普姓名、年龄、工作中国明星成龙姓名、年龄、工作上海中心大厦高度、业主、维护北京中信大厦高度、业主、维护可以使用 “姓名、年龄、工作” 等特征去描述特朗普和成龙这一类对象,使用 “高度、业主、维护” 等特征去描述上海中心大厦、北京中信大厦这一类对象。在编程领域,类是对一组具有相同属性和行为的对象的抽象。例如, “人” 是一个抽象的概念,它是一个类或者类别,描述了具有 “姓名、年龄、工作” 等特征的一组对象;“楼” 是一个抽象的概念,它是一个类或者类别,描述了具有 “高度、业主、维护” 等特征的一组对象。
信息的搜集往往不是单一的,是由类似上面列举的很多方式的组合。我们经常听到一个词 人肉搜索,大家都很惊讶网络神人技术太强,其实主要还是因为我们散布在网上的资料信息太多了。这些零碎的资料拼一拼还是能获得很全的信息的。搜索引擎随便输入你的名字,或者外加几个关键词可能查到你在哪所学校,参加了某某活动,获得了某某名次的奖励你在哪所公司,缴交的一些社保信息你在某个网站的评论根据你的昵称到 QQ 上面搜索,同一个昵称到处用概率还是很大的,如果有手机号那就更加准确了,紧接着可以根据你的 QQ 空间获取更多你私人的信息。(这以前是非常好查的,现在腾讯也一直在完善信息安全这块)也可能是到其他平台去搜索:微博,头条,人人网,58同城 等照片网上搜索相似百度搜索引擎就有根据图片搜索到功能到政府的一些网站,如 信用xx ,上面根据法人名字也能搜索不少有价值的东西。
/** * 获取用户 SESSION 和 COOKIE 信息 */ public function userinfo(){ halt(["cookie"=>cookie("user_info"),"session"=>session("user_info")]); }登录界面如下图所示用户信息如下图所示: