为了账号安全,请及时绑定邮箱和手机立即绑定
新浪微博

咱们打开新浪微博,然后随便找个带皇冠的,按下F12键(Mac用户按command+option+i)然后选中控制台的箭头,再点击皇冠:再点开这个图片可以发现:可以看到那些大 V 图标皇冠图标以及各种微博认证等图标,都是放在了一张雪碧图里(即使再牛的大 V,身份标志也是放在雪碧图中的)。

4. 模板方法模式

模板方法模式是定义一个操作中的算法的骨架,从而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。通常对于一些重要的复杂方法和多个子类共有的方法且逻辑相同的情况下会使用模板方法模式。比如用户第三方用户认证的时候就比较适合使用模板方法。我们来看一个例子:假设我们现在需要用到微信、微博的第三方用户授权来获取用户的信息。//使用模板方法模式描述获取第三方用户信息的过程 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(); }输出结果:获得微信用户授权 获取微信用信信息 获得微博用户授权 获取微博用信信息此时,我们的模板方法得到了大幅的简化,同时通过函数接口让模板方法获得了极大的灵活性。

3.1 打包为微信小程序

注册微信小程序账号,获取到 AppID,我们后面配置的时候会用到。在 HBuilderX 工具栏,点击发行,选择小程序-微信。输入小程序名称和 AppID,单击发行就可以了。这样我们就会获得一个微信小程序的打包文件,接下来我们来发布微信小程序项目,打开微信小程序开发者工具,导入刚刚生成的微信小程序项目的打包文件,在微信小程序开发者工具中先测试一下,项目运行是否正常,项目测试没有问题后,点击右上角>>按钮,上传代码就可以发布微信小程序了,最后等待微信团队审核通过,别人就可以在线上访问到你的项目了。

3.1 微信小程序 API

uni-app 的 API 与微信小程序 API 基本一致。掌握微信小程序 API 对后面的开发很有帮助。微信小程序 API 文档:https://developers.weixin.qq.com/miniprogram/dev/api/

5. 信息综合搜索

信息的搜集往往不是单一的,是由类似上面列举的很多方式的组合。我们经常听到一个词 人肉搜索,大家都很惊讶网络神人技术太强,其实主要还是因为我们散布在网上的资料信息太多了。这些零碎的资料拼一拼还是能获得很全的信息的。搜索引擎随便输入你的名字,或者外加几个关键词可能查到你在哪所学校,参加了某某活动,获得了某某名次的奖励你在哪所公司,缴交的一些社保信息你在某个网站的评论根据你的昵称到 QQ 上面搜索,同一个昵称到处用概率还是很大的,如果有手机号那就更加准确了,紧接着可以根据你的 QQ 空间获取更多你私人的信息。(这以前是非常好查的,现在腾讯也一直在完善信息安全这块)也可能是到其他平台去搜索:微博,头条,人人网,58同城 等照片网上搜索相似百度搜索引擎就有根据图片搜索到功能到政府的一些网站,如 信用xx ,上面根据法人名字也能搜索不少有价值的东西。

1. 前言

上一节我们介绍了「密码认证」的实现方法,本节我们讨论如何通过 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

1. 前言

有些同学乍一听九宫格可能不知道是什么,但其实它在我们的日常生活中很常见:顾名思义,九宫格通常为如图这种三行三列的布局。微信客户端就用到了这种布局方式:大家最熟悉的朋友圈也采用了九宫格:还有微博:

3. 线程的使用方法

Java 虚拟机支持多线程并发编程,并发意味着同时执行多个任务。在 Android 中常见的多线程常见就是在子线程执行耗时操作,然后将结果通过线程间通信传递给主线程,主线程仅仅拿到结果进行 UI 的刷新。

1. 开篇词

据不完全统计(其实就统计了自己身边的朋友和同事),在刨除抖音或快手这一类短视频 APP 后,每天在手机上花费时间最长的就是刷微博和逛朋友圈。在刷微博和逛朋友圈的时候经常会看到这种东西:它有一个高大上的名字:九宫格。它在移动端的运用十分的广泛,而且不仅仅是在移动端的运用,它甚至还运用到了一些面试题中,因为九宫格可以很好的考察面试者的 CSS 功底。有些同学可能觉得九宫格看上去非常的简单,但实际上一些边框问题却还是很考验人的。借助市面上已有的 CSS 库,我们可以很轻易的做到九宫格布局,尤其是可以用到中文关键字,这非常有利于我们的记忆,它就是 chinese-layout。然后我们再用一个中文渐变色的CSS库来美化我们的界面:chinese-gradient。

3. 热门商品排行榜

如果是大型网站,时刻有很多用户在访问网页,对热门商品排行榜的访问频率是非常恐怖的。我们可以通过定时器,定时从关系数据库中取出热门商品数据放入 Redis 缓存,用户访问网页时,直接从缓存中获取热门商品数据。这将大大提高响应速度,并降低对关系数据库的性能损耗。

4.2 测试效果

点击工具栏–运行–运行到内置浏览器,测试H5平台。点击工具栏–运行–运行到小程序模拟器–微信开发者工具,测试微信小程序平台。

5.2 测试效果

点击工具栏–运行–运行到内置浏览器,测试H5平台。点击工具栏–运行–运行到小程序模拟器–微信开发者工具,测试微信小程序平台。

3. 热部署

支持热部署功能是 Nginx 的一个特色,许多大型门户网站要求 24 小时不间断提供服务,一旦出现服务停止,容易造成用户投诉和用户流失。Nginx 由于其管理进程和 Worker 进程的分离设计,使得其能提供热部署功能,满足大型站点在 7x24 小时不间断服务的前提下升级 Nginx。但要注意的是,Nginx 并不支持在不停止服务的情况下就更新配置、更换日志文件等功能。Nginx 的热部署实现原理是,在不停止老进程的前提下,终止其连接请求,并启动新的 Worker 进程处理新进来的连接请求,再慢慢终止老的 Worker 进程,实现新老交替。

2.1 微框架

Flask 是一个 Python 实现的 Web 开发微框架,但是这个“微”并不代表着 Flask 功能比较简陋、有所欠缺。微框架中的 “微” 意味着:Flask 旨在保持核心简单而易于扩展;Flask 不会替用户做出太多决策,比如使用何种数据库;Flask 的选项(比如使用何种模板引擎) 通常有多个,用户很容易替换。默认情况下,Flask 不包含数据库抽象层、模板引擎、身份认证或其它任何已有多种库可以胜任的功能,如下图所示。然而,Flask 支持用扩展来给应用添加这些功能,应用程序可以很方便的集成这些扩展。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。

2. Java 多线程编程方法

由于本节会涉及到 Java 多线程编程,所以需要你能预先掌握 Java 多线程编程的方法。比如,线程的创建,线程的启动,线程之间的同步和线程之间的通信。在 Java 平台下,创建线程的方法有两种:第一,是创建一个用户自定义的线程类,然后继承 java.leng.Thread 类,同时要覆写它的 run 方法,调用它的 start 方法启动线程。例如:class MyThread extends Thread{ @Override public void run() { super.run(); }}new MyThread().start();第二,是创建一个任务类。首先,实现 Runnable 接口,并且重写它的 run 方法。然后,创建 java.leng.Thread 类的对象,同时将 Runnable 的实例通过 java.lang.Thread 的构造方法传入。最后,调用 java.lang.Thread 的 start 方法启动线程。例如:class MyTask implements Runnable{ @Override public void run() { }}new Thread(new MyTask()).start();

1. 前言

上一小结谈到了操作系统中进程和线程的区别,其中进程之间、线程之间的通信方式不同,进程通信(Inter-Process Communication,简称 IPC)是指不同进程之间交换信息。操作系统中时刻都在进行 IPC,例如微信读取本地的文件,就是微信程序和文件系统进程交互的过程。

1.2 简单编码的独热化

这种编码和上述编码方式一样,只是进行了一些独热化处理,因为独热化处理能够让模型在分类任务上拥有更好的性质。比如上述的例子:s = "How are you"按照独热编码可以看作是:"How" = [1, 0, 0]"are" = [0, 1, 0]"you" = [0, 0, 1]虽然独热编码具有更好的性值,但是它仍然没有解决上面的问题,也就是说它依然无法表示两个单词之间的关系。不仅如此,它还引入了新的问题:存储空间开销巨大。因为每个单词的存储大小都是一个所有词汇量大小的一个数组。

2.1 微前端

微前端 尚处在发展时期,其核心概念和 微服务 相似。现阶段较为常用的微前端框架为 single-spa 和 qiankun,后者是基于前者实现的。该技术能做到 技术栈无关,即一个应用,能由多个不同技术的子应用构成,同时做到子应用的相互隔离,这里的隔离就可以选择采用 Web Components 实现。

2. 效果展示

这种布局是主内容处于页面的正中央位置,常见于登录、注册、提示用户、或点击头像查看大图等场景: 除了上图那样为了美观而添加的白色透明遮罩,还有一种是为了突出主题,添加的是一层灰色的透明遮罩: 图片来源 微博这么做的目的除了突出主题之外,还有一个比较重要的点就是可以令用户感觉到自己并没有离开当前页面,只不过是在当前页面中出现了一个小框而已,这样可以有效减少用户的陌生感。 图片来源 慕课网@imooc不仅如此,居中布局还能够有效引导用户进行自己希望用户所进行的操作,用强烈的对比感去引导用户: 图片来源 慕课网@imooc

4.2 微信

1. 独立的页面维护了全局 错误码错误码由5位整数构成2. 每个接口一个独立的 参数说明页面正常情况下出参只返回业务实体异常情况才有 errCode errMsg每个接口下也可能有自己的业务错误码

6. synchronized 作用于静态方法

Tips:对于 synchronized 作用于静态方法,锁为当前的 class,要明白与修饰普通方法的区别,普通方法的锁为创建的实例对象。为了更好地理解,我们对第 5 点讲解的代码进行微调,然后观察打印结果。代码修改:其他代码不变,只修改如下部分代码。新增创建一个实例对象 testNew ;将线程 2 设置为 testNew 。public static void main(String[] args) throws InterruptedException { DemoTest test = new DemoTest(); DemoTest testNew = new DemoTest(); Thread t1 = new Thread(test); Thread t2 = new Thread(testNew); t1.setName("threadOne"); t2.setName("threadTwo"); t1. start(); t2. start(); }结果验证:threadTwo 获取到锁,其他线程在我执行完毕之前,不可进入。threadOne 获取到锁,其他线程在我执行完毕之前,不可进入。threadTwo: 1threadOne: 2结果分析:我们发现 threadTwo 和 threadOne 同时进入了该方法,为什么会出现这种问题呢?因为我们此次的修改是新增了 testNew 这个实例对象,也就是说,threadTwo 的锁是 testNew ,threadOne 的锁是 test。两个线程持有两个不同的锁,不会产生互相 block。相信讲到这里,同学对实例对象锁的作用也了解了,那么我们再次将 increase 方法进行修改,将其修改成静态方法,然后输出结果。代码修改:public static synchronized void increase() throws InterruptedException { System.out.println(Thread.currentThread().getName() + "获取到锁,其他线程在我执行完毕之前,不可进入。" ); sleep(1000); count++; System.out.println(Thread.currentThread().getName() + ": " + count); }结果验证:threadOne获取到锁,其他线程在我执行完毕之前,不可进入。threadOne: 1threadTwo获取到锁,其他线程在我执行完毕之前,不可进入。threadTwo: 2结果分析:我们看到,结果又恢复了正常,为什么会这样?关键的原因在于,synchronized 修饰静态方法,锁为当前 class,即 DemoTest.class。public class DemoTest extends Thread {}无论 threadOne 和 threadTwo 如何进行 new 实例对象的创建,也不会改变锁是 DemoTest.class 的这一事实。

4. 小结

本节我们讨论了如何利用第三方平台做我们系统的 OAuth2.0 认证中心,主要的知识点如下:Spring Security 实现了 OAuth2.0 客户端的常用功能,开发者可以轻松的将 Spring Boot 应用作为 OAuth2.0 客户端集成到安全体系中;在使用第三方作为 OAuth2.0 认证服务器时,首先要在第三方平台上完成应用注册,并获取到 Client ID 和 Client Secret 两个重要参数;使用第三方 OAuth2.0 认证源,可以简化系统开发中的关于认证的操作,并且可以更轻易的实现单点登录;使用第三方 OAuth2.0 认证源的时候,用户在本系统内的权限、详细用户信息等,仍需要在本地系统内维护;目前在国内支持度比较好的第三方认证源有:QQ、微信、微博、Github 等。下一节中,我们继续在 OAuth2.0 协议的基础上,构造出属于自己的认证中心。

2.7 测试监控效果

启动客户端程序,然后刷新服务端网页,会发现监控管理页面已经显示了客户端信息。监控页面展示客户端信息此时我们关闭客户端程序,然后稍等一会刷新下监控管理页面(注意服务端发现客户端离线是需要一定时间的),会发现监控管理页已经显示了离线项目实例信息。监控页面展示离线客户端信息

1. 今日头条热点新闻数据抓取分析

今天的爬取对象是今日头条的热点新闻,下面的视频演示了如何找到头条新闻网站在获取热点新闻的 HTTP 请求:81从视频中我们可以看到头条新闻获取网站的接口示例如下:https://www.toutiao.com/api/pc/feed/?category=news_hot&utm_source=toutiao&widen=1&max_behot_time=1597152177&max_behot_time_tmp=1597152177&tadrequire=true&as=A1955F33D209BD8&cp=5F32293B3DE80E1&_signature=_02B4Z6wo0090109cl1gAAIBCcqbHy0H-dDdPWZPAAIzuFTZSh6NBsUuEpf13PktqrmxS-ZD4dEDZ6Ezcpyjo31hg62slsekkigwdRlS0FHfPsOvx.KRyeJBdEf5QI8nLcwEMyziL1YdPK6VD8f像这样的 http 请求时比较难模拟的,我们需要知道请求中所有参数的获取规则,特别是一些进行加密的方式,需要从前端中找出来并手工实现。比如这里的 URL,前几个参数都是固定值,其中 as、cp 和 _signature 则非常难获取,需要有极强的前端功底,网上也有大神对这些值的生成进行了分析和解密,当然这些不是我们学习的重点。最后一个问题:一次请求得到10条左右的新闻数据,那么像实现视频中那样更新更多新闻的请求,该如何完成呢?仔细分析下连续的刷新请求,我们会发现上述的 URL 请求结果中有这样一个参数:max_behot_time。第一次请求max_behot_time值为0next中的max_behot_time等于最后一条数据的behot_time值关于这个参数,我们得到两条信息:第一次请求热点新闻数据时,该参数为0;接下来的每次请求,带上的 max_behot_time 值为上一次请求热点新闻数据结果中的 next 字段中的 max_behot_time 键对应的值。它表示的是一个时间戳,其实就是意味着请求的热点新闻数据需要在这个时间之后;有了这样的信息,我们来基于 requests 库,纯手工实现一把头条热点新闻数据的抓取。我们按照如下的步骤来完成爬虫代码:准备基本变量,包括请求的基本 URL、请求参数、请求头等;hotnews_url = "https://www.toutiao.com/api/pc/feed/?"params = { 'category': 'news_hot', 'utm_source': 'toutiao', 'widen': 1, 'max_behot_time': '', 'max_behot_time_tmp': '',}headers = { 'referer': 'https://www.toutiao.com/ch/news_hot/', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36'}cookies = {'tt_webid':'6856365980324382215'} max_behot_time = '0'注意:上面的 cookies 中的 tt_webid 字段值可以通过右键看到,不过用处不大。tt_webid值的获取准备三个个方法:get_request_data() 、get_as_cp() 和 save_to_json()。其中第二个函数是网上有人对头条的 js 生成 as 和 cp 参数的代码进行了翻译,目前看来似乎还能使用;def get_request_data(url, headers): response = requests.get(url=url, headers=headers) return json.loads(response.text)def get_as_cp(): # 该函数主要是为了获取as和cp参数,程序参考今日头条中的加密js文件:home_4abea46.js zz = {} now = round(time.time()) e = hex(int(now)).upper()[2:] a = hashlib.md5() a.update(str(int(now)).encode('utf-8')) i = a.hexdigest().upper() if len(e) != 8: zz = {'as':'479BB4B7254C150', 'cp':'7E0AC8874BB0985'} return zz n = i[:5] a = i[-5:] r = '' s = '' for i in range(5): s = s + n[i] + e[i] for j in range(5): r = r + e[j + 3] + a[j] zz ={ 'as': 'A1' + s + e[-3:], 'cp': e[0:3] + r + 'E1' } return zzdef save_to_json(datas, file_path, key_list): """ 保存 json 数据 """ print('写入数据到文件{}中,共计{}条新闻数据!'.format(file_path, len(datas))) with codecs.open(file_path, 'a+', 'utf-8') as f: for d in datas: cleaned_data = {} for key in key_list: if key in d: cleaned_data[key] = d[key] print(json.dumps(cleaned_data, ensure_ascii=False)) f.write("{}\n".format(json.dumps(cleaned_data, ensure_ascii=False)))最后一步就是实现模拟刷新请求数据。下一次的请求会使用上一次请求结果中的 max_behot_time 值,这样能连续获取热点新闻数据,模拟头条页面向下的刷新过程;# 模拟向下下刷新5次获取新闻数据refresh_count = 5for _ in range(refresh_count): new_params = copy.deepcopy(params) zz = get_as_cp() new_params['as'] = zz['as'] new_params['cp'] = zz['cp'] new_params['max_behot_time'] = max_behot_time new_params['max_behot_time_tmp'] = max_behot_time request_url = "{}{}".format(hotnews_url, urlencode(new_params)) print(f'本次请求max_behot_time = {max_behot_time}') datas = get_request_data(request_url, headers=headers, cookies=cookies) max_behot_time = datas['next']['max_behot_time'] save_to_json(datas['data'], "result.json", key_list) time.sleep(2)最后来看看完整抓取热点新闻数据的代码运行过程,如下:82

多渲染方案,跨平台使用!

ECharts 支持以 Canvas、SVG(4.0+)、VML 的形式渲染图表。VML 可以兼容低版本 IE,SVG 使得移动端不再为内存担忧,Canvas 可以轻松应对大数据量和特效的展现。不同的渲染方式提供了更多选择,使得 ECharts 在各种场景下都有更好的表现。除了 PC 和移动端的浏览器,ECharts 还能在 node 上配合 node-canvas 进行高效的服务端渲染(SSR)。从 4.0 开始我们还和微信小程序的团队合作,提供了 ECharts 对小程序的适配!社区热心的贡献者也为我们提供了丰富的其它语言扩展,比如 Python 的 pyecharts,R 语言的 recharts, Julia 的 ECharts.jl 等等。我们希望平台和语言都不会成为大家使用 ECharts 实现可视化的限制!

ECharts 折线图

这个小节开始我们开始学习 ECharts 中的各个图形,这些图形都有着自己独特的风格,有着自己更适合的场景,在合理的场景下选择更为合适的图才能让我们的数据更好展示与分析。本节我们就先讲折线图这个稍微简单的图形。折线图用于显示数据在一个连续的时间间隔或者时间跨度上的变化,它的特点是反映事物随另一维度数值变化所产生趋势。

2. 利用 arcTo 方法绘制弧线

arcTo() 是利用两条相交切线来确定圆弧的位置,开始前我们先要搞懂切线的几个知识点。如何确定切线?我们都知道两点确定一条直线,这里两条直线相交处有一个交点,交点是两条线共用的一个点,所以我们只需要三个点就能确定两条切线。根据切线如何确定圆心?切线的性质有:(1)切线和圆只有一个公共点。(2)切线和圆心的距离等于圆的半径。(3)切线垂直于经过切点的半径。(4)经过圆心垂直于切线的直线必过切点。(5)经过切点垂直于切线的直线必过圆心。我们根据切线的垂直线必过圆心,即可确定圆心。我们来看一张图片:上图中,只要我们确定了 PA、PB 这两条切线和圆的半径 OA,即可确定 AB 这条弧线。上图中,我们沿着 OP 延长线移动 O 点的位置,即可得到半径不同的圆,也就得到了不同的 AB 弧线。到这里我们明白了:有三个点就可以确定两条切线。有圆的半径就可以确定切线间的一条弧线。arcTo 就是利用上面的原理来绘制弧线的。arcTo 方法有5个参数,前两个参数表示的是上图中 P 点的坐标,也就是切线的交点,第3个和第4个参数表示 PB 切线上的任意一个坐标点,第5个参数表示的是上图中 OA 的长度,也就是绘制圆的半径。特别注意:第3、4个参数表示的点不是切点!第3、4个参数表示的点不是切点!第3、4个参数表示的点不是切点!arcTo 方法的参数中只有两个点和一个半径,我们前面讲到要绘制弧线,必须是三个点,那第一个点哪儿去了呢?其实第一个点就是当前画布中笔触所在的位置,也就是当前画布中已经绘制的路径的终点。先看整体案例:1433运行结果:我们对上面的绘制弧线代码做拆分讲解:开始一个新路径。ctx.beginPath();确定第一个坐标点 A 点,A 点是当前已有路径的终点。ctx.moveTo(40,40);我换一个写法:ctx.moveTo(40,0);ctx.lineTo(80,40);这时候 A 点的位置就变成了 (80, 40)。 根据切线交点、第二条切线上的某个点和半径开始绘制弧线。ctx.arcTo(260,40, 260,200, 60); //调用了绘制圆的函数这里需要注意三点:(1) A 点和 PA 切线的切点会被自动连接起来,但是 PB 切线上的切点和 B点不会自动连接起来。 (2) A 点肯定在路径上,B 点不一定在路径上。(3) 切点由 canvas 自动计算。设置绘制样式以及开始描边。ctx.strokeStyle = "#456795";ctx.lineWidth = 4;ctx.stroke();我们从案例中可以看到,绘制一个圆形路径只需要调用一个函数即可,arc 方法和我们之前学过的 rect 绘制矩形的方法类似,也是绘制了一个路径,我们后续对路径的描边或者填充依然是需要调用 stroke 或者 fill 方法的。

3. 热插拔

上节我们学习了 ChannelHandler 的生命周期,其中有一个关键的方法是 handlerRemoved (),在 handler 被移除的时候触发该事件,针对该事件,其实我们可以灵活的扩展自己的业务功能。需求:客户端和服务端之间通信,必须需要先认证。实例:serverBootstrap .group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<NioSocketChannel>() { protected void initChannel(NioSocketChannel ch) { //1.登录认证Handler ch.pipeline().addLast(new LoginHandler()); //2.其他业务Handler ch.pipeline().addLast(new OtherHandler()); } });通过以上的代码,我们就能很好的解决了客户端登录认证问题,但是我们会发现,在登录认证成功之后,客户端发起其他类型请求的时候,每次请求 LoginHandler 都会被执行,那么应该怎么去解决这个问题呢?解决思路:在客户端第一次连接服务端时,进行账号认证,认证成功之后,把 LoginHandler 给移除掉。实例:public class LoginHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //1.省略了部分代码(转换ByteBuf,对象流反序列化) //2.获取Map Map<String,String> map=(Map<String,String>)iss.readObject(); //3.认证账号、密码,并且响应 String username=map.get("username"); String password=map.get("password"); if(username.equals("admin")&&password.equals("123456")){ //3.1.给客户端响应 ctx.channel().writeAndFlush(Unpooled.copiedBuffer("success".getBytes())); //3.2.移除该Handler,这样下次请求就不会再执行该Handler了 ctx.pipeline().remove(this); }else{ ctx.channel().writeAndFlush(Unpooled.copiedBuffer("error".getBytes())); ctx.channel().closeFuture(); } } @Override public void handlerRemoved(ChannelHandlerContext ctx) { System.out.println("LoginHandler被移除"); }}总结,动态新增和移除 Handler,也称之为热插拔,在真实项目开发当中其实非常的有用。

CDN 加速原理

热衷京东平台的朋友大部分是被他极致的物流体验折服的,因为京东买东西经常第二天就到了,更有甚者上午买下午就到。而同样知名的淘宝则很难做到这点,这是由于京东在全国的各个城市都有自己的仓库系统,可以做到就近配送,而淘宝上都是独立的商家,每件商品都得从原厂地发货过来。CDN 全称 Content Delivery Network 即内容分发网络,它就类似京东的物流配送体系,通过智能分配算法,让用户最近最快速的获取到他们想要访问的资源。

5. 小结

本节内容概览本小节从服务资源隔离的前提概念开始介绍,采用图文并茂的方式,详细介绍了进程和线程、Web 项目中的进程与线程、服务资源隔离产生的原因,以及服务资源隔离的概念;接着,我们采用代码实现的方式,对 Hystrix 中的线程池隔离和信号量隔离这两种实现服务资源隔离的措施进行了介绍,并对其中需要注意的地方做了补充。服务资源隔离是微服务项目治理中的最后一关,同时也是至关重要的一关,微服务项目经常由于服务没有响应而导致后续服务瘫痪,所以,掌握服务资源隔离是保证微服务项目正常运行的关键所在。

首页上一页1234567下一页尾页
直播
查看课程详情
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号